MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
lscartesiansolver.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#include "lscartesiansolver.h"
8#include <algorithm>
9#include <stack>
10#include "COMM/mpioverride.h"
11#include "COUPLER/lsfv.h"
12#include "IO/parallelio.h"
13#include "MEMORY/alloc.h"
14#include "UTIL/functions.h"
15#include "globals.h"
16
17using namespace std;
18using namespace maia;
19using namespace maia::ls;
20
21#define MAX_NO_LS_BNDRY_CND 10
22//#define LS_DEBUG
23
24//----------------------------------------------------------------------------
25
26template <MInt nDim>
27LsCartesianSolver<nDim>::LsCartesianSolver(MInt solverId_, const MBool* propertiesGroups, GridProxy& gridProxy_,
28 Geometry<nDim>& geometry_, const MPI_Comm comm)
29 : maia::CartesianSolver<nDim, LsCartesianSolver<nDim>>(solverId_, gridProxy_, comm, true), m_geometry(&geometry_) {
30 TRACE();
31
32 // set default
33 m_maxNoSets = 1;
34
35 const MLong oldAllocatedBytes = allocatedBytes();
36
37 // general levelSet activation!
38 const MBool levelSet = propertiesGroups[LEVELSET];
39
40 ASSERT(levelSet, "");
41
42 if(grid().azimuthalPeriodicity() && nDim == 2) {
43 mTerm(1, "Azimuthal periodicity is untested in 2D and it doesn't make sense in 2D!");
44 }
45
46 // leveset used for emerged moving boundaries
47 m_levelSetLb = propertiesGroups[LEVELSET_LB];
48 m_levelSetMb = propertiesGroups[LEVELSETMB] || m_levelSetLb;
49 // levelset used for combustion
50 m_combustion = propertiesGroups[COMBUSTION];
51 m_LSSolver = propertiesGroups[LS_SOLVER];
52 m_levelSetRans = propertiesGroups[LS_RANS];
53 // leveset used for the tracking of free surfaces between to fluid phases
54 m_freeSurface = (string2enum(solverMethod()) == MAIA_LEVELSET_SURFACE);
55
56 m_time = F0;
57
58 m_levelSetFv = false;
59 if((levelSet || m_levelSetRans) && !m_levelSetMb && !m_combustion && !m_LSSolver && !m_freeSurface) {
60 m_levelSetFv = true;
61 }
62
63 if(domainId() == 0) {
64 cerr << "m_levelSetMb : " << m_levelSetMb << endl;
65 cerr << "m_combustion : " << m_combustion << endl;
66 cerr << "m_LSSolver : " << m_LSSolver << endl;
67 cerr << "m_levelSetRans: " << m_levelSetRans << endl;
68 cerr << "m_levelSetFv : " << m_levelSetFv << endl;
69 cerr << "m_freeSurface: " << m_freeSurface << endl;
70 }
71
72 ASSERT(m_LSSolver || m_levelSetMb || m_combustion || m_levelSetRans || m_levelSetFv || m_freeSurface,
73 "Unintentianal-ls-solver initialisation?!");
74
75 readLevelSetProperties();
76 allocateLevelSetMemory();
77
78 if(isActive()) printAllocatedMemory(oldAllocatedBytes, "LsCartesianSolver", mpiComm());
79
80 initializeTimers();
81}
82
83
84template <MInt nDim>
86 TRACE();
87
88 ASSERT(m_LSSolver || m_combustion || m_levelSetMb || m_levelSetRans || m_levelSetFv || m_freeSurface,
89 "No valid LS mode");
90
91 // If solver inactive only mark all cells as halo cells
92 // Inactive solvers can not have internal cells
93 if(!isActive()) {
94 this->setHaloCellsOnInactiveRanks();
95 return;
96 }
97
98 grid().updateLeafCellExchange();
99
100 // Set the restart time step correctly when using useNonSpecifiedRestartFile
101 if(m_useNonSpecifiedRestartFile) {
102 m_restartTimeStep = globalTimeStep;
103 }
104
105 // Init the exchange for azimuthal periodicity
106 initAzimuthalExchange();
107
108 if(m_levelSetMb && m_constructGField) return;
109
110 if(m_restart) {
111 restartLocalizedLevelSetCG();
112 } else {
113 initLocalizedLevelSetCG();
114 }
115
116 // NOTE: only possible after the cells are added to the collector!
117 this->checkNoHaloLayers();
118
119 computeGCellTimeStep();
120
121 if(m_combustion) {
122 determineSteadyFlameLength();
123 return;
124 }
125
126 if(m_freeSurface) {
127 return;
128 }
129
130 // if(m_initialRefinement) return;
131
132 setGCellBndryProperty();
133
134 if(!m_semiLagrange) {
135 computeNormalVectors();
136 computeCurvature();
137 }
138
139 finalizeLevelSetInitialization();
140
141 buildMultipleLevelSet();
142
143 checkHaloCells();
144
145 if(!m_semiLagrange) {
146 determinePropagationSpeed();
147 }
148
149 if(m_restart && m_GFieldFromSTLInitCheck) {
150 writeRestartLevelSetFileCG(1, "restartLSGridCG_restart", "restartLSCG_restart");
151 }
152}
153
154
155template <MInt nDim>
157 TRACE();
158
159 if(m_combustion) {
160 m_maxFlameFrontPosition = (MFloat*)nullptr;
161 m_minFlameFrontPosition = (MFloat*)nullptr;
162 m_meanFlameFrontPosition = (MFloat*)nullptr;
163
164 mAlloc(m_maxFlameFrontPosition, nDim, "m_maxFlameFrontPosition", -1000.0, AT_);
165 mAlloc(m_minFlameFrontPosition, nDim, "m_minFlameFrontPosition", 1000.0, AT_);
166 mAlloc(m_meanFlameFrontPosition, nDim, "m_meanFlameFrontPosition", F0, AT_);
167 }
168
169 m_cells.setMaxNoSets(m_maxNoSets);
170
171 // set the ls-Collector type to reduce ls-Cell memory!
172 if(m_combustion || m_freeSurface) {
173 // combustion Type
174 m_lsCollectorMode = 0;
175 } else if(m_semiLagrange) {
176 // semi-Lagrange Type with reinitialisation
177 m_lsCollectorMode = 2;
178 if(!m_guaranteeReinit && m_STLReinitMode == 2) {
179 // semi-Lagrange without reinitialisation
180 m_lsCollectorMode = 1;
181 }
182 } else {
183 // just the ls-Solver or lsFv
184 // TODO labels:LS,FV reduce memory further for applications which don't need all information!
185 ASSERT(m_LSSolver || m_levelSetFv || m_levelSetRans, "");
186 m_lsCollectorMode = 3;
187 }
188
189 m_cells.setLsCollectorType(m_lsCollectorMode);
190
191 m_noBodiesToCompute = 0;
192
193 if(m_semiLagrange) {
194 if(m_LsRotate) {
195 allocateRotatingLs();
196 }
197
198 mAlloc(m_semiLagrange_xShift_ref, m_noEmbeddedBodies * nDim, "m_semiLagrange_xShift_ref", F0, AT_);
199 }
200
201 m_cells.setGapClosing(m_closeGaps);
202 m_cells.setMaxBodiesToCompute(m_noBodiesToCompute);
203 m_cells.setReconstructOldG(m_reconstructOldG);
204 m_cells.setRotatingLs(m_LsRotate);
205 m_cells.setReinit(m_guaranteeReinit || m_STLReinitMode != 2);
206
207 m_cells.reset(m_maxNoCells);
208
209 if(m_LsRotate) {
210 m_cells.fillContainingCell();
211 if(!m_reconstructOldG) m_cells.fillContainingDomain();
212 }
213
214 // multiple level-set functions
215 m_noGapCells = 0;
216 m_noOldGapCells = 0;
217
218 mAlloc(m_bandCells, m_maxNoSets, "m_bandCells", AT_);
219 mAlloc(m_internalBandCells, m_maxNoSets, "m_internalBandCells", AT_);
220 mAlloc(m_bandBndryCells, m_maxNoSets, "m_bandBndryCells", AT_);
221 mAlloc(m_G0Cells, m_maxNoSets, "m_G0Cells", AT_);
222 for(MInt i = 0; i < m_maxNoSets; i++) {
223 m_bandCells[i].clear();
224 m_internalBandCells[i].clear();
225 m_bandBndryCells[i].clear();
226 m_G0Cells[i].clear();
227 }
228 mAlloc(m_bandLayer, (m_gShadowWidth + 1) * m_maxNoSets, "m_bandLayer", 0, AT_);
229 mAlloc(m_internalBandLayer, (m_gShadowWidth + 1) * m_maxNoSets, "m_internalBandLayer", 0, AT_);
230
231 if(!m_semiLagrange) {
232 mAlloc(m_gBndryCells, m_maxNoSets, "m_gBndryCells", AT_);
233 for(MInt i = 0; i < m_maxNoSets; i++) {
234 m_gBndryCells[i].clear();
235 }
236 }
237
238 m_localMarksteinLength = nullptr;
239 if(m_useLocalMarksteinLength) {
240 mAlloc(m_localMarksteinLength, m_maxNoCells, "m_localMarksteinLength", F0, AT_);
241 mTerm(1, AT_, "code should be debugged for multiple sets");
242 }
243
244 // memorz for reinitialisation
245 if(!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2) {
246 mAlloc(m_cellList, m_maxNoCells, "m_cellList", 0, AT_);
247 mAlloc(m_phiRatioCells, m_maxNoCells, 2 * nDim * m_maxNoSets, "m_phiRatioCells", 0, AT_);
248 mAlloc(m_correction, m_maxNoCells * m_maxNoSets, "m_correction", F0, AT_);
249 mAlloc(m_d, m_maxNoCells * m_maxNoSets, "m_d", F0, AT_);
250 mAlloc(m_phiRatio, m_maxNoCells, 2 * nDim * m_maxNoSets, "m_phiRatio", F0, AT_);
251 mAlloc(m_signG, m_maxNoCells * m_maxNoSets, "m_signG", F0, AT_);
252 }
253
254 // Parallelization
255 // allocate space for buffers
256 if(noNeighborDomains() > 0) {
257 if(isActive() && grid().noNeighborDomains() > 0) {
258 // allocate space for send and receive buffers
259 if(!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2) {
260 mAlloc(m_gSendBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gSendBuffers", F0, AT_);
261 mAlloc(m_gReceiveBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gReceiveBuffers", F0, AT_);
262 }
263
264 if(m_combustion) {
265 mAlloc(m_intSendBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intSendBuffers", 0, AT_);
266 mAlloc(m_intReceiveBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intReceiveBuffers", 0, AT_);
267 }
268
269 if(m_combustion || (!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2)) {
270 mAlloc(mpi_request, grid().noNeighborDomains(), "mpi_request", AT_);
271 mAlloc(mpi_recive, grid().noNeighborDomains(), "mpi_recive", AT_);
272 }
273 }
274 }
275
276 // initialize the flame surface area
277 m_arcLength = F0;
278}
279
285template <MInt nDim>
287 TRACE();
288
289 mAlloc(m_bodyRadius, m_noEmbeddedBodies, "m_bodyRadius", F0, AT_);
290 mAlloc(m_omega, m_noEmbeddedBodies * nDim, "m_omega", F0, AT_);
291 mAlloc(m_bodyAngularVelocity, m_noEmbeddedBodies * nDim, "m_bodyAngularVelocity", F0, AT_);
292 mAlloc(m_bodyAngularAcceleration, m_noEmbeddedBodies * nDim, "m_bodyAngularAcceleration", F0, AT_);
293 mAlloc(m_semiLagrange_xRot_ref, m_noEmbeddedBodies * nDim, "m_semiLagrange_xRot_ref", F0, AT_);
294 mAlloc(m_semiLagrange_xRot_STL, m_noEmbeddedBodies * nDim, "m_semiLagrange_xRot_STL", F0, AT_);
295 if(!m_reconstructOldG) {
296 mAlloc(m_initialGCell, m_maxNoCells, "m_initialGCell", 0, AT_);
297 mAlloc(m_cellDomIds, 2 * m_maxNoCells, "m_cellDomIds", -1, AT_);
298 }
299
300 MFloat maRot = F0;
301 MFloat rad = F0;
302 MInt ind = -1;
303 for(MInt b = 0; b < m_noEmbeddedBodies; b++) {
304 rad = Context::getSolverProperty<MFloat>("bodyRadius", solverId(), AT_, b);
305 m_bodyRadius[b] = rad;
306 for(MInt i = 0; i < nDim; i++) {
307 ind = b * nDim + i;
308 maRot = Context::getSolverProperty<MFloat>("MaRot", solverId(), AT_, ind);
309 if(abs(maRot) > F0) {
310 m_bodiesToCompute.push_back(b);
311 break;
312 }
313 }
314 }
315
316 m_noBodiesToCompute = m_bodiesToCompute.size();
317
318 // Communication buffers only needed when solver is active
319 if(!m_reconstructOldG && isActive()) {
320 // Global Communication
321 mAlloc(m_globalSndOffsets, grid().noDomains() + 1, "m_globalSndOffsets", 0, AT_);
322 mAlloc(m_globalRcvOffsets, grid().noDomains() + 1, "m_globalRcvOffsets", 0, AT_);
323 }
324}
325
326// ----------------------------------------------------------------------------------------
327
328
339template <MInt nDim>
341 TRACE();
342
343 MInt nghbrL;
344 MInt nghbrL2;
345 MInt nghbrL3;
346 MInt nghbrR;
347 MInt nghbrR2;
348 MInt nghbrR3;
349 MInt id;
350 MInt cellId;
351 //--- end of initialization
352 for(MInt set = m_startSet; set < m_noSets; set++) {
353 if(!m_computeSet[set]) continue;
354 // reset the G right hand side
355 for(MInt bandId = 0; bandId < a_noBandCells(set); bandId++) {
356 cellId = a_bandCellId(bandId, set);
357 a_levelSetRHS(cellId, set) = F0;
358 }
359 // UC5
360 for(MInt bandId = 0; bandId < a_noBandCells(set); bandId++) {
361 cellId = a_bandCellId(bandId, set);
362 if(a_isHalo(cellId)) continue;
363 for(MInt i = 0; i < nDim; i++) {
364 if(a_extensionVelocityG(cellId, i, set) > F0) {
365 nghbrL = c_neighborId(cellId, 2 * i);
366 nghbrL2 = c_neighborId(nghbrL, 2 * i);
367 nghbrL3 = c_neighborId(nghbrL2, 2 * i);
368 nghbrR = c_neighborId(cellId, 2 * i + 1);
369 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
370 id = cellId;
371 if((!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR, set)) /*||
372 (a_isGBoundaryCellG( nghbrL2 , set ) ||
373 a_isGBoundaryCellG( nghbrR , set ) )*/
374 ) {
375 // reduce to first order
376 nghbrR = cellId;
377 nghbrR2 = cellId;
378 nghbrL2 = cellId;
379 nghbrL3 = cellId;
380 } else {
381 if((!a_inBandG(nghbrL3, set) || !a_inBandG(nghbrR2, set)) /*||
382 (a_isGBoundaryCellG( nghbrL3 , set ) ||
383 a_isGBoundaryCellG( nghbrR2 , set ) )*/
384 ) {
385 // reduce to third order
386 id = nghbrR;
387 nghbrR = cellId;
388 nghbrR2 = nghbrL2;
389 nghbrL3 = nghbrL2;
390 }
391 }
392 a_levelSetRHS(cellId, set) +=
393 a_extensionVelocityG(cellId, i, set)
394 * (-F1B30 * a_levelSetFunctionG(nghbrL3, set) + F1B4 * a_levelSetFunctionG(nghbrL2, set)
395 - a_levelSetFunctionG(nghbrL, set) + F1B3 * a_levelSetFunctionG(id, set)
396 + F1B2 * a_levelSetFunctionG(nghbrR, set) - F1B20 * a_levelSetFunctionG(nghbrR2, set));
397 } else {
398 nghbrL = c_neighborId(cellId, 2 * i);
399 nghbrL2 = c_neighborId(nghbrL, 2 * i);
400 nghbrR = c_neighborId(cellId, 2 * i + 1);
401 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
402 nghbrR3 = c_neighborId(nghbrR2, 2 * i + 1);
403 id = cellId;
404 if((!a_inBandG(nghbrR2, set) || !a_inBandG(nghbrL, set)) /*||
405 (a_isGBoundaryCellG( nghbrR2 , set ) ||
406 a_isGBoundaryCellG( nghbrL , set ) )*/
407 ) {
408 // reduce to first order
409 nghbrL = cellId;
410 nghbrL2 = cellId;
411 nghbrR2 = cellId;
412 nghbrR3 = cellId;
413 } else {
414 if((!a_inBandG(nghbrR3, set) || !a_inBandG(nghbrL2, set)) /*||
415 (a_isGBoundaryCellG( nghbrR3 , set ) ||
416 a_isGBoundaryCellG( nghbrL2 , set ) )*/
417 ) {
418 // reduce to third order
419 id = nghbrL;
420 nghbrL = cellId;
421 nghbrL2 = nghbrR2;
422 nghbrR3 = nghbrR2;
423 }
424 }
425 a_levelSetRHS(cellId, set) +=
426 a_extensionVelocityG(cellId, i, set)
427 * (F1B30 * a_levelSetFunctionG(nghbrR3, set) - F1B4 * a_levelSetFunctionG(nghbrR2, set)
428 + a_levelSetFunctionG(nghbrR, set) - F1B3 * a_levelSetFunctionG(id, set)
429 - F1B2 * a_levelSetFunctionG(nghbrL, set) + F1B20 * a_levelSetFunctionG(nghbrL2, set));
430 }
431 }
432 a_levelSetRHS(cellId, set) *= m_FgCellDistance;
433 }
434 }
435}
436
437
438// ----------------------------------------------------------------------------------------
439
447template <MInt nDim>
449 TRACE();
450
451 MBool timeStepCompleted = false;
452
453 // exchange level set function on halo cells, cause they are needed for the Markstein length computation!
454
455 computeLevelSetRHS();
456
457 // advance the G field
458 timeStepCompleted = gRungeKutta();
459
460 // average G from the fine grid to the coarse grid
461 if(timeStepCompleted) levelSetRestriction();
462
463 return timeStepCompleted;
464}
465
466//-----------------------------------------------------------------------------
467
468
469template <MInt nDim>
471 TRACE();
472 MFloat c;
473 MFloat factor;
474 //---end of initialization
475 if(m_gRKMethod == 5) return true;
476
477 // set old variables - changes due to multilevel
478 for(MInt set = 0; set < m_noSets; set++) {
479 if(!m_computeSet[set]) continue;
480 if(m_gRKStep == 0)
481 for(MInt id = 0; id < a_noBandCells(set); id++)
482 a_oldLevelSetFunctionG(a_bandCellId(id, set), set) = a_levelSetFunctionG(a_bandCellId(id, set), set);
483 }
484
485 switch(m_gRKMethod) {
486 case 0: {
487 factor = m_gRKalpha[m_gRKStep] * timeStep();
488 for(MInt set = m_startSet; set < m_noSets; set++) {
489 if(!m_computeSet[set]) continue;
490 for(MInt id = 0; id < a_noBandCells(set); id++) {
491 if(a_isGBoundaryCellG(a_bandCellId(id, set), set)) continue;
492 a_levelSetFunctionG(a_bandCellId(id, set), set) =
493 a_oldLevelSetFunctionG(a_bandCellId(id, set), set) - factor * a_levelSetRHS(a_bandCellId(id, set), set);
494 }
495 }
496 break;
497 }
498 case 1: {
499 factor = m_gRKalpha[m_gRKStep] * timeStep();
500 for(MInt set = m_startSet; set < m_noSets; set++) {
501 if(!m_computeSet[set]) continue;
502 for(MInt id = 0; id < a_noBandCells(set); id++) {
503 if(a_isGBoundaryCellG(a_bandCellId(id, set), set)) continue;
504 a_levelSetFunctionG(a_bandCellId(id, set), set) =
505 a_levelSetFunctionG(a_bandCellId(id, set), set) * m_gRKalpha[m_gRKStep]
506 + a_oldLevelSetFunctionG(a_bandCellId(id, set), set) * (F1 - m_gRKalpha[m_gRKStep])
507 - a_levelSetRHS(a_bandCellId(id, set), set) * factor;
508 }
509 }
510 break;
511 }
512 case 2: {
513 MInt noIntegrationLayers = m_gBandWidth - 5;
514 factor = m_gRKalpha[m_gRKStep] * timeStep();
515 for(MInt set = m_startSet; set < m_noSets; set++) {
516 if(!m_computeSet[set]) continue;
517 for(MInt id = 0; id < a_noBandCells(set); id++) {
518 if(a_isGBoundaryCellG(a_bandCellId(id, set), set)) continue;
519 c = fabs(a_levelSetFunctionG(a_bandCellId(id, set), set)) * m_FgCellDistance - noIntegrationLayers;
520 if(c > F0)
521 a_levelSetRHS(a_bandCellId(id, set), set) = F0;
522 else if(c > -3.0)
523 a_levelSetRHS(a_bandCellId(id, set), set) *= (F2B27 * POW3(c) + F1B3 * POW2(c));
524 a_levelSetFunctionG(a_bandCellId(id, set), set) =
525 a_levelSetFunctionG(a_bandCellId(id, set), set) * m_gRKalpha[m_gRKStep]
526 + a_oldLevelSetFunctionG(a_bandCellId(id, set), set) * (F1 - m_gRKalpha[m_gRKStep])
527 - a_levelSetRHS(a_bandCellId(id, set), set) * factor;
528 }
529 }
530 break;
531 }
532 case 3: {
533 factor = m_gRKalpha[m_gRKStep] * timeStep();
534 for(MInt set = m_startSet; set < m_noSets; set++) {
535 if(!m_computeSet[set]) continue;
536 for(MInt id = 0; id < a_bandLayer(0, set); id++) {
537 if(a_isGBoundaryCellG(a_bandCellId(id, set), set)) continue;
538 a_levelSetFunctionG(a_bandCellId(id, set), set) =
539 a_levelSetFunctionG(a_bandCellId(id, set), set) * m_gRKalpha[m_gRKStep]
540 + a_oldLevelSetFunctionG(a_bandCellId(id, set), set) * (F1 - m_gRKalpha[m_gRKStep])
541 - a_levelSetRHS(a_bandCellId(id, set), set) * factor;
542 }
543 }
544 reinitBand(m_startSet, m_noSets);
545 break;
546 }
547 // the level-set equation is only solved at the front
548 case 4: {
549 factor = m_gRKalpha[m_gRKStep] * timeStep();
550 for(MInt set = m_startSet; set < m_noSets; set++) {
551 if(!m_computeSet[set]) continue;
552 for(MInt id = 0; id < a_bandLayer(0, set); id++) {
553 if(a_isGBoundaryCellG(a_bandCellId(id, set), set)) continue;
554 a_levelSetFunctionG(a_bandCellId(id, set), set) =
555 a_levelSetFunctionG(a_bandCellId(id, set), set) * m_gRKalpha[m_gRKStep]
556 + a_oldLevelSetFunctionG(a_bandCellId(id, set), set) * (F1 - m_gRKalpha[m_gRKStep])
557 - a_levelSetRHS(a_bandCellId(id, set), set) * factor;
558 }
559 }
560 break;
561 }
562 case 5: {
563 // property is initialized to this value, which does nothing
564 break;
565 }
566 default: {
567 mTerm(1, AT_, "Unknown gRKMethod");
568 }
569 }
570 // cerr << "m_gRKStep: " << m_gRKStep << endl;
571 m_gRKStep++;
572
573 if(m_gRKStep == m_nogRKSteps) {
574 m_gRKStep = 0;
575 if(m_LSSolver) {
576 if(globalTimeStep > 0) {
577 m_time += timeStep();
578 }
579 }
580 return true;
581 } else
582 return false;
583}
584
585
586//-----------------------------------------------------------------------------
587
588
597template <MInt nDim>
599 TRACE();
600
601 switch(string2enum(m_levelSetDiscretizationScheme)) {
602 case BACKWARDS_PAR: {
603 MFloat xOld[3] = {F0, F0, F0};
604 MInt containingCell = 0;
605 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
606
607 MInt position = 0;
608 MFloat xCurrent[3] = {F0, F0, F0};
609 MFloat xShift[3] = {F0, F0, F0};
610 MFloat xShift_cur[3] = {F0, F0, F0};
611#if defined LS_DEBUG || !defined NDEBUG
612 MFloat shiftCheck[3] = {F0, F0, F0};
613#endif
614
615 //-------------------------
616
617 for(MInt set = m_startSet; set < m_noSets; set++) {
618 if(!m_computeSet[set]) continue;
619
620 const MFloat cellLength = c_cellLengthAtLevel(a_maxGCellLevel(set));
621 const MFloat cellHalfLength = c_cellLengthAtLevel(a_maxGCellLevel(set) + 1);
622
623 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
624 const MInt body = m_setToBodiesTable[set][b];
625 computeBodyPropertiesForced(1, xCurrent, body, time() + timeStep(), true);
626
627#if defined LS_DEBUG || !defined NDEBUG
628 computeBodyPropertiesForced(1, shiftCheck, body, time());
629 for(MInt d = 0; d < nDim; d++) {
630 MFloat shift = xCurrent[d] - shiftCheck[d];
631 if(shift > cellLength && !m_periodicMovement) {
632 mTerm(1, AT_, "LevelSet-Shift is exceeding maximum shift-limit of a cellLength! Reduce timestep!");
633 }
634 }
635#endif
636 computeBodyPropertiesForced(1, xOld, body, 0.0);
637 for(MInt d = 0; d < nDim; d++) {
638 xShift[d] = xCurrent[d] - xOld[d];
639 xShift_cur[d] = xShift[d] - m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body];
640 }
641
642 // 0. if required, shift reference field
643 for(MInt d = 0; d < nDim; d++) {
644 MFloat tmp = xShift_cur[d];
645 if(abs(tmp) > 2 * cellLength && m_periodicMovement) {
646 m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body] -= m_periodicDistance - cellLength;
647 shiftOldLevelSetField(2 * d + 1, set, body);
648 exchangeLeafDataLS<false>();
649 } else {
650 if(tmp + cellHalfLength > cellLength) {
651 m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body] += cellLength;
652 shiftOldLevelSetField(2 * d + 1, set, body);
653 exchangeLeafDataLS<false>();
654 } else if(tmp - cellHalfLength < -cellLength) {
655 m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body] -= cellLength;
656 shiftOldLevelSetField(2 * d, set, body);
657 exchangeLeafDataLS<false>();
658 }
659 }
660 }
661
662 // interpolate current field from reference field
663 for(MInt id = 0; id < a_noBandCells(set); id++) {
664 const MInt cellId = a_bandCellId(id, set);
665 if(!(a_bodyIdG(cellId, set) == body)) continue;
666 // if cell is a boundary cell, process simle (0th order)
667 MBool boundaryCell = false;
668 for(MInt d = 0; d < m_noDirs; d++) {
669 if(!a_hasNeighbor(cellId, d)) {
670 a_levelSetFunctionG(cellId, set) = a_oldLevelSetFunctionG(cellId, set);
671 boundaryCell = true;
672 break;
673 }
674 }
675 if(boundaryCell) continue;
676 if(a_isHalo(cellId)) continue;
677 // else, 1st order interpolation:
678 // 1. find x_old
679 for(MInt i = 0; i < nDim; i++) {
680 xOld[i] =
681 c_coordinate(cellId, i) - (xShift[i] - m_semiLagrange_xShift_ref[i * m_noEmbeddedBodies + body]);
682 }
683 // 2. get containing cell
684 containingCell = getContainingCell(cellId, xOld, set);
685 // 3. set up interpolation stencil
686 position = setUpLevelSetInterpolationStencil(containingCell, interpolationCells, xOld);
687 // 4. interpolate level set
688 MFloat phiNew = -99;
689 if(position > -1) {
690 phiNew = interpolateOldLevelSet(interpolationCells, xOld, set);
691 } else {
692 phiNew = a_oldLevelSetFunctionG(containingCell, set);
693 }
694 a_levelSetFunctionG(cellId, set) = phiNew;
695 }
696 }
697 }
698 break;
699 }
700 case ROTATING_LS: {
701 MFloat xInitial[3];
702 MFloat xCoord[3];
703 MFloat xOld[3];
704 MFloat xCurrent[3];
705 MInt body;
706 MInt set;
707 MFloat phiNew = F0;
708 MInt containingCell;
709 MInt searchCell;
710 MInt searchDomain;
711 MInt cellId;
712 MInt ind;
713
714 MBool firstRun = false;
715 std::vector<MInt> remCells;
716
717 // Update the rotated angle
718 for(MInt i = 0; i < m_noBodiesToCompute; i++) {
719 body = m_bodiesToCompute[i];
720 for(MInt d = 0; d < nDim; d++) {
721 m_semiLagrange_xRot_ref[body * nDim + d] += m_omega[body * nDim + d] * timeStep();
722 m_semiLagrange_xRot_STL[body * nDim + d] += m_omega[body * nDim + d] * timeStep();
723 }
724
725#ifndef NDEBUG
726 if(domainId() == 0) {
727 cerr << "TS: " << globalTimeStep << " B: " << body
728 << " rot: " << m_semiLagrange_xRot_STL[body * nDim + 0] * 180.0 / PI << ","
729 << m_semiLagrange_xRot_STL[body * nDim + 1] * 180.0 / PI << ","
730 << m_semiLagrange_xRot_STL[body * nDim + 2] * 180.0 / PI << " / "
731 << m_semiLagrange_xRot_ref[body * nDim + 0] * 180.0 / PI << ","
732 << m_semiLagrange_xRot_ref[body * nDim + 1] * 180.0 / PI << ","
733 << m_semiLagrange_xRot_ref[body * nDim + 2] * 180.0 / PI << " deg;"
734 << " Omega: " << m_omega[body * nDim + 0] << " " << m_omega[body * nDim + 1] << " "
735 << m_omega[body * nDim + 2] << endl;
736 }
737#endif
738 }
739
740 // Compute levelset
741 if(m_reconstructOldG) {
742 // Update halo information of containingCells list
743 MInt noData = m_noBodiesToCompute;
744 MLongScratchSpace tmp_data(a_noCells(), noData, AT_, "tmp_data");
745 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
746 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
747 for(MInt j = 0; j < noWindowCells(i); j++) {
748 cellId = windowCellId(i, j);
749 if(a_containingCell(cellId, b) > -1) {
750 tmp_data(cellId, b) = c_globalId(a_containingCell(cellId, b));
751 } else {
752 tmp_data(cellId, b) = -1;
753 }
754 }
755 }
756 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
757 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
758 cellId = grid().azimuthalWindowCell(i, j);
759 if(a_containingCell(cellId, b) > -1) {
760 tmp_data(cellId, b) = c_globalId(a_containingCell(cellId, b));
761 } else {
762 tmp_data(cellId, b) = -1;
763 }
764 }
765 }
766 }
767 exchangeDataLS(&tmp_data(0, 0), noData);
768 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
769 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
770 for(MInt j = 0; j < noHaloCells(i); j++) {
771 cellId = haloCellId(i, j);
772 if(tmp_data(cellId, b) > -1) {
773 a_containingCell(cellId, b) = a_localId(tmp_data(cellId, b));
774 } else {
775 a_containingCell(cellId, b) = -1;
776 }
777 }
778 }
779 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
780 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
781 cellId = grid().azimuthalHaloCell(i, j);
782 if(tmp_data(cellId, b) > -1) {
783 a_containingCell(cellId, b) = a_localId(tmp_data(cellId, b));
784 } else {
785 a_containingCell(cellId, b) = -1;
786 }
787 }
788 }
789 }
790
791 // Loop over all sets and compute levelset value and update containingCells list
792 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
793 body = m_bodiesToCompute[b];
794 set = m_bodyToSetTable[body];
795
796 // Compute position of bodycenter
797 computeBodyPropertiesForced(1, xCurrent, body, time() + timeStep());
798 computeBodyPropertiesForced(1, xOld, body, 0.0);
799
800 for(MInt id = 0; id < a_noBandCells(set); id++) {
801 cellId = a_bandCellId(id, set);
802 if(!(a_bodyIdG(cellId, set) == body)) continue;
803 if(a_isHalo(cellId)) continue;
804
805 searchCell = a_containingCell(cellId, b);
806 if(searchCell < 0) {
807 for(MInt i = 0; i < nDim; i++)
808 xCoord[i] = c_coordinate(cellId, i);
809
810 getContainingCellFromNeighbor(b, cellId, xCoord, xOld);
811 m_newCells.push_back(cellId);
812 }
813 }
814 m_newCells.clear();
815
816 // Loop over all bandCells in set
817 for(MInt id = 0; id < a_noBandCells(set); id++) {
818 cellId = a_bandCellId(id, set);
819 if(!(a_bodyIdG(cellId, set) == body)) continue;
820 if(a_isHalo(cellId)) continue;
821
822 // Access information about which cell lies at xInitial. If no information is available take it from
823 // neighborCell
824 searchCell = a_containingCell(cellId, b);
825
826 // Compute the reference position of the bandCell at t=0
827 for(MInt i = 0; i < nDim; i++) {
828 xCoord[i] = c_coordinate(cellId, i);
829 }
830 rotateLevelSet(1, xInitial, body, xCoord, xOld, &m_semiLagrange_xRot_ref[body * nDim]);
831 for(MInt i = 0; i < nDim; i++) {
832 xInitial[i] += xCurrent[i] - xOld[i];
833 }
834
835 if(grid().azimuthalPeriodicity()) {
836 MBool shift = false;
837 for(MInt d = 0; d < nDim; d++) {
838 shift = shift || !approx(c_coordinate(searchCell, d), xInitial[d], F2 * c_cellLengthAtCell(searchCell));
839 }
840 if(shift) {
841 MFloat coords[nDim];
842 MFloat coordsCylSearch[nDim];
843 MFloat coordsCyl[nDim];
844 for(MInt d = 0; d < nDim; d++) {
845 coords[d] = c_coordinate(searchCell, d);
846 }
847 grid().raw().cartesianToCylindric(coords, coordsCylSearch);
848 grid().raw().cartesianToCylindric(xInitial, coordsCyl);
849 MInt side = grid().determineAzimuthalBoundarySide(xInitial);
850 MInt fac = 0;
851 if(side == -1) {
852 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() - F1B2);
853 } else if(side == 1) {
854 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() + F1B2);
855 } else {
856 mTerm(1, AT_, "Invalid side!");
857 }
858 grid().raw().rotateCartesianCoordinates(xInitial, fac * grid().azimuthalAngle());
859 }
860 }
861
862 // Find containingCell
863 containingCell = getContainingCell(searchCell, xInitial);
864 if(containingCell != cellId) {
865 m_rotatingReinitTrigger = 1;
866 }
867
868 // Compute new levelSet value and determine containingCell. Then update list.
869 MInt dummyDomain = -1;
870 processRotatingLevelSet(phiNew, containingCell, dummyDomain, xInitial, set);
871
872 a_levelSetFunctionG(cellId, set) = phiNew;
873 a_containingCell(cellId, b) = containingCell;
874 }
875
876 // Reset cells in shadow layer
877 for(MInt i = 0; i < m_maxNoCells; i++) {
878 if(!a_inBandG(i, set)) {
879 a_containingCell(i, b) = -1;
880 }
881 }
882 }
883
884 } else {
885 // Update halo information of containingCells list
886 MInt noData = 2 * m_noBodiesToCompute;
887 MIntScratchSpace tmp_data(a_noCells(), noData, AT_, "tmp_data");
888 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
889 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
890 for(MInt j = 0; j < noWindowCells(i); j++) {
891 cellId = windowCellId(i, j);
892 if(a_containingCell(cellId, b) > -1) {
893 tmp_data(cellId, b) = a_containingCell(cellId, b);
894 tmp_data(cellId, m_noBodiesToCompute + b) = a_containingDomain(cellId, b);
895 } else {
896 tmp_data(cellId, b) = -1;
897 tmp_data(cellId, m_noBodiesToCompute + b) = -1;
898 }
899 }
900 }
901 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
902 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
903 cellId = grid().azimuthalWindowCell(i, j);
904 if(a_containingCell(cellId, b) > -1) {
905 tmp_data(cellId, b) = a_containingCell(cellId, b);
906 tmp_data(cellId, m_noBodiesToCompute + b) = a_containingDomain(cellId, b);
907 } else {
908 tmp_data(cellId, b) = -1;
909 tmp_data(cellId, m_noBodiesToCompute + b) = -1;
910 }
911 }
912 }
913 }
914 exchangeDataLS(&tmp_data(0, 0), noData);
915 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
916 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
917 for(MInt j = 0; j < noHaloCells(i); j++) {
918 cellId = haloCellId(i, j);
919 if(tmp_data(cellId, b) > -1) {
920 a_containingCell(cellId, b) = tmp_data(cellId, b);
921 a_containingDomain(cellId, b) = tmp_data(cellId, m_noBodiesToCompute + b);
922 } else {
923 a_containingCell(cellId, b) = -1;
924 a_containingDomain(cellId, b) = -1;
925 }
926 }
927 }
928 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
929 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
930 cellId = grid().azimuthalHaloCell(i, j);
931 if(tmp_data(cellId, b) > -1) {
932 a_containingCell(cellId, b) = tmp_data(cellId, b);
933 a_containingDomain(cellId, b) = tmp_data(cellId, m_noBodiesToCompute + b);
934 } else {
935 a_containingCell(cellId, b) = -1;
936 a_containingDomain(cellId, b) = -1;
937 }
938 }
939 }
940 }
941
942 // Loop over all sets and compute levelset value and update containingCells list
943 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
944 body = m_bodiesToCompute[b];
945 set = m_bodyToSetTable[body];
946
947 // Compute position of bodycenter
948 computeBodyPropertiesForced(1, xCurrent, body, time() + timeStep());
949 computeBodyPropertiesForced(1, xOld, body, 0.0);
950
951 // Allocate Buffers for global communication
952 MIntScratchSpace noCellsToDom(grid().noDomains(), AT_, "noCellsToDom");
953 noCellsToDom.fill(0);
954
955 for(MInt id = 0; id < a_noBandCells(set); id++) {
956 cellId = a_bandCellId(id, set);
957 if(!(a_bodyIdG(cellId, set) == body)) continue;
958 if(a_isHalo(cellId)) continue;
959
960 searchCell = a_containingCell(cellId, b);
961 searchDomain = a_containingDomain(cellId, b);
962 if(searchCell < 0 || searchDomain < 0) {
963 for(MInt i = 0; i < nDim; i++)
964 xCoord[i] = c_coordinate(cellId, i);
965 getContainingCellFromNeighbor(b, cellId, xCoord, xOld);
966 searchDomain = a_containingDomain(cellId, b);
967 m_newCells.push_back(cellId);
968 }
969 if(searchDomain > -1) {
970 noCellsToDom[searchDomain]++;
971 }
972 }
973 m_newCells.clear();
974
975 prepareGlobalComm(&noCellsToDom[0]);
976 MInt noCellsComm = mMax(m_globalSndOffsets[grid().noDomains()], m_globalRcvOffsets[grid().noDomains()]);
977
978 MIntScratchSpace intSndBufSizeGlob(grid().noDomains(), AT_, "intSndBufSizeGlob");
979 MIntScratchSpace intRcvBufSizeGlob(grid().noDomains(), AT_, "intRcvBufSizeGlob");
980 MIntScratchSpace floatSndBufSizeGlob(grid().noDomains(), AT_, "floatSndBufSizeGlob");
981 MIntScratchSpace floatRcvBufSizeGlob(grid().noDomains(), AT_, "floatRcvBufSizeGlob");
982 MInt floatOffset = 3;
983 MInt intOffset = 2;
984 MIntScratchSpace intSndBufGlob(intOffset * noCellsComm, AT_, "intSndBufGlob");
985 MIntScratchSpace intRcvBufGlob(intOffset * noCellsComm, AT_, "intRcvBufGlob");
986 MFloatScratchSpace floatSndBufGlob(floatOffset * noCellsComm, AT_, "floatSndBufGlob");
987 MFloatScratchSpace floatRcvBufGlob(floatOffset * noCellsComm, AT_, "floatRcvBufGlob");
988
989 std::vector<std::vector<MInt>> cellIdsLoc;
990 cellIdsLoc.resize(grid().noDomains());
991
992 intSndBufGlob.fill(-1);
993 intRcvBufGlob.fill(-1);
994 floatSndBufGlob.fill(-F1);
995 floatRcvBufGlob.fill(-F1);
996 intSndBufSizeGlob.fill(0);
997 intRcvBufSizeGlob.fill(0);
998 floatSndBufSizeGlob.fill(0);
999 floatRcvBufSizeGlob.fill(0);
1000
1001 // Loop over all bandCells in set
1002 for(MInt id = 0; id < a_noBandCells(set); id++) {
1003 cellId = a_bandCellId(id, set);
1004 if(!(a_bodyIdG(cellId, set) == body)) continue;
1005 if(a_isHalo(cellId)) continue;
1006
1007 // Access information about which cell lies at xInitial. If no information is available take it from
1008 // neighborCell
1009 searchCell = a_containingCell(cellId, b);
1010 searchDomain = a_containingDomain(cellId, b);
1011
1012 // Skip outer layer of bandCells.
1013 /*
1014 if ( a_isGBoundaryCellG(cellId,set) ) {
1015 if ( a_levelSetFunctionG(cellId,set) > F0 ) {
1016 a_levelSetFunctionG(cellId,set) = m_outsideGValue;
1017 } else {
1018 a_levelSetFunctionG(cellId,set) = -m_outsideGValue;
1019 }
1020 m_containingCell[ b*m_maxNoCells + cellId ] = -1;
1021 m_containingDomain[ b*m_maxNoCells + cellId ] = -1;
1022 continue;
1023 }
1024 */
1025 // Compute the reference position of the bandCell at t=0
1026 for(MInt i = 0; i < nDim; i++) {
1027 xCoord[i] = c_coordinate(cellId, i);
1028 }
1029 rotateLevelSet(1, xInitial, body, xCoord, xOld, &m_semiLagrange_xRot_ref[body * nDim]);
1030 for(MInt i = 0; i < nDim; i++) {
1031 xInitial[i] += xCurrent[i] - xOld[i];
1032 }
1033
1034 // Now, handle all cases where cell and containingCell are on the same domain (no communication neccessary).
1035 if(searchDomain == domainId()) {
1036 if(grid().azimuthalPeriodicity()) {
1037 MBool shift = false;
1038 for(MInt d = 0; d < nDim; d++) {
1039 shift =
1040 shift || !approx(c_coordinate(searchCell, d), xInitial[d], F2 * c_cellLengthAtCell(searchCell));
1041 }
1042 if(shift) {
1043 MFloat coords[nDim];
1044 MFloat coordsCylSearch[nDim];
1045 MFloat coordsCyl[nDim];
1046 for(MInt d = 0; d < nDim; d++) {
1047 coords[d] = c_coordinate(searchCell, d);
1048 }
1049 grid().raw().cartesianToCylindric(coords, coordsCylSearch);
1050 grid().raw().cartesianToCylindric(xInitial, coordsCyl);
1051 MInt side = grid().determineAzimuthalBoundarySide(xInitial);
1052 MInt fac = 0;
1053 if(side == -1) {
1054 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() - F1B2);
1055 } else if(side == 1) {
1056 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() + F1B2);
1057 } else {
1058 mTerm(1, AT_, "Invalid side!");
1059 }
1060 grid().raw().rotateCartesianCoordinates(xInitial, fac * grid().azimuthalAngle());
1061 }
1062 }
1063
1064 // Find containingCell
1065 containingCell = getContainingCell(searchCell, xInitial);
1066
1067 // This is a backup, if the list is incorrect after restarts
1068 if(firstRun && containingCell < 0) {
1069 remCells.push_back(cellId);
1070 continue;
1071 }
1072 // Compute new levelSet value and determine containingCell and containingDomain. Then update list.
1073 processRotatingLevelSet(phiNew, containingCell, searchDomain, xInitial, set);
1074
1075 a_levelSetFunctionG(cellId, set) = phiNew;
1076 a_containingCell(cellId, b) = containingCell;
1077 a_containingDomain(cellId, b) = searchDomain;
1078 } else if(searchDomain < 0) {
1079 // If the list is broken after restart, use backup method. Otherwise, exit...
1080 if(firstRun) {
1081 remCells.push_back(cellId);
1082 } else {
1083 mTerm(1, AT_, "Containing Domain unkown in ROTATING_LS!");
1084 }
1085 } else {
1086 // If containingCell is on different domain. Put all neccessary information in send buffer to exchange
1087 // latter.
1088 cellIdsLoc[searchDomain].push_back(cellId);
1089 intSndBufGlob[m_globalSndOffsets[searchDomain] + intSndBufSizeGlob.p[searchDomain]] = searchCell;
1090 intSndBufSizeGlob.p[searchDomain]++;
1091
1092 for(MInt dim = 0; dim < nDim; dim++) {
1093 floatSndBufGlob[floatOffset * m_globalSndOffsets[searchDomain] + floatSndBufSizeGlob.p[searchDomain]] =
1094 xInitial[dim];
1095 floatSndBufSizeGlob.p[searchDomain]++;
1096 }
1097 }
1098 }
1099
1100
1101 // exchange
1102 exchangeBuffersGlobal(intSndBufGlob.getPointer(), intRcvBufGlob.getPointer(), intSndBufSizeGlob.getPointer(),
1103 intRcvBufSizeGlob.getPointer(), m_globalSndOffsets, m_globalRcvOffsets, 3);
1104 exchangeBuffersGlobal(floatSndBufGlob.getPointer(), floatRcvBufGlob.getPointer(),
1105 floatSndBufSizeGlob.getPointer(), floatRcvBufSizeGlob.getPointer(), m_globalSndOffsets,
1106 m_globalRcvOffsets, 5, floatOffset);
1107
1108 intSndBufGlob.fill(-1);
1109 floatSndBufGlob.fill(-F1);
1110 intSndBufSizeGlob.fill(0);
1111 floatSndBufSizeGlob.fill(0);
1112
1113 // Now handle all cells for which the containingCell is on different domain
1114 for(MInt i = 0; i < grid().noDomains(); i++) {
1115 ind = m_globalRcvOffsets[i];
1116 for(MInt j = 0; j < intRcvBufSizeGlob(i); j++) {
1117 searchCell = intRcvBufGlob(ind + j);
1118 searchDomain = domainId();
1119
1120 xInitial[0] = floatRcvBufGlob(ind * floatOffset + j * floatOffset + 0);
1121 xInitial[1] = floatRcvBufGlob(ind * floatOffset + j * floatOffset + 1);
1122 xInitial[2] = floatRcvBufGlob(ind * floatOffset + j * floatOffset + 2);
1123
1124 if(grid().azimuthalPeriodicity()) {
1125 MBool shift = false;
1126 for(MInt d = 0; d < nDim; d++) {
1127 shift =
1128 shift || !approx(c_coordinate(searchCell, d), xInitial[d], F2 * c_cellLengthAtCell(searchCell));
1129 }
1130 if(shift) {
1131 MFloat coords[nDim];
1132 MFloat coordsCylSearch[nDim];
1133 MFloat coordsCyl[nDim];
1134 for(MInt d = 0; d < nDim; d++) {
1135 coords[d] = c_coordinate(searchCell, d);
1136 }
1137 grid().raw().cartesianToCylindric(coords, coordsCylSearch);
1138 grid().raw().cartesianToCylindric(xInitial, coordsCyl);
1139 MInt side = grid().determineAzimuthalBoundarySide(xInitial);
1140 MInt fac = 0;
1141 if(side == -1) {
1142 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() - F1B2);
1143 } else if(side == 1) {
1144 fac = (MInt)((coordsCyl[1] - coordsCylSearch[1]) / grid().azimuthalAngle() + F1B2);
1145 } else {
1146 mTerm(1, AT_, "Invalid side!");
1147 }
1148 grid().raw().rotateCartesianCoordinates(xInitial, fac * grid().azimuthalAngle());
1149 }
1150 }
1151
1152 // Find containingCell
1153 containingCell = getContainingCell(searchCell, xInitial);
1154
1155 // Backup for restart
1156 if(firstRun && containingCell < 0) {
1157 intSndBufGlob(ind * intOffset + intSndBufSizeGlob.p[i]) = -2;
1158 intSndBufSizeGlob.p[i]++;
1159 intSndBufGlob(ind * intOffset + intSndBufSizeGlob.p[i]) = -2;
1160 intSndBufSizeGlob.p[i]++;
1161 floatSndBufGlob(ind * floatOffset + floatSndBufSizeGlob.p[i]) = F0;
1162 floatSndBufSizeGlob.p[i]++;
1163 continue;
1164 }
1165
1166 // Compute levelSet value and new containingCell and containingDomain and put it Buffer for later exchange
1167 processRotatingLevelSet(phiNew, containingCell, searchDomain, xInitial, set);
1168
1169 floatSndBufGlob(ind + floatSndBufSizeGlob.p[i]) = phiNew;
1170 floatSndBufSizeGlob.p[i]++;
1171 intSndBufGlob(ind * intOffset + intSndBufSizeGlob.p[i]) = containingCell;
1172 intSndBufSizeGlob.p[i]++;
1173 intSndBufGlob(ind * intOffset + intSndBufSizeGlob.p[i]) = searchDomain;
1174 intSndBufSizeGlob.p[i]++;
1175 }
1176 }
1177
1178 intRcvBufGlob.fill(-1);
1179 floatRcvBufGlob.fill(-F1);
1180 intRcvBufSizeGlob.fill(0);
1181 floatRcvBufSizeGlob.fill(0);
1182
1183 // exchange
1184 exchangeBuffersGlobal(intSndBufGlob.getPointer(), intRcvBufGlob.getPointer(), intSndBufSizeGlob.getPointer(),
1185 intRcvBufSizeGlob.getPointer(), &m_globalRcvOffsets[0], &m_globalSndOffsets[0], 3,
1186 intOffset);
1187 exchangeBuffersGlobal(floatSndBufGlob.getPointer(), floatRcvBufGlob.getPointer(),
1188 floatSndBufSizeGlob.getPointer(), floatRcvBufSizeGlob.getPointer(),
1189 &m_globalRcvOffsets[0], &m_globalSndOffsets[0], 5);
1190
1191 // Retrive information from other domains and update levelSet and lists
1192 for(MInt i = 0; i < grid().noDomains(); i++) {
1193 ind = m_globalSndOffsets[i];
1194 for(MInt j = 0; j < floatRcvBufSizeGlob(i); j++) {
1195 cellId = cellIdsLoc[i][j];
1196
1197 a_containingCell(cellId, b) = intRcvBufGlob(ind * intOffset + j * intOffset + 0);
1198 a_containingDomain(cellId, b) = intRcvBufGlob(ind * intOffset + j * intOffset + 1);
1199
1200 // Backup solution at restart
1201 if(firstRun && a_containingCell(cellId, b) < -1) {
1202 remCells.push_back(cellId);
1203 continue;
1204 }
1205
1206 a_levelSetFunctionG(cellId, set) = floatRcvBufGlob(ind + j);
1207 }
1208 }
1209
1210 // Backup method for restart. Search each cell in remCells on each domain. Very slow!!!!!
1211 if(firstRun) {
1212 for(MInt dom = 0; dom < grid().noDomains(); dom++) {
1213 MInt cnt = 0;
1214 if(domainId() == dom) {
1215 cnt = remCells.size();
1216 if(cnt > 0) cerr << "D:" << domainId() << " Restart Backup LS!" << endl;
1217 }
1218
1219 MPI_Bcast(&cnt, 1, MPI_INT, dom, MPI_COMM_WORLD, AT_, "cnt");
1220
1221 for(MInt c = 0; c < cnt; c++) {
1222 containingCell = -1;
1223 searchDomain = -2;
1224 if(domainId() == dom) {
1225 for(MInt i = 0; i < nDim; i++) {
1226 xCoord[i] = c_coordinate(remCells[c], i);
1227 }
1228 rotateLevelSet(1, xInitial, body, xCoord, xOld, &m_semiLagrange_xRot_ref[body * nDim]);
1229 for(MInt i = 0; i < nDim; i++) {
1230 xInitial[i] += xCurrent[i] - xOld[i];
1231 }
1232 }
1233
1234 MPI_Bcast(&xInitial[0], 3, maia::type_traits<MFloat>::mpiType(), dom, MPI_COMM_WORLD, AT_,
1235 "xInitial[0]");
1236
1237 containingCell = getContainingCell(xInitial);
1238
1239 if(containingCell > -1) {
1240 // This should be save, since only internalCells are investigated in getContainingCell!
1241 searchDomain = domainId();
1242
1243 processRotatingLevelSet(phiNew, containingCell, searchDomain, xInitial, set);
1244 }
1245 MPI_Allreduce(MPI_IN_PLACE, &searchDomain, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
1246 "searchDomain");
1247
1248 if(searchDomain != dom) {
1249 if(domainId() == searchDomain) {
1250 MPI_Send(&containingCell, 1, MPI_INT, dom, 5, mpiComm(), AT_, "containingCell");
1251 MPI_Send(&phiNew, 1, maia::type_traits<MFloat>::mpiType(), dom, 6, mpiComm(), AT_, "phiNew");
1252 }
1253 if(domainId() == dom) {
1254 MPI_Recv(&containingCell, 1, MPI_INT, searchDomain, 5, mpiComm(), MPI_STATUS_IGNORE, AT_,
1255 "containingCell");
1256 MPI_Recv(&phiNew, 1, maia::type_traits<MFloat>::mpiType(), searchDomain, 6, mpiComm(),
1257 MPI_STATUS_IGNORE, AT_, "phiNew");
1258 }
1259 }
1260
1261 if(domainId() == dom) {
1262 cellId = remCells[c];
1263 a_levelSetFunctionG(cellId, set) = phiNew;
1264 a_containingCell(cellId, b) = containingCell;
1265 a_containingDomain(cellId, b) = searchDomain;
1266 }
1267 }
1268 }
1269 }
1270
1271 // Set firstRun to false
1272 firstRun = false;
1273
1274 // Reset cells in shadow layer
1275 for(MInt i = 0; i < m_maxNoCells; i++) {
1276 if(!a_inBandG(i, set)) {
1277 a_containingCell(i, b) = -1;
1278 a_containingDomain(i, b) = -1;
1279 }
1280 }
1281 }
1282 }
1283
1284 // Finaly, update the bodies angular velocities. Neccessary for boundry condition
1285 for(MInt i = 0; i < m_noBodiesToCompute; i++) {
1286 body = m_bodiesToCompute[i];
1287 rotateLevelSet(5, &m_bodyAngularVelocity[body * nDim], body, nullptr, nullptr,
1288 &m_semiLagrange_xRot_STL[body * nDim]);
1289 }
1290
1291 break;
1292 }
1293 default: {
1294 stringstream errorMessage;
1295 errorMessage << "LsCartesianSolver::semiLagrangeTimeStep(): switch variable 'm_levelSetDiscretizationScheme' "
1296 "with value "
1297 << m_levelSetDiscretizationScheme << " not matching any case." << endl;
1298 mTerm(1, AT_, errorMessage.str());
1299 }
1300 }
1301
1302 return true;
1303}
1304//-----------------------------------------------------------------------------
1305
1306
1307template <MInt nDim>
1309 MInt gapMode) {
1310 TRACE();
1311
1312 NEW_TIMER_GROUP_STATIC(reInit, "Reinitialisation");
1313 NEW_TIMER_STATIC(t_reInit, "Total time - levelset Reinitialisation", reInit);
1314 NEW_SUB_TIMER_STATIC(t_c1, "preparation", t_reInit);
1315 NEW_SUB_TIMER_STATIC(t_c2, "solver", t_reInit);
1316
1317 RECORD_TIMER_START(t_reInit);
1318 RECORD_TIMER_START(t_c1);
1319
1320 // statistics only for start set! does not compute statistics for multiple level set functions!
1321 // #define REINITIALIZATION_STATISTICS
1322
1323 MBool upwind;
1324 MInt cellId;
1325 MInt cellListSize;
1326 MIntScratchSpace nghbr(m_noDirs, AT_, "nghbr");
1327 MInt counter;
1328 MFloatScratchSpace dx(nDim, AT_, "dx");
1329 MFloat eps = 0.000001;
1330 MFloatScratchSpace res(m_noSets, AT_, "res");
1331 MFloat smoothingTerm = F0;
1332 MFloat sumOfD;
1333 MFloat sumOfPhi;
1334 MIntScratchSpace reinit(m_maxNoCells * m_noSets, AT_, "reinit");
1335
1336#ifdef REINITIALIZATION_STATISTICS
1337
1338 MFloat avgGradient, maxGradient, minGradient, meanGradient, temp;
1339 MInt nghbrId;
1340 MFloatScratchSpace x(a_noBandCells(startSet) * m_noDirs, nDim, AT_, "x");
1341 MFloat variance;
1342 MFloat factor;
1343
1344#endif
1345 //--- end of initialization
1346
1347 // compute statistics
1348#ifdef REINITIALIZATION_STATISTICS
1349 counter = 0;
1350 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1351 cellId = a_G0CellId(id, startSet);
1352
1353 if(a_levelSetFunctionG(cellId, startSet) < F0) {
1354 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
1355 if(a_hasNeighbor(cellId, dirId) > 0) {
1356 nghbrId = c_neighborId(cellId, dirId);
1357 if(a_isGZeroCell(nghbrId, startSet) && a_levelSetFunctionG(nghbrId, startSet) > F0) {
1358 factor = ABS(a_levelSetFunctionG(cellId, startSet))
1359 / (ABS(a_levelSetFunctionG(nghbrId, startSet)) + ABS(a_levelSetFunctionG(cellId, startSet)));
1360 for(MInt i = 0; i < nDim; i++) {
1361 x(counter, i) = c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i));
1362 }
1363 counter++;
1364 }
1365 }
1366 }
1367 }
1368 }
1369
1370 // compute the reinitialization sensor
1371 avgGradient = F0, maxGradient = F0, minGradient = 1000.0, meanGradient = 0;
1372 variance = F0;
1373
1374 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1375 cellId = a_G0CellId(id, startSet);
1376
1377 temp = F0;
1378 for(MInt i = 0; i < nDim; i++) {
1379 temp += POW2(a_levelSetFunctionSlope(cellId, i, startSet));
1380 }
1381 temp = ABS(sqrt(temp));
1382
1383 avgGradient += ABS(temp - F1);
1384 meanGradient += temp;
1385 maxGradient = mMax(maxGradient, temp);
1386 minGradient = mMin(minGradient, temp);
1387 variance += POW2(temp);
1388 }
1389 avgGradient = avgGradient / (MFloat)a_noG0Cells(startSet);
1390 meanGradient = meanGradient / (MFloat)a_noG0Cells(startSet);
1391 variance = sqrt(variance) / (MFloat)a_noG0Cells(startSet);
1392 FILE* avg;
1393 avg = fopen("avgGradient", "a+");
1394 fprintf(avg, "%d", globalTimeStep);
1395 fprintf(avg, " %f", avgGradient * 1000.0);
1396 fprintf(avg, " %f", variance);
1397 fprintf(avg, " %f", meanGradient);
1398 fprintf(avg, " %f", maxGradient);
1399 fprintf(avg, " %f", minGradient);
1400 fprintf(avg, "\n");
1401 fclose(avg);
1402#endif
1403
1404
1405 // reset the reinit flag
1406 for(MInt set = startSet; set < endSet; set++) {
1407 if(!m_computeSet[set]) continue;
1408 for(MInt cell = 0; cell < a_internalBandLayer(0, set); cell++)
1409 reinit[IDX_LSSET(cell, set)] = 1;
1410 }
1411
1412 // determine the reinit property
1413 for(MInt set = startSet; set < endSet; set++) {
1414 if(!m_computeSet[set]) continue;
1415 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1416 cellId = a_internalBandCellId(id, set);
1417 for(MInt j = 0; j < m_noDirs; j++) {
1418 nghbr[j] = a_bandNghbrIdsG(cellId, j, set);
1419 }
1420 for(MInt i = 0; i < nDim; i++) {
1421 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(nghbr[2 * i], set) > F0
1422 && a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(a_bandNghbrIdsG(nghbr[2 * i], 2 * i, set), set)
1423 > F0) {
1424 continue;
1425 }
1426 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(nghbr[2 * i + 1], set) > F0
1427 && a_levelSetFunctionG(cellId, set)
1428 * a_levelSetFunctionG(a_bandNghbrIdsG(nghbr[2 * i + 1], 2 * i + 1, set), set)
1429 > F0) {
1430 continue;
1431 }
1432 reinit[IDX_LSSET(id, set)] = 0;
1433 i = nDim;
1434 }
1435 }
1436 }
1437
1438 // determine the signed distance of phi0 cells
1439 // -------------------------------------------
1440 for(MInt set = startSet; set < endSet; set++) {
1441 if(!m_computeSet[set]) continue;
1442 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1443 cellId = a_internalBandCellId(id, set);
1444 if(reinit[IDX_LSSET(id, set)] == 0) {
1445 m_d[IDX_LSSET(cellId, set)] = a_levelSetFunctionG(cellId, set);
1446 continue;
1447 }
1448
1449 for(MInt j = 0; j < m_noDirs; j++) {
1450 nghbr[j] = a_bandNghbrIdsG(cellId, j, set);
1451 }
1452
1453 for(MInt i = 0; i < nDim; i++) {
1454 upwind = false;
1455 dx[i] = F2 * m_gCellDistance;
1456 if(!a_isGZeroCell(nghbr[2 * i], set)) {
1457 nghbr[2 * i] = cellId;
1458 upwind = true;
1459 dx[i] -= m_gCellDistance;
1460 }
1461 if(!a_isGZeroCell(nghbr[2 * i + 1], set)) {
1462 nghbr[2 * i + 1] = cellId;
1463 upwind = true;
1464 dx[i] -= m_gCellDistance;
1465 }
1466
1467 if(!upwind) {
1468 if(a_levelSetFunctionG(nghbr[2 * i], set) * a_levelSetFunctionG(nghbr[2 * i + 1], set) < F0) {
1469 if((a_levelSetFunctionG(nghbr[2 * i], set) - a_levelSetFunctionG(cellId, set))
1470 * (a_levelSetFunctionG(nghbr[2 * i + 1], set) - a_levelSetFunctionG(cellId, set))
1471 > F0
1472 || a_levelSetFunctionG(nghbr[2 * i], set)
1473 * a_levelSetFunctionG(a_bandNghbrIdsG(nghbr[2 * i], 2 * i, set), set)
1474 < F0
1475 || a_levelSetFunctionG(nghbr[2 * i + 1], set)
1476 * a_levelSetFunctionG(a_bandNghbrIdsG(nghbr[2 * i + 1], 2 * i + 1, set), set)
1477 < F0) {
1478 if(fabs(a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(nghbr[2 * i], set))
1479 > fabs(a_levelSetFunctionG(nghbr[2 * i + 1], set) - a_levelSetFunctionG(cellId, set) + eps)) {
1480 nghbr[2 * i + 1] = cellId;
1481 dx[i] -= m_gCellDistance;
1482 }
1483 if(fabs(a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(nghbr[2 * i], set) + eps)
1484 < fabs(a_levelSetFunctionG(nghbr[2 * i + 1], set) - a_levelSetFunctionG(cellId, set))) {
1485 nghbr[2 * i] = cellId;
1486 dx[i] -= m_gCellDistance;
1487 }
1488 }
1489 }
1490 }
1491 }
1492
1493 // compute the sdf at the front
1494 m_d[IDX_LSSET(cellId, set)] = F0;
1495 for(MInt i = 0; i < nDim; i++) {
1496 dx[i] = mMax(eps, dx[i]);
1497 m_d[IDX_LSSET(cellId, set)] +=
1498 POW2((a_levelSetFunctionG(nghbr[2 * i + 1], set) - a_levelSetFunctionG(nghbr[2 * i], set)) / dx[i]);
1499 }
1500 m_d[IDX_LSSET(cellId, set)] = F1 / sqrt(m_d[IDX_LSSET(cellId, set)]);
1501 m_d[IDX_LSSET(cellId, set)] *= a_levelSetFunctionG(cellId, set);
1502 }
1503 }
1504
1505 // parallel version: exchange d
1506 exchangeLs(m_d, 0, m_maxNoSets);
1507
1508 // determine r for each cell and space direction (stored in m_phiRatio)
1509 for(MInt set = startSet; set < endSet; set++) {
1510 if(!m_computeSet[set]) continue;
1511 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1512 cellId = a_internalBandCellId(id, set);
1513 for(MInt j = 0; j < m_noDirs; j++) {
1514 m_phiRatioCells[cellId][IDX_LSSET(j, set)] = -1;
1515 }
1516 for(MInt j = 0; j < m_noDirs; j++) {
1517 nghbr[j] = a_bandNghbrIdsG(cellId, j, set);
1518 if(a_levelSetFunctionG(nghbr[j], set) * a_levelSetFunctionG(cellId, set) < F0) {
1519 m_phiRatioCells[cellId][IDX_LSSET(j, set)] = nghbr[j];
1520 m_phiRatio[cellId][IDX_LSSET(j, set)] = a_levelSetFunctionG(cellId, set) / a_levelSetFunctionG(nghbr[j], set);
1521 }
1522 }
1523 }
1524 }
1525
1526 for(MInt set = startSet; set < endSet; set++) {
1527 if(!m_computeSet[set]) continue;
1528 // reinitialization scheme CR-1
1529 // ----------------------------
1530 if(methodId == 1) {
1531 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1532 cellId = a_internalBandCellId(id, set);
1533 if((a_curvatureG(cellId, set) >= F0 && a_levelSetFunctionG(cellId, set) < F0)
1534 || (a_curvatureG(cellId, set) < F0 && a_levelSetFunctionG(cellId, set) > F0)) {
1535 m_correction[IDX_LSSET(cellId, set)] = F0;
1536 counter = 0;
1537 for(MInt i = 0; i < m_noDirs; i++) {
1538 if(m_phiRatioCells[cellId][IDX_LSSET(i, set)] != -1) {
1539 m_correction[IDX_LSSET(cellId, set)] += m_d[IDX_LSSET(m_phiRatioCells[cellId][IDX_LSSET(i, set)], set)]
1540 * m_phiRatio[cellId][IDX_LSSET(i, set)];
1541 counter++;
1542 }
1543 }
1544 if(counter > 0)
1545 m_correction[IDX_LSSET(cellId, set)] = m_correction[IDX_LSSET(cellId, set)] / (MFloat)counter;
1546 else
1547 m_correction[IDX_LSSET(cellId, set)] = m_d[IDX_LSSET(cellId, set)];
1548 } else {
1549 m_correction[IDX_LSSET(cellId, set)] = m_d[IDX_LSSET(cellId, set)];
1550 }
1551 }
1552 for(MInt id = 0; id < a_noG0Cells(set); id++) {
1553 cellId = a_G0CellId(id, set);
1554 m_d[IDX_LSSET(cellId, set)] = m_correction[IDX_LSSET(cellId, set)];
1555 }
1556 }
1557
1558 // reinitialization scheme CR-2
1559 // ----------------------------
1560 if(methodId == 2) {
1561 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1562 cellId = a_internalBandCellId(id, set);
1563
1564 if((a_curvatureG(cellId, set) >= F0 && a_levelSetFunctionG(cellId, set) < F0)
1565 || (a_curvatureG(cellId, set) < F0 && a_levelSetFunctionG(cellId, set) > F0)) {
1566 counter = 0;
1567 sumOfD = 0;
1568 sumOfPhi = 0;
1569 for(MInt i = 0; i < m_noDirs; i++) {
1570 if(m_phiRatioCells[cellId][IDX_LSSET(i, set)] != -1) {
1571 sumOfD += m_d[IDX_LSSET(m_phiRatioCells[cellId][IDX_LSSET(i, set)], set)];
1572 sumOfPhi += a_levelSetFunctionG(m_phiRatioCells[cellId][IDX_LSSET(i, set)], set);
1573 counter++;
1574 }
1575 }
1576 if(counter > 0)
1577 m_correction[IDX_LSSET(cellId, set)] = a_levelSetFunctionG(cellId, set) * sumOfD / sumOfPhi;
1578 else
1579 m_correction[IDX_LSSET(cellId, set)] = m_d[IDX_LSSET(cellId, set)];
1580 } else {
1581 m_correction[IDX_LSSET(cellId, set)] = m_d[IDX_LSSET(cellId, set)];
1582 }
1583 }
1584 for(MInt id = 0; id < a_noG0Cells(set); id++) {
1585 cellId = a_G0CellId(id, set);
1586 m_d[IDX_LSSET(cellId, set)] = m_correction[IDX_LSSET(cellId, set)];
1587 }
1588 }
1589
1590 // set phi_0 = d
1591 for(MInt id = 0; id < a_internalBandLayer(0, set); id++)
1592 if(reinit[IDX_LSSET(id, set)] != 0)
1593 a_levelSetFunctionG(a_internalBandCellId(id, set), set) +=
1594 m_omegaReinit
1595 * (m_d[IDX_LSSET(a_internalBandCellId(id, set), set)]
1596 - a_levelSetFunctionG(a_internalBandCellId(id, set), set));
1597
1598 // compute sign(G) and a_hasPositiveSign(G)
1599 for(MInt id = 0; id < a_noInternalBandCells(set); id++) {
1600 cellId = a_internalBandCellId(id, set);
1601 m_signG[IDX_LSSET(cellId, set)] =
1602 a_levelSetFunctionG(cellId, set) / sqrt(POW2(a_levelSetFunctionG(cellId, set)) + POW2(smoothingTerm));
1603 if(a_levelSetFunctionG(cellId, set) > F0) {
1604 a_hasPositiveSign(cellId, set) = true;
1605 } else {
1606 a_hasPositiveSign(cellId, set) = false;
1607 }
1608 }
1609
1610 exchangeLevelSet();
1611
1612 // call the Eikonal solver
1613 // -----------------------
1614 // fill the cell list and levelSetFunction
1615 cellListSize = 0;
1616 for(MInt id = 0; id < a_noInternalBandCells(set); id++) {
1617 cellId = a_internalBandCellId(id, set);
1618
1619 if(gapMode == 0) {
1620 if(!a_isGZeroCell(cellId, set) && a_nearGapG(cellId) > 0 && a_potentialGapCellClose(cellId)) {
1621 m_cellList[cellListSize] = cellId;
1622 cellListSize++;
1623 }
1624 } else {
1625 if(!a_isGZeroCell(cellId, set)) {
1626 m_cellList[cellListSize] = cellId;
1627 cellListSize++;
1628 }
1629 }
1630 }
1631
1632 RECORD_TIMER_STOP(t_c1);
1633 RECORD_TIMER_START(t_c2);
1634 res[set] = firstOrderEikonalSolver(cellListSize, m_gReinitIterations, set);
1635 RECORD_TIMER_STOP(t_c2);
1636 RECORD_TIMER_START(t_c1);
1637#ifndef NDEBUG
1638 m_log << "Reinitialization finished at ts " << globalTimeStep << ": " << res[set] << endl;
1639#endif
1640 }
1641
1642 // statistics
1643#ifdef REINITIALIZATION_STATISTICS
1644 counter = 0;
1645 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1646 cellId = a_G0CellId(id, startSet);
1647 if(a_levelSetFunctionG(cellId, startSet) < F0) {
1648 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
1649 if(a_hasNeighbor(cellId, dirId) > 0) {
1650 nghbrId = c_neighborId(cellId, dirId);
1651 if(a_isGZeroCell(nghbrId, startSet) && a_levelSetFunctionG(nghbrId, startSet) > F0) {
1652 factor = ABS(a_levelSetFunctionG(cellId, startSet))
1653 / (ABS(a_levelSetFunctionG(nghbrId, startSet)) + ABS(a_levelSetFunctionG(cellId, startSet)));
1654 for(MInt i = 0; i < nDim; i++) {
1655 x(counter, i) =
1656 100
1657 * (x(counter, i)
1658 - (c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i))));
1659 }
1660 counter++;
1661 }
1662 }
1663 }
1664 }
1665 }
1666 MFloat deviation = F0;
1667 for(MInt it = 0; it < counter; it++) {
1668 factor = F0;
1669 for(MInt i = 0; i < nDim; i++)
1670 factor += POW2(x(it, i));
1671 deviation += sqrt(factor);
1672 }
1673 deviation = deviation * 1000.0 / (MFloat)counter;
1674 FILE* dev;
1675 dev = fopen("deviation", "a+");
1676 fprintf(dev, "%d", globalTimeStep);
1677 fprintf(dev, " %f", deviation);
1678 fprintf(dev, "\n");
1679 fclose(dev);
1680
1681 //
1682 computeNormalVectors();
1683
1684 avgGradient = F0, maxGradient = F0, minGradient = 1000.0;
1685 variance = F0;
1686
1687 MInt nghbrL, nghbrL2, nghbrR, nghbrR2;
1688 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1689 cellId = a_G0CellId(id, startSet);
1690
1691 temp = F0;
1692 for(MInt i = 0; i < nDim; i++) {
1693 // compute the fourth-order gradient
1694 nghbrL = a_bandNghbrIdsG(cellId, 2 * i, startSet);
1695 nghbrL2 = a_bandNghbrIdsG(nghbrL, 2 * i, startSet);
1696 nghbrR = a_bandNghbrIdsG(cellId, 2 * i + 1, startSet);
1697 nghbrR2 = a_bandNghbrIdsG(nghbrR, 2 * i + 1, startSet);
1698 a_levelSetFunctionSlope(cellId, i, startSet) =
1699 m_FgCellDistance
1700 * (F2B3 * (a_levelSetFunctionG(nghbrR, startSet) - a_levelSetFunctionG(nghbrL, startSet))
1701 - F1B12 * (a_levelSetFunctionG(nghbrR2, startSet) - a_levelSetFunctionG(nghbrL2, startSet)));
1702 temp += POW2(a_levelSetFunctionSlope(cellId, i, startSet));
1703 }
1704 temp = ABS(sqrt(temp));
1705
1706 avgGradient += ABS(temp - F1);
1707 meanGradient += temp;
1708 maxGradient = mMax(maxGradient, temp);
1709 minGradient = mMin(minGradient, temp);
1710 variance += POW2(temp);
1711 }
1712 avgGradient = avgGradient / (MFloat)a_noG0Cells(startSet);
1713 meanGradient = meanGradient / (MFloat)a_noG0Cells(startSet);
1714 variance = sqrt(variance) / (MFloat)a_noG0Cells(startSet);
1715 FILE* avg2;
1716 avg2 = fopen("avgGradientAfter", "a+");
1717 fprintf(avg2, "%d", globalTimeStep);
1718 fprintf(avg2, " %f", avgGradient * 1000.0);
1719 fprintf(avg2, " %f", variance);
1720 fprintf(avg2, " %f", meanGradient);
1721 fprintf(avg2, " %f", maxGradient);
1722 fprintf(avg2, " %f", minGradient);
1723 fprintf(avg2, "\n");
1724 fclose(avg2);
1725
1726#endif
1727
1728 RECORD_TIMER_STOP(t_c1);
1729 RECORD_TIMER_STOP(t_reInit);
1730}
1731//-----------------------------------------------------------------------------
1732
1739template <MInt nDim>
1741 MInt gapMode) {
1742 TRACE();
1743
1744 MInt cellId;
1745 MInt cellListSize;
1746 MInt counter;
1747 MInt counter2;
1748 MFloat smoothingTerm = m_gCellDistance;
1749 MFloat sumOfPhi;
1750
1751
1752 MFloatScratchSpace res(m_noSets, AT_, "res");
1753 MInt noCellsToCorrect = 0;
1754 MIntScratchSpace cellsToCorrect(m_maxNoCells, AT_, "cellsToCorrect");
1755 MFloatScratchSpace factors(m_maxNoCells, AT_, "factors");
1756
1757 // output
1758 MInt nghbrId;
1759 MFloat avgGradient;
1760 MFloat maxGradient;
1761 MFloat minGradient;
1762 MFloat meanGradient = F0;
1763 MFloat factor;
1764 MFloat temp;
1765 MFloat variance;
1766 MFloat** x;
1767 //--- end of initialization
1768
1769 // statistics output for startSet only, no statistics for other sets given!
1770 if(!m_writeReinitializationStatistics) {
1771 x = (MFloat**)nullptr;
1772 } else {
1773 x = new MFloat*[a_noBandCells(startSet) * m_noDirs];
1774 }
1775 if(m_writeReinitializationStatistics) {
1776 for(MInt cell = 0; cell < a_noBandCells(startSet) * m_noDirs; cell++)
1777 x[cell] = new MFloat[nDim];
1778 // FOR PUBLICATION OUTPUT ONLY!!!
1779 // determine the original position of the interface
1780 counter = 0;
1781 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1782 cellId = a_G0CellId(id, startSet);
1783
1784 if(a_levelSetFunctionG(cellId, startSet) < F0) {
1785 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
1786 if(a_hasNeighbor(cellId, dirId) > 0) {
1787 nghbrId = c_neighborId(cellId, dirId);
1788 if(a_isGZeroCell(nghbrId, startSet) && a_levelSetFunctionG(nghbrId, startSet) > F0) {
1789 factor = ABS(a_levelSetFunctionG(cellId, startSet))
1790 / (ABS(a_levelSetFunctionG(nghbrId, startSet)) + ABS(a_levelSetFunctionG(cellId, startSet)));
1791 for(MInt i = 0; i < nDim; i++) {
1792 x[counter][i] = c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i));
1793 }
1794 counter++;
1795 }
1796 }
1797 }
1798 }
1799 }
1800 }
1801
1802 for(MInt set = startSet; set < endSet; set++) {
1803 if(!m_computeSet[set]) continue;
1804 // compute sign(G) and a_hasPositiveSign(G)
1805 for(MInt id = 0; id < a_noBandCells(set); id++) {
1806 cellId = a_bandCellId(id, set);
1807 m_signG[IDX_LSSET(cellId, set)] =
1808 a_levelSetFunctionG(cellId, set) / sqrt(POW2(a_levelSetFunctionG(cellId, set)) + POW2(smoothingTerm));
1809 if(a_levelSetFunctionG(cellId, set) > F0) {
1810 a_hasPositiveSign(cellId, set) = true;
1811 } else {
1812 a_hasPositiveSign(cellId, set) = false;
1813 }
1814 }
1815
1816
1817 // fill the cell list
1818 cellListSize = 0;
1819 for(MInt id = 0; id < a_noBandCells(set); id++) {
1820 cellId = a_bandCellId(id, set);
1821 if(gapMode == 0) {
1822 if(!a_isGZeroCell(cellId, set) && a_nearGapG(cellId) > 0 && a_potentialGapCellClose(cellId)) {
1823 m_cellList[cellListSize] = cellId;
1824 cellListSize++;
1825 }
1826 } else {
1827 m_cellList[cellListSize] = cellId;
1828 cellListSize++;
1829 }
1830 }
1831
1832 // determine r for each cell and space direction (stored in m_phiRatio)
1833 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1834 cellId = a_internalBandCellId(id, set);
1835 for(MInt j = 0; j < m_noDirs; j++)
1836 m_phiRatioCells[cellId][IDX_LSSET(j, set)] = -1;
1837 for(MInt j = 0; j < m_noDirs; j++) {
1838 if(a_levelSetFunctionG(a_bandNghbrIdsG(cellId, j, set), set) * a_levelSetFunctionG(cellId, set) < F0) {
1839 m_phiRatioCells[cellId][IDX_LSSET(j, set)] = a_bandNghbrIdsG(cellId, j, set);
1840 m_phiRatio[cellId][IDX_LSSET(j, set)] =
1841 a_levelSetFunctionG(cellId, set) / a_levelSetFunctionG(a_bandNghbrIdsG(cellId, j, set), set);
1842 }
1843 }
1844 }
1845
1846 // compute the forcing terms and call the Eikonal solver
1847
1848 // reinitialization scheme CR-1
1849 // ----------------------------
1850 if(methodId == 1) {
1851 counter2 = 0;
1852 noCellsToCorrect = 0;
1853 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1854 cellId = a_internalBandCellId(id, set);
1855 m_correction[IDX_LSSET(cellId, set)] = F0;
1856 counter = 0;
1857 for(MInt i = 0; i < m_noDirs; i++) {
1858 if(m_phiRatioCells[cellId][IDX_LSSET(i, set)] != -1) {
1859 factors.p[counter2++] =
1860 a_levelSetFunctionG(cellId, set) / a_levelSetFunctionG(m_phiRatioCells[cellId][IDX_LSSET(i, set)], set);
1861 counter++;
1862 }
1863 }
1864 if(counter > 0) cellsToCorrect.p[noCellsToCorrect++] = cellId;
1865 }
1866
1867 res[set] = fifthOrderEikonalSolver(cellListSize, m_gReinitIterations, cellsToCorrect.getPointer(),
1868 noCellsToCorrect, factors.getPointer(), 1, set);
1869 }
1870
1871 // reinitialization scheme CR-2
1872 // ----------------------------
1873 if(methodId == 2 || methodId == 4 || methodId == 6) {
1874 noCellsToCorrect = 0;
1875 for(MInt id = 0; id < a_internalBandLayer(0, set); id++) {
1876 cellId = a_internalBandCellId(id, set);
1877 counter = 0;
1878 sumOfPhi = 0;
1879 for(MInt i = 0; i < m_noDirs; i++) {
1880 if(m_phiRatioCells[cellId][IDX_LSSET(i, set)] != -1) {
1881 sumOfPhi += a_levelSetFunctionG(m_phiRatioCells[cellId][IDX_LSSET(i, set)], set);
1882 counter++;
1883 }
1884 }
1885 factors.p[noCellsToCorrect] = a_levelSetFunctionG(cellId, set) / sumOfPhi;
1886 if(counter > 0) cellsToCorrect.p[noCellsToCorrect++] = cellId;
1887 }
1888 if(methodId == 2)
1889 res[set] = fifthOrderEikonalSolver(cellListSize, m_gReinitIterations, cellsToCorrect.getPointer(),
1890 noCellsToCorrect, factors.getPointer(), 2, set);
1891 else if(methodId == 4)
1892 res[set] = fifthOrderEikonalSolver(cellListSize, m_gReinitIterations, cellsToCorrect.getPointer(),
1893 noCellsToCorrect, factors.getPointer(), 4, set);
1894 else if(methodId == 6)
1895 res[set] = fifthOrderEikonalSolver(cellListSize, m_gReinitIterations, cellsToCorrect.getPointer(),
1896 noCellsToCorrect, factors.getPointer(), 6, set);
1897 }
1898 }
1899
1900 if(domainId() == 0) {
1901 // write out info
1902 FILE* datei = nullptr;
1903 stringstream reinitFile;
1904 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
1905 datei = fopen((reinitFile.str()).c_str(), "a+");
1906 fprintf(datei, " %-10.8f reinitialized", res[startSet]);
1907 fclose(datei);
1908 }
1909
1910 if(m_writeReinitializationStatistics) {
1911 // FOR PUBLICATION OUTPUT ONLY!!!
1912 counter = 0;
1913 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1914 cellId = a_G0CellId(id, startSet);
1915 if(a_levelSetFunctionG(cellId, startSet) < F0) {
1916 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
1917 if(a_hasNeighbor(cellId, dirId) > 0) {
1918 nghbrId = c_neighborId(cellId, dirId);
1919 if(a_isGZeroCell(nghbrId, startSet) && a_levelSetFunctionG(nghbrId, startSet) > F0) {
1920 factor = ABS(a_levelSetFunctionG(cellId, startSet))
1921 / (ABS(a_levelSetFunctionG(nghbrId, startSet)) + ABS(a_levelSetFunctionG(cellId, startSet)));
1922 for(MInt i = 0; i < nDim; i++) {
1923 x[counter][i] =
1924 100
1925 * (x[counter][i]
1926 - (c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i))));
1927 }
1928 counter++;
1929 }
1930 }
1931 }
1932 }
1933 }
1934 MFloat deviation = F0;
1935 for(MInt it = 0; it < counter; it++) {
1936 factor = F0;
1937 for(MInt i = 0; i < nDim; i++)
1938 factor += POW2(x[it][i]);
1939 deviation += sqrt(factor);
1940 }
1941 deviation = deviation * 1000.0 / (MFloat)counter;
1942 FILE* dev = nullptr;
1943 dev = fopen("deviation", "a+");
1944 fprintf(dev, "%d", globalTimeStep);
1945 fprintf(dev, " %f", deviation);
1946 fprintf(dev, "\n");
1947 fclose(dev);
1948
1949 avgGradient = F0, maxGradient = F0, minGradient = 1000.0;
1950 variance = F0;
1951
1952 MInt nghbrL;
1953 MInt nghbrL2;
1954 MInt nghbrR;
1955 MInt nghbrR2;
1956 for(MInt id = 0; id < a_noG0Cells(startSet); id++) {
1957 cellId = a_G0CellId(id, startSet);
1958
1959 temp = F0;
1960 for(MInt i = 0; i < nDim; i++) {
1961 // compute the fourth-order gradient
1962 nghbrL = a_bandNghbrIdsG(cellId, 2 * i, startSet);
1963 nghbrL2 = a_bandNghbrIdsG(nghbrL, 2 * i, startSet);
1964 nghbrR = a_bandNghbrIdsG(cellId, 2 * i + 1, startSet);
1965 nghbrR2 = a_bandNghbrIdsG(nghbrR, 2 * i + 1, startSet);
1966 a_levelSetFunctionSlope(cellId, i, startSet) =
1967 m_FgCellDistance
1968 * (F2B3 * (a_levelSetFunctionG(nghbrR, startSet) - a_levelSetFunctionG(nghbrL, startSet))
1969 - F1B12 * (a_levelSetFunctionG(nghbrR2, startSet) - a_levelSetFunctionG(nghbrL2, startSet)));
1970 temp += POW2(a_levelSetFunctionSlope(cellId, i, startSet));
1971 }
1972 temp = ABS(sqrt(temp));
1973
1974 avgGradient += ABS(temp - F1);
1975 meanGradient += temp;
1976 maxGradient = mMax(maxGradient, temp);
1977 minGradient = mMin(minGradient, temp);
1978 variance += POW2(temp);
1979 }
1980 avgGradient = avgGradient / (MFloat)a_noG0Cells(startSet);
1981 meanGradient = meanGradient / (MFloat)a_noG0Cells(startSet);
1982 variance = sqrt(variance) / (MFloat)a_noG0Cells(startSet);
1983 FILE* avg2;
1984 avg2 = fopen("avgGradientAfter", "a+");
1985 fprintf(avg2, "%d", globalTimeStep);
1986 fprintf(avg2, " %f", avgGradient * 1000.0);
1987 fprintf(avg2, " %f", variance);
1988 fprintf(avg2, " %f", meanGradient);
1989 fprintf(avg2, " %f", maxGradient);
1990 fprintf(avg2, " %f", minGradient);
1991 fprintf(avg2, "\n");
1992 fclose(avg2);
1993
1994 // free memory
1995 for(MInt cell = 0; cell < a_noBandCells(startSet) * m_noDirs; cell++)
1996 delete[] x[cell];
1997 delete[] x;
1998 x = nullptr;
1999 }
2000}
2001
2002
2003//-----------------------------------------------------------------------------
2004
2005
2006template <MInt nDim>
2007void LsCartesianSolver<nDim>::maintainOuterBandLayers(MInt order, MInt startSet, MInt endSet) {
2008 TRACE();
2009
2010 MInt cellId;
2011 MInt cellListSize;
2012 MFloat smoothingTerm = m_gCellDistance;
2013 MFloatScratchSpace res(m_noSets, AT_, "res");
2014 auto startBand = (MInt)(m_gBandWidth / 2);
2015 if(startBand > 6) startBand = 6;
2016 //--- end of initialization
2017
2018 for(MInt set = startSet; set < endSet; set++) {
2019 if(!m_computeSet[set]) continue;
2020 // compute sign(G) and a_hasPositiveSign(G)
2021 for(MInt id = 0; id < a_noBandCells(set); id++) {
2022 cellId = a_bandCellId(id, set);
2023 m_signG[IDX_LSSET(cellId, set)] =
2024 a_levelSetFunctionG(cellId, set) / sqrt(POW2(a_levelSetFunctionG(cellId, set)) + POW2(smoothingTerm));
2025 if(a_levelSetFunctionG(cellId, set) > F0) {
2026 a_hasPositiveSign(cellId, set) = true;
2027 } else {
2028 a_hasPositiveSign(cellId, set) = false;
2029 }
2030 }
2031
2032 // fill the cell list
2033 cellListSize = 0;
2034 for(MInt id = a_bandLayer(startBand, set); id < a_noBandCells(set); id++) {
2035 cellId = a_bandCellId(id, set);
2036 m_cellList[cellListSize] = cellId;
2037 cellListSize++;
2038 }
2039
2040 switch(order) {
2041 case 1:
2042 res[set] = firstOrderEikonalSolver(cellListSize, m_maintenanceIterations, set);
2043 break;
2044 case 5:
2045 res[set] =
2046 fifthOrderEikonalSolver(cellListSize, m_maintenanceIterations, (MInt*)nullptr, 0, (MFloat*)nullptr, 0, set);
2047 break;
2048 default: {
2049 stringstream errorMessage;
2050 errorMessage << "LsCartesianSolver::maintainOuterBandLayers(): switch variable 'order' with value " << order
2051 << " not matching any case." << endl;
2052 mTerm(1, AT_, errorMessage.str());
2053 }
2054 }
2055 }
2056 // write out info
2057 FILE* datei;
2058 stringstream reinitFile;
2059 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
2060 datei = fopen((reinitFile.str()).c_str(), "a+");
2061 fprintf(datei, " %f maintained", res[startSet]);
2062 fclose(datei);
2063}
2064
2065
2066//-----------------------------------------------------------------------------
2067
2068
2069//-----------------------------------------------------------------------------
2077template <MInt nDim>
2079 TRACE();
2080 MInt counter;
2081 MInt cellId;
2082 MInt nghbrId;
2083 MFloat Fcounter;
2084 MFloat factor;
2085 MInt set = 0; // operates on zeroth level-set function only!
2086 MFloatScratchSpace x(a_noBandCells(set) * nDim, AT_, "x");
2087
2088 //---
2089
2090 // determine all the G0 points
2091 counter = 0;
2092 for(MInt id = 0; id < a_noG0Cells(set); id++) {
2093 cellId = a_G0CellId(id, set);
2094 if(a_isHalo(cellId)) continue;
2095
2096 if(a_levelSetFunctionG(cellId, set) < F0) {
2097 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
2098 if(a_hasNeighbor(cellId, dirId) > 0) {
2099 nghbrId = c_neighborId(cellId, dirId);
2100 if(a_isGZeroCell(nghbrId, set) && a_levelSetFunctionG(nghbrId, set) > F0) {
2101 factor = ABS(a_levelSetFunctionG(cellId, set))
2102 / (ABS(a_levelSetFunctionG(nghbrId, set)) + ABS(a_levelSetFunctionG(cellId, set)));
2103 for(MInt i = 0; i < nDim; i++) {
2104 x.p[counter * nDim + i] =
2105 c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i));
2106 }
2107 counter++;
2108 }
2109 }
2110 }
2111 }
2112 }
2113
2114 // determine the min, max, and mean values
2115 Fcounter = F1 / (MFloat)counter;
2116 for(MInt i = 0; i < nDim; i++) {
2117 m_minFlameFrontPosition[i] = 10000.0;
2118 m_maxFlameFrontPosition[i] = -10000.0;
2119 m_meanFlameFrontPosition[i] = F0;
2120 }
2121 for(MInt p = 0; p < counter; p++) {
2122 for(MInt i = 0; i < nDim; i++) {
2123 m_minFlameFrontPosition[i] = mMin(m_minFlameFrontPosition[i], x.p[nDim * p + i]);
2124 m_maxFlameFrontPosition[i] = mMax(m_maxFlameFrontPosition[i], x.p[nDim * p + i]);
2125 m_meanFlameFrontPosition[i] += x.p[nDim * p + i] * Fcounter;
2126 }
2127 }
2128 // exchange min/max/mean flame front position
2129 for(MInt i = 0; i < nDim; i++) {
2130 MPI_Allreduce(MPI_IN_PLACE, &m_minFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "MPI_IN_PLACE",
2131 "m_minFlameFrontPosition[i]");
2132 MPI_Allreduce(MPI_IN_PLACE, &m_maxFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
2133 "m_maxFlameFrontPosition[i]");
2134 MPI_Allreduce(MPI_IN_PLACE, &m_meanFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
2135 "m_meanFlameFrontPosition[i]");
2136 }
2137}
2138
2139//-----------------------------------------------------------------------------
2148template <MInt nDim>
2150 TRACE();
2151
2152 if(m_steadyFlameLength > -F1) {
2153 m_steadyFlameAngle = -F1;
2154 m_log << "WARINING: steady flame front length should be defined correctly in your properties.cdl " << endl;
2155 m_steadyFlameAngle = atan(m_steadyFlameLength / m_realRadiusFlameTube) * 180. / PI;
2156
2157 m_log << "steadyFlameLength is : " << m_steadyFlameLength << endl;
2158 m_log << "uncurved flame base angle in Grad: " << m_steadyFlameAngle << endl;
2159 m_log << "flame surface slope is: " << tan(m_steadyFlameAngle * PI / 180.0) << endl;
2160 }
2161
2162 if(approx(m_steadyFlameLength, -F1, MFloatEps) && m_forcing) {
2163 MString errorMessage = "ERROR: steady flame length is not determined!!! should be defined for forced flames";
2164 mTerm(1, AT_, errorMessage);
2165 }
2166}
2167
2168//-----------------------------------------------------------------------------
2178template <MInt nDim>
2180 MFloat yRegP, MInt set) {
2181 TRACE();
2182
2183 MInt counter;
2184 MInt cellId;
2185 MInt nghbrId;
2186 MFloat Fcounter;
2187 MFloat factor;
2188 MFloatScratchSpace x(a_noBandCells(set) * nDim, AT_, "x");
2189 //---
2190
2191 // determine all the G0 points
2192 counter = 0;
2193 for(MInt id = 0; id < a_noG0Cells(set); id++) {
2194 cellId = a_G0CellId(id, set);
2195
2196 if(c_coordinate(cellId, 0) > xRegP) continue;
2197 if(c_coordinate(cellId, 0) < xRegN) continue;
2198 if(c_coordinate(cellId, 1) > yRegP) continue;
2199 if(c_coordinate(cellId, 1) < yRegN) continue;
2200 if(a_levelSetFunctionG(cellId, set) < F0) {
2201 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
2202 if(a_hasNeighbor(cellId, dirId) > 0) {
2203 nghbrId = c_neighborId(cellId, dirId);
2204 if(a_isGZeroCell(nghbrId, set) && a_levelSetFunctionG(nghbrId, set) > F0) {
2205 factor = ABS(a_levelSetFunctionG(cellId, set))
2206 / (ABS(a_levelSetFunctionG(nghbrId, set)) + ABS(a_levelSetFunctionG(cellId, set)));
2207 for(MInt i = 0; i < nDim; i++) {
2208 x.p[counter * nDim + i] =
2209 c_coordinate(cellId, i) + factor * (c_coordinate(nghbrId, i) - c_coordinate(cellId, i));
2210 }
2211 counter++;
2212 }
2213 }
2214 }
2215 }
2216 }
2217
2218 // determine the min, max, and mean values
2219 Fcounter = F1 / (MFloat)counter;
2220 for(MInt i = 0; i < nDim; i++) {
2221 m_minFlameFrontPosition[i] = 10000.0;
2222 m_maxFlameFrontPosition[i] = -10000.0;
2223 m_meanFlameFrontPosition[i] = F0;
2224 }
2225 for(MInt p = 0; p < counter; p++) {
2226 for(MInt i = 0; i < nDim; i++) {
2227 m_minFlameFrontPosition[i] = mMin(m_minFlameFrontPosition[i], x.p[nDim * p + i]);
2228 m_maxFlameFrontPosition[i] = mMax(m_maxFlameFrontPosition[i], x.p[nDim * p + i]);
2229 m_meanFlameFrontPosition[i] += x.p[nDim * p + i] * Fcounter;
2230 }
2231 }
2232
2233 // exchange min/max/mean flame front position
2234 for(MInt i = 0; i < nDim; i++) {
2235 MPI_Allreduce(MPI_IN_PLACE, &m_minFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
2236 "m_minFlameFrontPosition[i]");
2237 MPI_Allreduce(MPI_IN_PLACE, &m_maxFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
2238 "m_maxFlameFrontPosition[i]");
2239 MPI_Allreduce(MPI_IN_PLACE, &m_meanFlameFrontPosition[i], 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
2240 "m_meanFlameFrontPosition[i]");
2241 }
2242}
2243
2244
2245//-----------------------------------------------------------------------------
2246
2247
2248template <MInt nDim>
2249void LsCartesianSolver<nDim>::reinitBand(MInt startSet, MInt endSet) {
2250 TRACE();
2251
2252 MInt cellId;
2253 MInt cellListSize;
2254 MFloatScratchSpace res(m_noSets, AT_, "res");
2255 //---
2256
2257 // based on Sussman, JCP 1994
2258
2259 for(MInt set = startSet; set < endSet; set++) {
2260 if(!m_computeSet[set]) continue;
2261 // compute sign(G) and a_hasPositiveSign(G)
2262 for(MInt id = 0; id < a_noBandCells(set); id++) {
2263 cellId = a_bandCellId(id, set);
2264 m_signG[IDX_LSSET(cellId, set)] = a_levelSetFunctionG(cellId, set) / ABS(a_levelSetFunctionG(cellId, set));
2265 if(a_levelSetFunctionG(cellId, set) > F0) {
2266 a_hasPositiveSign(cellId, set) = true;
2267 } else {
2268 a_hasPositiveSign(cellId, set) = false;
2269 }
2270 }
2271
2272 // call the Eikonal solver
2273 // -----------------------
2274 // fill the cell list and levelSetFunction
2275 cellListSize = 0;
2276 for(MInt id = a_bandLayer(0, set); id < a_noBandCells(set); id++) {
2277 m_cellList[cellListSize] = a_bandCellId(id, set);
2278 cellListSize++;
2279 }
2280
2281 if(cellListSize > 0) {
2282 res[set] = firstOrderEikonalSolver(cellListSize, m_intermediateReinitIterations, set);
2283 m_log << "Reinitialization at ts " << globalTimeStep << ": " << res[set] << endl;
2284 } else {
2285 m_log << "Reinitialization skipped since no cell was found to reinitialize " << endl;
2286 }
2287 }
2288}
2289
2290
2291// ----------------------------------------------------------------------------------------
2292
2293
2306template <MInt nDim>
2307MFloat LsCartesianSolver<nDim>::firstOrderEikonalSolver(MInt cellListSize, MInt maxIterations, MInt set) {
2308 TRACE();
2309
2310
2311 MInt cellId;
2312 MInt iteration;
2313 MFloat a, b;
2314 MFloat G;
2315 MFloat dt = m_reinitCFL * m_gCellDistance;
2316 MFloatScratchSpace res(1, AT_, "res");
2317 MFloatScratchSpace globalRes(1, AT_, "globalRes");
2318 //---
2319
2320 // Iteration loop of the Sussman method
2321 // ------------------------------------
2322 iteration = 0;
2323 res.p[0] = F0;
2324
2325 if(maxIterations == 0) {
2326 return res.p[0];
2327 }
2328
2329 while(iteration < maxIterations) {
2330 res.p[0] = F0;
2331
2332 // discretization
2333 for(MInt cell = 0; cell < cellListSize; cell++) {
2334 cellId = m_cellList[cell];
2335 a_levelSetRHS(cellId, set) = F0;
2336 for(MInt i = 0; i < nDim; i++) {
2337 a = (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(a_bandNghbrIdsG(cellId, 2 * i, set), set))
2338 * m_FgCellDistance;
2339 b = (a_levelSetFunctionG(a_bandNghbrIdsG(cellId, 2 * i + 1, set), set) - a_levelSetFunctionG(cellId, set))
2340 * m_FgCellDistance;
2341 a_levelSetRHS(cellId, set) +=
2342 F1B2
2343 * ((a_levelSetSign(cellId, set) + F1) * mMax(POW2(mMax(a, F0)), POW2(mMin(b, F0)))
2344 - (a_levelSetSign(cellId, set) - F1) * mMax(POW2(mMin(a, F0)), POW2(mMax(b, F0))));
2345 }
2346 a_levelSetRHS(cellId, set) = m_signG[IDX_LSSET(cellId, set)] * (F1 - sqrt(a_levelSetRHS(cellId, set)));
2347 }
2348
2349 // solver
2350 for(MInt cell = 0; cell < cellListSize; cell++) {
2351 cellId = m_cellList[cell];
2352 G = a_levelSetFunctionG(cellId, set) + a_levelSetRHS(cellId, set) * dt;
2353 if(G * a_levelSetFunctionG(cellId, set) < F0) G = a_levelSetFunctionG(cellId, set);
2354 a_levelSetFunctionG(cellId, set) = G;
2355 res.p[0] = mMax(res.p[0], ABS(a_levelSetRHS(cellId, set)));
2356 }
2357 iteration++;
2358
2359 MFloat* q;
2360 q = (MFloat*)&a_levelSetFunctionG(0, 0);
2361 exchangeLs(q, set, 1);
2362 // exchange residual and data
2363 MPI_Allreduce(res.getPointer(), globalRes.getPointer(), 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "res.getPointer()",
2364 "globalRes.getPointer()");
2365
2366 res.p[0] = globalRes.p[0];
2367
2368 if(res.p[0] < m_reinitConvergence) {
2369 return res.p[0];
2370 }
2371 }
2372
2373 return res.p[0];
2374}
2375
2376
2377// ----------------------------------------------------------------------------------------
2378
2391template <MInt nDim>
2393 MInt maxIterations, MInt set) {
2394 TRACE();
2395
2396 MInt cellId;
2397 MInt iteration;
2398 MFloat a, b;
2399 MFloat G;
2400 MFloat cminus, cplus;
2401 MFloat PHI[7];
2402 MFloat dt = m_reinitCFL * m_gCellDistance;
2403 MFloatScratchSpace res(1, AT_, "res");
2404 MFloatScratchSpace globalRes(1, AT_, "globalRes");
2405 //---
2406
2407 // Iteration loop of the Sussman method
2408 // ------------------------------------
2409 iteration = 0;
2410 res.p[0] = F0;
2411
2412 if(maxIterations == 0) {
2413 return res.p[0];
2414 }
2415
2416 while(iteration < maxIterations) {
2417 res.p[0] = F0;
2418
2419 // discretization
2420 for(MInt cell = 0; cell < cellListSize; cell++) {
2421 cellId = m_cellList[cell];
2422 a_levelSetRHS(cellId, set) = F0;
2423 for(MInt i = 0; i < nDim; i++) {
2424 // compute the table of divided differences
2425 // entries 0-6: PHI(k-2,k-1), PHI(k-1,k), PHI(k+1,k), PHI(k+2,k+1)
2426 // PHI(k-2,k), PHI(k-1,k+1), PHI(k,k+2)
2427 PHI[0] = (q[IDX_LSSET(nghbrs[IDX_LSSETDIR(cellId, 2 * i, set)], set)]
2428 - q[IDX_LSSET(nghbrs[IDX_LSSETDIR(nghbrs[IDX_LSSETDIR(cellId, 2 * i, set)], 2 * i, set)], set)])
2429 * m_FgCellDistance;
2430 PHI[1] = (q[IDX_LSSET(cellId, set)] - q[IDX_LSSET(nghbrs[IDX_LSSETDIR(cellId, 2 * i, set)], set)])
2431 * m_FgCellDistance;
2432 PHI[2] = (q[IDX_LSSET(nghbrs[IDX_LSSETDIR(cellId, 2 * i + 1, set)], set)] - q[IDX_LSSET(cellId, set)])
2433 * m_FgCellDistance;
2434 PHI[3] = (q[IDX_LSSET(nghbrs[IDX_LSSETDIR(nghbrs[IDX_LSSETDIR(cellId, 2 * i + 1, set)], 2 * i + 1, set)], set)]
2435 - q[IDX_LSSET(cellId, set)])
2436 * m_FgCellDistance;
2437 PHI[4] = (PHI[1] - PHI[0]) * F1B2 * m_FgCellDistance;
2438 PHI[5] = (PHI[2] - PHI[1]) * F1B2 * m_FgCellDistance;
2439 PHI[6] = (PHI[3] - PHI[2]) * F1B2 * m_FgCellDistance;
2440 // compute cminus and cplus using a minmod limiter
2441 if(PHI[4] * PHI[5] > F0) {
2442 if(ABS(PHI[4]) <= ABS(PHI[5]))
2443 cminus = PHI[4];
2444 else
2445 cminus = PHI[5];
2446 } else
2447 cminus = F0;
2448 if(PHI[5] * PHI[6] > F0) {
2449 if(ABS(PHI[5]) <= ABS(PHI[6]))
2450 cplus = PHI[5];
2451 else
2452 cplus = PHI[6];
2453 } else
2454 cplus = F0;
2455 a = PHI[1] + cminus * m_gCellDistance;
2456 b = PHI[2] - cplus * m_gCellDistance;
2457 a_levelSetRHS(cellId, set) +=
2458 F1B2
2459 * ((a_levelSetSign(cellId, set) + F1) * mMax(POW2(mMax(a, F0)), POW2(mMin(b, F0)))
2460 - (a_levelSetSign(cellId, set) - F1) * mMax(POW2(mMin(a, F0)), POW2(mMax(b, F0))));
2461 }
2462 a_levelSetRHS(cellId, set) = m_signG[IDX_LSSET(cellId, set)] * (F1 - sqrt(a_levelSetRHS(cellId, set)));
2463 }
2464
2465 // solver
2466 for(MInt cell = 0; cell < cellListSize; cell++) {
2467 cellId = m_cellList[cell];
2468
2469 G = q[IDX_LSSET(cellId, set)] + a_levelSetRHS(cellId, set) * dt;
2470 q[IDX_LSSET(cellId, set)] = ABS(G) * a_levelSetSign(cellId, set);
2471 res.p[0] = mMax(res.p[0], ABS(a_levelSetRHS(cellId, set)));
2472 }
2473 iteration++;
2474
2475 exchangeLs(q, set, 1);
2476 // exchange residual and data
2477 MPI_Allreduce(res.getPointer(), globalRes.getPointer(), 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "res.getPointer()",
2478 "globalRes.getPointer()");
2479 res.p[0] = globalRes.p[0];
2480
2481 if(res.p[0] < m_reinitConvergence) {
2482 return res.p[0];
2483 }
2484 }
2485
2486 return res.p[0];
2487}
2488
2489
2490// ----------------------------------------------------------------------------------------
2491
2514template <MInt nDim>
2515MFloat LsCartesianSolver<nDim>::fifthOrderEikonalSolver(MInt cellListSize, MInt maxIterations, MInt* crCells,
2516 MInt noCRCells, MFloat* factors, MInt crMode, MInt set) {
2517 TRACE();
2518
2519 MInt cellId;
2520 MInt iteration;
2521 MInt nghbrL, nghbrL2, nghbrL3, nghbrL4, nghbrL5, nghbrR, nghbrR2, nghbrR3, nghbrR4, nghbrR5;
2522 MFloat a, b;
2523 MFloat dPlusL3, dPlusL2, dPlusL, dPlus, dPlusR, dPlusR2;
2524 MFloat eps = 0.000001;
2525 MFloat IS0, IS1, IS2;
2526 MFloat alpha0, alpha1, alpha2, omega0, omega2;
2527 MFloat PsiMinus, PsiPlus;
2528 MFloat c, d;
2529 MBool converged = false; // only active for crMode == 4 (limited CR2)
2530 MFloat dt = m_reinitCFL * m_gCellDistance;
2531 MBoolScratchSpace firstOrder(cellListSize, AT_, "firstOrder");
2532 MFloat res = F0;
2533 MInt minIteration;
2534 if(crMode == 6)
2535 minIteration = m_gBandWidth / m_reinitCFL;
2536 else
2537 minIteration = 0;
2538
2539 //---
2540
2541 // Iteration loop of the Sussman method
2542 // ------------------------------------
2543 iteration = 0;
2544
2545 if(!maxIterations) {
2546 return res;
2547 }
2548
2549 // only method 6 resets level set function
2550 switch(crMode) {
2551 case 6: {
2552 // check all cells which have a stencil neighbor outside of the domain
2553 for(MInt cell = 0; cell < cellListSize; cell++) {
2554 firstOrder.p[cell] = false;
2555 cellId = m_cellList[cell];
2556 if(a_isHalo(cellId)) continue;
2557
2558 for(MInt i = 0; i < nDim; i++) {
2559 nghbrL = a_bandNghbrIdsG(cellId, 2 * i, set);
2560 nghbrL2 = a_bandNghbrIdsG(nghbrL, 2 * i, set);
2561 nghbrL3 = a_bandNghbrIdsG(nghbrL2, 2 * i, set);
2562 nghbrL4 = a_bandNghbrIdsG(nghbrL3, 2 * i, set);
2563 nghbrL5 = a_bandNghbrIdsG(nghbrL4, 2 * i, set);
2564 nghbrR = a_bandNghbrIdsG(cellId, 2 * i + 1, set);
2565 nghbrR2 = a_bandNghbrIdsG(nghbrR, 2 * i + 1, set);
2566 nghbrR3 = a_bandNghbrIdsG(nghbrR2, 2 * i + 1, set);
2567 nghbrR4 = a_bandNghbrIdsG(nghbrR3, 2 * i + 1, set);
2568 nghbrR5 = a_bandNghbrIdsG(nghbrR4, 2 * i + 1, set);
2569 if(nghbrL5 == nghbrL4 || nghbrR5 == nghbrR4) {
2570 firstOrder.p[cell] = true;
2571 break;
2572 }
2573 }
2574 }
2575 break;
2576 }
2577 default: {
2578 // check all cells which have a stencil neighbor outside of the domain
2579 for(MInt cell = 0; cell < cellListSize; cell++) {
2580 firstOrder.p[cell] = false;
2581 cellId = m_cellList[cell];
2582 if(a_isHalo(cellId)) continue;
2583 for(MInt i = 0; i < nDim; i++) {
2584 nghbrL = a_bandNghbrIdsG(cellId, 2 * i, set);
2585 nghbrL2 = a_bandNghbrIdsG(nghbrL, 2 * i, set);
2586 nghbrL3 = a_bandNghbrIdsG(nghbrL2, 2 * i, set);
2587 nghbrL4 = a_bandNghbrIdsG(nghbrL3, 2 * i, set);
2588 nghbrL5 = a_bandNghbrIdsG(nghbrL4, 2 * i, set);
2589 nghbrR = a_bandNghbrIdsG(cellId, 2 * i + 1, set);
2590 nghbrR2 = a_bandNghbrIdsG(nghbrR, 2 * i + 1, set);
2591 nghbrR3 = a_bandNghbrIdsG(nghbrR2, 2 * i + 1, set);
2592 nghbrR4 = a_bandNghbrIdsG(nghbrR3, 2 * i + 1, set);
2593 nghbrR5 = a_bandNghbrIdsG(nghbrR4, 2 * i + 1, set);
2594 if(nghbrL5 == nghbrL4 || nghbrR5 == nghbrR4) {
2595 firstOrder.p[cell] = true;
2596 break;
2597 }
2598 }
2599 }
2600 break;
2601 }
2602 }
2603
2604 while(iteration < maxIterations) {
2605 res = F0;
2606
2607 // discretization
2608 // WENO-JP-5
2609 for(MInt cell = 0; cell < cellListSize; cell++) {
2610 cellId = m_cellList[cell];
2611 if(a_isHalo(cellId)) continue;
2612 a_levelSetRHS(cellId, set) = F0;
2613 if(!firstOrder.p[cell]) {
2614 for(MInt i = 0; i < nDim; i++) {
2615 nghbrL = a_bandNghbrIdsG(cellId, 2 * i, set);
2616 nghbrL2 = a_bandNghbrIdsG(nghbrL, 2 * i, set);
2617 nghbrL3 = a_bandNghbrIdsG(nghbrL2, 2 * i, set);
2618 nghbrR = a_bandNghbrIdsG(cellId, 2 * i + 1, set);
2619 nghbrR2 = a_bandNghbrIdsG(nghbrR, 2 * i + 1, set);
2620 nghbrR3 = a_bandNghbrIdsG(nghbrR2, 2 * i + 1, set);
2621 dPlusL3 = a_levelSetFunctionG(nghbrL2, set) - a_levelSetFunctionG(nghbrL3, set);
2622 dPlusL2 = a_levelSetFunctionG(nghbrL, set) - a_levelSetFunctionG(nghbrL2, set);
2623 dPlusL = a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(nghbrL, set);
2624 dPlus = a_levelSetFunctionG(nghbrR, set) - a_levelSetFunctionG(cellId, set);
2625 dPlusR = a_levelSetFunctionG(nghbrR2, set) - a_levelSetFunctionG(nghbrR, set);
2626 dPlusR2 = a_levelSetFunctionG(nghbrR3, set) - a_levelSetFunctionG(nghbrR2, set);
2627 a = (dPlusL2 - dPlusL3) * m_FgCellDistance;
2628 b = (dPlusL - dPlusL2) * m_FgCellDistance;
2629 c = (dPlus - dPlusL) * m_FgCellDistance;
2630 d = (dPlusR - dPlus) * m_FgCellDistance;
2631 IS0 = 13.0 * POW2(a - b) + 3.0 * POW2(a - 3 * b);
2632 IS1 = 13.0 * POW2(b - c) + 3.0 * POW2(b + c);
2633 IS2 = 13.0 * POW2(c - d) + 3.0 * POW2(3 * c - d);
2634 alpha0 = F1 / POW2(eps + IS0);
2635 alpha1 = F6 / POW2(eps + IS1);
2636 alpha2 = F3 / POW2(eps + IS2);
2637 omega0 = alpha0 / (alpha0 + alpha1 + alpha2);
2638 omega2 = alpha2 / (alpha0 + alpha1 + alpha2);
2639 PsiMinus = F1B3 * omega0 * (a - 2 * b + c) + F1B6 * (omega2 - F1B2) * (b - 2 * c + d);
2640 a = (dPlusR2 - dPlusR) * m_FgCellDistance;
2641 b = (dPlusR - dPlus) * m_FgCellDistance;
2642 d = (dPlusL - dPlusL2) * m_FgCellDistance;
2643 IS0 = 13.0 * POW2(a - b) + 3.0 * POW2(a - 3 * b);
2644 IS1 = 13.0 * POW2(b - c) + 3.0 * POW2(b + c);
2645 IS2 = 13.0 * POW2(c - d) + 3.0 * POW2(3 * c - d);
2646 alpha0 = F1 / POW2(eps + IS0);
2647 alpha1 = F6 / POW2(eps + IS1);
2648 alpha2 = F3 / POW2(eps + IS2);
2649 omega0 = alpha0 / (alpha0 + alpha1 + alpha2);
2650 omega2 = alpha2 / (alpha0 + alpha1 + alpha2);
2651 PsiPlus = F1B3 * omega0 * (a - 2 * b + c) + F1B6 * (omega2 - F1B2) * (b - 2 * c + d);
2652 a = F1B12 * m_FgCellDistance * (-dPlusL2 + F7 * dPlusL + F7 * dPlus - dPlusR) - PsiMinus;
2653 b = F1B12 * m_FgCellDistance * (-dPlusL2 + F7 * dPlusL + F7 * dPlus - dPlusR) + PsiPlus;
2654
2655 a_levelSetRHS(cellId, set) +=
2656 F1B2
2657 * ((a_levelSetSign(cellId, set) + F1) * mMax(POW2(mMax(a, F0)), POW2(mMin(b, F0)))
2658 - (a_levelSetSign(cellId, set) - F1) * mMax(POW2(mMin(a, F0)), POW2(mMax(b, F0))));
2659 }
2660 } else {
2661 for(MInt i = 0; i < nDim; i++) {
2662 a = (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(a_bandNghbrIdsG(cellId, 2 * i, set), set))
2663 * m_FgCellDistance;
2664 b = (a_levelSetFunctionG(a_bandNghbrIdsG(cellId, 2 * i + 1, set), set) - a_levelSetFunctionG(cellId, set))
2665 * m_FgCellDistance;
2666 a_levelSetRHS(cellId, set) +=
2667 F1B2
2668 * ((a_levelSetSign(cellId, set) + F1) * mMax(POW2(mMax(a, F0)), POW2(mMin(b, F0)))
2669 - (a_levelSetSign(cellId, set) - F1) * mMax(POW2(mMin(a, F0)), POW2(mMax(b, F0))));
2670 }
2671 }
2672 }
2673
2674 // final computation of a_levelSetRHS without forcing -> distinguish between limited (crMode = 4 ) and not limited
2675 // schemes:
2676 if(crMode == 4) {
2677 converged = true;
2678 for(MInt cell = 0; cell < cellListSize; cell++) {
2679 cellId = m_cellList[cell];
2680 if(a_isHalo(cellId)) continue;
2681 if(fabs(F1 - sqrt(a_levelSetRHS(cellId, set))) > 1.0) {
2682 converged = false;
2683 a_levelSetRHS(cellId, set) = m_signG[IDX_LSSET(cellId, set)] * (F1 - sqrt(a_levelSetRHS(cellId, set)));
2684 } else {
2685 a_levelSetRHS(cellId, set) = F0;
2686 }
2687 }
2688 } else {
2689 for(MInt cell = 0; cell < cellListSize; cell++) {
2690 cellId = m_cellList[cell];
2691 if(a_isHalo(cellId)) continue;
2692 a_levelSetRHS(cellId, set) = m_signG[IDX_LSSET(cellId, set)] * (F1 - sqrt(a_levelSetRHS(cellId, set)));
2693 }
2694 }
2695
2696
2697 // forcing term - only applied if crMode > 0 (CR scheme applied)
2698 switch(crMode) {
2699 case 0: { // zero disables forcing
2700 break;
2701 }
2702 case 1: { // CR1 - see Diss/Papers Daniel Hartmann
2703 MInt cnt, overallCnt;
2704 MBool forcing;
2705 MFloat sum;
2706 overallCnt = 0;
2707 for(MInt k = 0; k < noCRCells; k++) {
2708 forcing = true;
2709 sum = F0;
2710 cnt = 0;
2711 if(a_isHalo(crCells[k])) continue;
2712 for(MInt i = 0; i < m_noDirs; i++) {
2713 if(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)] != -1) {
2714 if(a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set)
2715 * a_levelSetFunctionG(crCells[k], set)
2716 < F0) {
2717 sum += factors[overallCnt++] * a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set);
2718 cnt++;
2719 } else
2720 forcing = false;
2721 }
2722 }
2723 if(forcing) {
2724 a_levelSetRHS(crCells[k], set) +=
2725 m_relaxationFactor * m_FgCellDistance * (sum / (MFloat)cnt - a_levelSetFunctionG(crCells[k], set));
2726 }
2727 }
2728 break;
2729 }
2730 case 6:
2731 case 2: { // CR2 - see Diss/Papers Daniel Hartmann
2732 MBool forcing;
2733 MFloat sum;
2734 // MInt cnt =0;
2735 for(MInt k = 0; k < noCRCells; k++) {
2736 forcing = true;
2737 sum = F0;
2738 if(a_isHalo(crCells[k])) continue;
2739 // cnt=0;
2740 // check whether sign is changed
2741 if(a_levelSetSign(crCells[k], set) > 0 && a_levelSetFunctionG(crCells[k], set) < 0) {
2742 forcing = false;
2743 }
2744 if(a_levelSetSign(crCells[k], set) < 0 && a_levelSetFunctionG(crCells[k], set) > 0) {
2745 forcing = false;
2746 }
2747 for(MInt i = 0; i < m_noDirs; i++) {
2748 if(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)] != -1) {
2749 if(a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set)
2750 * a_levelSetFunctionG(crCells[k], set)
2751 < F0) {
2752 sum += a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set);
2753 // cnt++;
2754 } else {
2755 forcing = false;
2756 break; // Stephan : to not force when in one direction no sign is changing Stephan: debug
2757 }
2758 }
2759 }
2760 if(forcing) {
2761 a_levelSetRHS(crCells[k], set) +=
2762 m_relaxationFactor * m_FgCellDistance * (factors[k] * sum - a_levelSetFunctionG(crCells[k], set));
2763 }
2764 }
2765 break;
2766 }
2767 case 3: { // CR3 - ? Conservative Level Set only!
2768 for(MInt k = 0; k < noCRCells; k++) {
2769 if(a_isHalo(crCells[k])) continue;
2770 a_levelSetRHS(crCells[k], set) +=
2771 m_relaxationFactor * m_FgCellDistance
2772 * (atanh(m_hypTanLSF[IDX_LSSET(crCells[k], set)] * F2 - F1) * m_gCellDistance
2773 - a_levelSetFunctionG(crCells[k], set));
2774 }
2775 break;
2776 }
2777 case 4: { // limited CR2
2778 MBool forcing;
2779 MFloat sum;
2780 for(MInt k = 0; k < noCRCells; k++) {
2781 if(a_isHalo(crCells[k])) continue;
2782 if(abs(a_levelSetRHS(crCells[k], set)) < 0.000000000001) continue;
2783 sum = F0;
2784 forcing = true;
2785 for(MInt i = 0; i < m_noDirs; i++) {
2786 if(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)] != -1) {
2787 if(a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set)
2788 * a_levelSetFunctionG(crCells[k], set)
2789 < F0)
2790 sum += a_levelSetFunctionG(m_phiRatioCells[crCells[k]][IDX_LSSET(i, set)], set);
2791 else
2792 forcing = false;
2793 }
2794 }
2795 if(forcing)
2796 a_levelSetRHS(crCells[k], set) +=
2797 m_relaxationFactor * m_FgCellDistance * (factors[k] * sum - a_levelSetFunctionG(crCells[k], set));
2798 }
2799 break;
2800 }
2801 default: {
2802 mTerm(1, AT_, "Unknown crMode");
2803 }
2804 }
2805
2806 // solver
2807 for(MInt cell = 0; cell < cellListSize; cell++) {
2808 cellId = m_cellList[cell];
2809 if(a_isHalo(cellId)) continue;
2810
2811 a_levelSetFunctionG(cellId, set) += a_levelSetRHS(cellId, set) * dt;
2812 res = mMax(res, ABS(a_levelSetRHS(cellId, set)));
2813 // debug: if this line is used instead of the previous one, stephans old results can be estabished!
2814 // res = mMax( res, ABS(a_levelSetRHS(cellId , set) *dt) );
2815 }
2816
2817 iteration++;
2818
2819 MFloat* q;
2820 q = (MFloat*)&a_levelSetFunctionG(0, 0);
2821 exchangeLs(q, set, 1);
2822
2823 // exchange residual and data
2824 MPI_Allreduce(MPI_IN_PLACE, &res, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "res");
2825
2826 // Stephan: minIteration included (result inly different for crMode == 6 where fully reinitialization of band is
2827 // guaranteed)
2828 if((res < m_reinitConvergence && iteration > minIteration) || converged) {
2829 if(set == m_startSet) {
2830 if(domainId() == 0) {
2831 FILE* datei;
2832 stringstream reinitFile;
2833 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
2834 datei = fopen((reinitFile.str()).c_str(), "a+");
2835 fprintf(datei, " %d", iteration);
2836 fclose(datei);
2837 }
2838 }
2839 return res;
2840 }
2841 }
2842
2843 if(set == m_startSet) {
2844 if(domainId() == 0) {
2845 FILE* datei;
2846 stringstream reinitFile;
2847 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
2848 datei = fopen((reinitFile.str()).c_str(), "a+");
2849 fprintf(datei, " %d", iteration);
2850 fclose(datei);
2851 }
2852 }
2853 // as during regridding the convergence criterium is decreased by a factor of 3, here we reset it to the original
2854 // convergence criteria
2855 m_reinitConvergence = m_reinitConvergenceReset;
2856 return res;
2857}
2858
2859
2860//----------------------------------------------------------------------------
2861
2868template <MInt nDim>
2870 TRACE();
2871
2872 MFloat elapsedTime = F0;
2873 if(m_restart) {
2874 elapsedTime = time();
2875 }
2876
2889 m_GCtrlPntMethod = 2; // control point 2 as default
2890 m_GCtrlPntMethod = Context::getSolverProperty<MInt>("levelSetCtrlPntMethod", m_solverId, AT_, &m_GCtrlPntMethod);
2891 // set initial orientation and position
2892 // if 2D, set the 3rd dimension to zero and w[] to [0,0,1], in-plane xy rotation
2893 // Control point alway refers 3D coordinates
2894 MFloat u[3], v[3], w[3];
2895 // Example, Anchor the reference orgin at bounding box mid point, or any as preference.
2896 MFloat InitPos[3] = {F0, F0, F0};
2897 // InitPos[0] = m_geometry->m_mbMidPnt[0];
2898 // InitPos[1] = m_geometry->m_mbMidPnt[1];
2899 // InitPos[2] = m_geometry->m_mbMidPnt[2];
2900 // IF_CONSTEXPR(nDim == 2) InitPos[2] = 0.0;
2901 // Example, +30 degree xy plane orientation
2902 // Orientation about "current reference origin",
2903 // if orientation about geometry mid point, do "InitOrientation" before "InitPosition"
2904 // unit normalized vector is needed
2905 u[0] = 1.0;
2906 v[0] = 0.0;
2907 w[0] = 0.0;
2908 u[1] = 0.0;
2909 v[1] = 1.0;
2910 w[1] = 0.0;
2911 u[2] = 0.0;
2912 v[2] = 0.0;
2913 w[2] = 1.0;
2914 IF_CONSTEXPR(nDim == 2) {
2915 u[2] = v[2] = w[0] = w[1] = 0.0;
2916 w[2] = 1.0;
2917 }
2918 // initialize control points
2919 //
2920 //
2921 switch(m_GCtrlPntMethod) {
2922 case 1: {
2923 // not adjusted to multiple bodies...
2924 if(m_noBodyBndryCndIds > 1)
2925 mTerm(1, AT_,
2926 "You are using GCtrlPntMethod 1, which is not adjusted to multiple bodies, but you are trying to "
2927 "compute multiple bodies. Please check!");
2928 m_gCtrlPnt.CtrlPnt1_Initialize(m_geometry, nDim);
2929 m_gCtrlPnt.CtrlPnt1_InitOrientation(u, v, w);
2930 computeBodyPropertiesForced(1, InitPos, 0, elapsedTime);
2931 IF_CONSTEXPR(nDim == 2) InitPos[2] = 0.0;
2932 m_gCtrlPnt.CtrlPnt1_InitPosition(InitPos);
2933 break;
2934 }
2935 case 2: {
2936 m_gCtrlPnt.CtrlPnt2_Initialize(m_geometry, nDim);
2937 for(MInt body = 0; body < m_noEmbeddedBodies; body++) {
2938 const MInt bcId = m_bodyBndryCndIds[body];
2939 computeBodyPropertiesForced(1, InitPos, body, elapsedTime);
2940 IF_CONSTEXPR(nDim == 2) InitPos[2] = 0.0;
2941 m_gCtrlPnt.CtrlPnt2_InitOrientation(u, v, w, bcId);
2942 m_gCtrlPnt.CtrlPnt2_InitPosition(InitPos, bcId);
2943#if defined LS_DEBUG
2944 stringstream controlfile;
2945 controlfile << "Ctrl_Body_" << body << ".stl";
2946 m_gCtrlPnt.CtrlPnt2_CtrlPntToSTL((controlfile.str()).c_str(), bcId);
2947#endif
2948 }
2949 m_gCtrlPnt.CtrlPnt2_Update();
2950 break;
2951 }
2952 case 3:
2953 // TODO labels:LS,totest Validate
2954 // Attempt to create body-free version ~jv
2955 {
2956 m_gCtrlPnt.CtrlPnt1_Initialize(m_geometry, nDim);
2957 m_gCtrlPnt.CtrlPnt1_InitOrientation(u, v, w);
2958 IF_CONSTEXPR(nDim == 2) InitPos[2] = 0.0;
2959 m_gCtrlPnt.CtrlPnt1_InitPosition(InitPos);
2960 break;
2961 }
2962 default: {
2963 mTerm(1, AT_, "Unknown GCtrlPntMethod");
2964 }
2965 }
2966}
2967
2968//----------------------------------------------------------------------------
2969
2970
2971template <MInt nDim>
2973 TRACE();
2974
2985 m_nogRKSteps = Context::getSolverProperty<MInt>("nogRKSteps", m_solverId, AT_);
2986
2987 // alpha
2988 m_gRKalpha = new MFloat[m_nogRKSteps];
2989 for(MInt i = 0; i < m_nogRKSteps; i++) {
2997 m_gRKalpha[i] = Context::getSolverProperty<MFloat>("grkalpha-step", m_solverId, AT_, i);
2998 }
2999
3000 // reset step
3001 m_gRKStep = 0;
3002 if(!m_restart && m_LSSolver) {
3003 m_time = 0.0;
3004 globalTimeStep = 0;
3005 }
3006}
3007
3008//----------------------------------------------------------------------------
3009
3010
3011template <MInt nDim>
3013 TRACE();
3014
3015 // reset step - not really required for semiLagrange, but do nevertheless for security reasons!
3016 m_gRKStep = 0;
3017
3018 // for a restart the value will be over-written later
3019 for(MInt i = 0; i < nDim * m_noEmbeddedBodies; i++) {
3020 m_semiLagrange_xShift_ref[i] = F0;
3021 }
3022
3023 initRotatingLS();
3024}
3025
3026
3027// ----------------------------------------------------------------------------------------
3028
3029
3030// sets the m_isBndryCell member of levelSetFrontCells
3031template <MInt nDim>
3033 TRACE();
3034
3035 // checks whether a neighbor exists in all directions
3036 // if not, the cell is a boundary cell
3037 // this is only valid for isotropic G grids!
3038
3039 // reset m_isBndryCell property:
3040
3041 for(MInt set = 0; set < m_noSets; set++) {
3042 if(!m_computeSet[set]) continue;
3043 for(MInt id = 0; id < a_noG0Cells(set); id++) {
3044 MInt cellId = a_G0CellId(id, set);
3045 a_isBndryCellG(cellId) = false;
3046 }
3047 }
3048
3049 // set m_isBndryCell property - cell is bndry cell if at least 1 level set function identifies it as such
3050 for(MInt set = 0; set < m_noSets; set++) {
3051 if(!m_computeSet[set]) continue;
3052 for(MInt id = 0; id < a_noG0Cells(set); id++) {
3053 MInt cellId = a_G0CellId(id, set);
3054 for(MInt dir = 0; dir < 2 * nDim; dir++) {
3055 if(a_hasNeighbor(cellId, dir) == 0) {
3056 a_isBndryCellG(cellId) = true;
3057 break;
3058 }
3059 }
3060 }
3061 }
3062}
3063
3064
3065// ----------------------------------------------------------------------------------------
3066
3067
3068// sets the m_isBndryCell member of levelSetFrontCells
3069template <MInt nDim>
3071 TRACE();
3072
3073 for(MInt set = m_startSet; set < m_noSets; set++) {
3074 switch(m_levelSetBoundaryCondition) {
3075 case 17516: {
3076 MFloat x, err = 0.05;
3077 MFloat deltaX = m_flameRadiusOffset;
3078 // two flame code
3079 if(m_twoFlames) {
3080 for(MInt id = 0; id < a_noGBndryCells(set); id++) {
3081 a_isGBoundaryCellG(a_gBndryCellId(id, set), set) = true;
3082 x = c_coordinate(id, 0);
3083
3084 if((x > (-m_radiusFlameTube2 * 1.3 - err + m_xOffsetFlameTube))
3085 && (x < (m_radiusFlameTube2 * 1.3 + err + m_xOffsetFlameTube))) {
3086 a_levelSetFunctionG(a_gBndryCellId(id, set), set) =
3087 ABS(c_coordinate(a_gBndryCellId(id, set), 0) - m_xOffsetFlameTube) - m_radiusFlameTube * 1.3;
3088
3089 } else if((x > (-m_radiusFlameTube2 * 1.3 - err + m_xOffsetFlameTube2))
3090 && (x < (m_radiusFlameTube2 * 1.3 + err + m_xOffsetFlameTube2))) {
3091 a_levelSetFunctionG(a_gBndryCellId(id, set), set) =
3092 ABS(c_coordinate(a_gBndryCellId(id, set), 0) - m_xOffsetFlameTube2) - m_radiusFlameTube2 * 1.3;
3093 }
3094 }
3095 // one flame code
3096 } else {
3097 for(MInt id = 0; id < a_noGBndryCells(set); id++) {
3098 MInt cellId = a_gBndryCellId(id, set);
3099 a_isGBoundaryCellG(cellId, set) = true;
3100 a_levelSetFunctionG(cellId, set) =
3101 ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube) - (m_radiusFlameTube + deltaX);
3102 a_curvatureG(cellId, 0) = 0;
3103 for(MInt i = 0; i < nDim; i++)
3104 a_extensionVelocityG(cellId, i, set) = F0;
3105 }
3106 }
3107 break;
3108 }
3109 case 1751600: {
3110 // MFloat x,z,err= 0.05;
3111 MFloat deltaX = m_flameRadiusOffset;
3112 // two flame code
3113 for(MInt id = 0; id < a_noGBndryCells(set); id++) {
3114 MInt cellId = a_gBndryCellId(id, set);
3115 a_isGBoundaryCellG(cellId, set) = true;
3116 // x = c_coordinate( gCellId , 0 );
3117 // z = c_coordinate( gCellId , 2 );
3118
3119 MFloat minXG = ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube) - (m_jetHalfWidth + deltaX);
3120 MFloat minZG = ABS(c_coordinate(cellId, 2)) - (m_jetHalfLength + deltaX);
3121 MFloat maxG = mMax(minXG, minZG);
3122 a_levelSetFunctionG(cellId, set) =
3123 m_initialFlameHeight * sqrt(2.0 - 1.0) * maxG + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3124
3125 a_curvatureG(cellId, 0) = 0;
3126
3127 for(MInt i = 0; i < nDim; i++)
3128 a_extensionVelocityG(cellId, i, set) = F0;
3129 }
3130 break;
3131 }
3132
3133 case 5401000: {
3134 MFloat deltaX = 0.05;
3135 // two flame code
3136 for(MInt id = 0; id < a_noGBndryCells(set); id++) {
3137 MInt cellId = a_gBndryCellId(id, set);
3138 a_isGBoundaryCellG(cellId, set) = true;
3139
3140 MFloat radius = sqrt(POW2(c_coordinate(cellId, 0)) + POW2(c_coordinate(cellId, 2)));
3141
3142 MFloat maxG = ABS(radius) - (0.515 + deltaX);
3143 a_levelSetFunctionG(cellId, set) =
3144 m_initialFlameHeight * sqrt(2.0 - 1.0) * maxG + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3145
3146 a_curvatureG(cellId, 0) = 0;
3147
3148 for(MInt i = 0; i < nDim; i++)
3149 a_extensionVelocityG(cellId, i, set) = F0;
3150 }
3151 break;
3152 }
3153 default: {
3154 break; // some testcases do not need boundary conditions
3155 }
3156 }
3157 }
3158}
3159
3160
3161// ----------------------------------------------------------------------------------------
3162
3163
3171template <MInt nDim>
3173 TRACE();
3174
3175 ASSERT(!m_GFieldInitFromSTL, "");
3176
3177 MInt noCells = a_noCells();
3178 //---
3179
3180 IF_CONSTEXPR(nDim == 2) {
3181 switch(m_initialCondition) {
3182 case 50431:
3183 case 504312: {
3184 MFloat radius;
3185 MFloat x, y;
3186 MFloat h = 2.5;
3187 MFloat w = 0.25;
3188 MFloat R0 = 1.5;
3189 MFloat dy = 2.5;
3190 if(m_initialCondition == 504312) {
3191 dy = -1.9;
3192 }
3193
3194 for(MInt set = m_startSet; set < m_noSets; set++) {
3195 for(MInt cellId = 0; cellId < noCells; cellId++) {
3196 radius = POW2(c_coordinate(cellId, 0)) + POW2(c_coordinate(cellId, 1) - dy);
3197 radius = sqrt(radius);
3198 x = c_coordinate(cellId, 0);
3199 y = c_coordinate(cellId, 1) - dy;
3200
3201 if(radius < R0) {
3202 if(y > h - R0) {
3203 if(ABS(x) > w) {
3204 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, sqrt(POW2(ABS(x) - w) + POW2(y - h + R0)));
3205 } else {
3206 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, ABS(y - h + R0));
3207 }
3208 } else {
3209 if(ABS(x) < w) {
3210 a_levelSetFunctionG(cellId, set) = mMax(-ABS(ABS(x) - w), -ABS(y - h + R0));
3211 } else {
3212 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, ABS(x) - w);
3213 }
3214 }
3215 } else {
3216 if(ABS(x) > w || y > 0) {
3217 a_levelSetFunctionG(cellId, set) = R0 - radius;
3218 } else {
3219 a_levelSetFunctionG(cellId, set) = -sqrt(POW2(ABS(x) - w) + POW2(y + R0));
3220 }
3221 }
3222 }
3223 }
3224
3225 break;
3226 }
3227 case 203: {
3228 // rotating disk problem
3229 MFloat radius;
3230 MFloat x, y;
3231 MFloat h = 2.5;
3232 MFloat w = 0.25;
3233 MFloat R0 = 1.5;
3234 MFloat dy = 2.5;
3235 for(MInt set = m_startSet; set < m_noSets; set++) {
3236 for(MInt cellId = 0; cellId < noCells; cellId++) {
3237 radius =
3238 POW2(c_coordinate(cellId, 0) - a_meanCoord(0)) + POW2(c_coordinate(cellId, 1) - a_meanCoord(1) - dy);
3239 radius = sqrt(radius);
3240 x = c_coordinate(cellId, 0);
3241 y = c_coordinate(cellId, 1) - dy;
3242
3243 if(radius < R0) {
3244 if(y > h - R0) {
3245 if(ABS(x) > w) {
3246 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, sqrt(POW2(ABS(x) - w) + POW2(y - h + R0)));
3247 } else {
3248 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, ABS(y - h + R0));
3249 }
3250 } else {
3251 if(ABS(x) < w) {
3252 a_levelSetFunctionG(cellId, set) = mMax(-ABS(ABS(x) - w), -ABS(y - h + R0));
3253 } else {
3254 a_levelSetFunctionG(cellId, set) = mMin(R0 - radius, ABS(x) - w);
3255 }
3256 }
3257 } else {
3258 if(ABS(x) > w || y > 0) {
3259 a_levelSetFunctionG(cellId, set) = R0 - radius;
3260 } else {
3261 a_levelSetFunctionG(cellId, set) = -sqrt(POW2(ABS(x) - w) + POW2(y + R0));
3262 }
3263 }
3264 }
3265 }
3266 break;
3267 }
3268
3269 case 450: {
3270 // cylinder moving boundary test
3271
3280 MFloat R0 = F1B2;
3281 R0 = Context::getSolverProperty<MFloat>("radius", m_solverId, AT_, &R0);
3282
3283 MFloat center[nDim];
3284 MInt set = 0;
3285 for(MInt i = 0; i < nDim; i++) {
3286 center[i] = F0;
3287 }
3288 if(Context::propertyExists("initialBodyCenter", m_solverId)) {
3289 if(Context::propertyLength("initialBodyCenter", m_solverId) != nDim) {
3290 mTerm(1, AT_, "Property 'initialBodyCenter' has invalid amount of entries!");
3291 }
3292 for(MInt i = 0; i < nDim; i++) {
3293 center[i] = Context::getSolverProperty<MFloat>("initialBodyCenter", m_solverId, AT_, i);
3294 }
3295 }
3296 MFloat radius;
3297
3298 for(MInt cellId = 0; cellId < noCells; cellId++) {
3299 radius = POW2(c_coordinate(cellId, 0) - center[0]) + POW2(c_coordinate(cellId, 1) - center[1]);
3300 radius = sqrt(radius);
3301 a_levelSetFunctionG(cellId, set) = radius - R0;
3302 }
3303 break;
3304 }
3305
3306 case 17516: {
3307 MFloat x, err = 0.1;
3308 MFloat deltaX = m_flameRadiusOffset;
3309 MInt set = 0;
3310 for(MInt cellId = 0; cellId < noCells; cellId++) {
3311 x = c_coordinate(cellId, 0);
3312
3313 if(m_twoFlames) {
3314 err = 0.3;
3315 if((x > (-m_radiusFlameTube2 * 1.3 - err + m_xOffsetFlameTube))
3316 && (x < (m_radiusFlameTube2 * 1.3 + err + m_xOffsetFlameTube))) {
3317 a_levelSetFunctionG(cellId, set) =
3318 sqrt(4.0 - 1.0) * (ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube) - m_radiusFlameTube * 1.3)
3319 + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3320
3321 } else if((x > (-m_radiusFlameTube2 * 1.3 - err + m_xOffsetFlameTube2))
3322 && (x < (m_radiusFlameTube2 * 1.3 + err + m_xOffsetFlameTube2))) {
3323 a_levelSetFunctionG(cellId, set) =
3324 sqrt(4.0 - 1.0) * (ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube2) - m_radiusFlameTube2 * 1.3)
3325 + c_coordinate(cellId, 1) - m_yOffsetFlameTube2;
3326
3327 // level set function outside of the domain
3328 } else {
3329 a_levelSetFunctionG(cellId, set) = c_coordinate(cellId, 1) + 0.5;
3330 }
3331
3332 // one flame initial level set function
3333 } else {
3334 if((x > -m_radiusFlameTube - deltaX - 0.5) && (x < m_radiusFlameTube + deltaX + 0.5)) {
3335 a_levelSetFunctionG(cellId, set) =
3336 sqrt(4.0 - 1.0) * (ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube) - (m_radiusFlameTube + deltaX))
3337 + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3338
3339 // level set function outside of the domain
3340 } else {
3341 a_levelSetFunctionG(cellId, set) = c_coordinate(cellId, 1) + 0.5;
3342 }
3343 }
3344 }
3345
3346 for(MInt cellId = 0; cellId < noCells; cellId++) {
3347 for(MInt s = 1; s < m_noSets; s++)
3348 a_levelSetFunctionG(cellId, s) = a_levelSetFunctionG(cellId, 0);
3349 }
3350 break;
3351 }
3352 default: {
3353 break; // some testcases do not need initialization
3354 }
3355 }
3356 }
3357 else IF_CONSTEXPR(nDim == 3) {
3358 switch(m_initialCondition) {
3359 case 0: {
3360 // parallel inflow field with G sphere
3361 MFloat radius;
3362 MInt set = 0;
3363 for(MInt cellId = 0; cellId < noCells; cellId++) {
3364 radius = POW2(c_coordinate(cellId, 0)) + POW2(c_coordinate(cellId, 1)) + POW2(c_coordinate(cellId, 2));
3365 radius = sqrt(radius);
3366
3367 a_levelSetFunctionG(cellId, set) = (3.0 - radius);
3368 }
3369 break;
3370 }
3371
3372 case 450: {
3373 // cylinder moving boundary test
3374 MFloat R0 = F1B2;
3375 MInt set = 0;
3376
3384 R0 = Context::getSolverProperty<MFloat>("radius", m_solverId, AT_, &R0);
3385
3386 MFloat center[nDim];
3387 for(MInt i = 0; i < nDim; i++) {
3388 center[i] = F0;
3389 }
3390 if(Context::propertyExists("initialBodyCenter", m_solverId)) {
3391 if(Context::propertyLength("initialBodyCenter", m_solverId) != nDim) {
3392 mTerm(1, AT_, "Property 'initialBodyCenter' has invalid amount of entries!");
3393 }
3394 for(MInt i = 0; i < nDim; i++) {
3395 center[i] = Context::getSolverProperty<MFloat>("initialBodyCenter", m_solverId, AT_, i);
3396 }
3397 }
3398 MFloat radius;
3399
3400 for(MInt cellId = 0; cellId < noCells; cellId++) {
3401 radius = F0;
3402 for(MInt i = 0; i < nDim; i++) {
3403 radius += POW2(c_coordinate(cellId, i) - center[i]);
3404 }
3405 radius = sqrt(radius);
3406 a_levelSetFunctionG(cellId, set) = radius - R0;
3407 }
3408 break;
3409 }
3410
3411 case 1751600: {
3412 MFloat x, z;
3413 MFloat deltaX = m_flameRadiusOffset;
3414 MInt set = 0;
3415 MInt count = 0;
3416 for(MInt cellId = 0; cellId < noCells; cellId++) {
3417 x = c_coordinate(cellId, 0);
3418 z = c_coordinate(cellId, 2);
3419
3420 if((x > -m_radiusFlameTube - deltaX - 0.5) && (x < m_radiusFlameTube + deltaX + 0.5)
3421 && (z > -m_jetHalfLength - 0.5) && (z < m_jetHalfLength + 0.5)) {
3422 MFloat minXG = ABS(c_coordinate(cellId, 0) - m_xOffsetFlameTube) - (m_jetHalfWidth + deltaX);
3423 MFloat minZG = ABS(c_coordinate(cellId, 2)) - (m_jetHalfLength + deltaX);
3424 MFloat maxG = mMax(minXG, minZG);
3425 a_levelSetFunctionG(cellId, set) =
3426 m_initialFlameHeight * sqrt(2.0 - 1.0) * maxG + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3427
3428 // level set function outside of the domain
3429 } else {
3430 a_levelSetFunctionG(cellId, set) = c_coordinate(cellId, 1) - 1.0;
3431 }
3432 if(approx(a_levelSetFunctionG(cellId, set), 0.0, MFloatEps)) count++;
3433 }
3434
3435 for(MInt cellId = 0; cellId < noCells; cellId++) {
3436 for(MInt s = 1; s < m_noSets; s++)
3437 a_levelSetFunctionG(cellId, s) = a_levelSetFunctionG(cellId, 0);
3438 }
3439 break;
3440 }
3441
3442 case 5401000: {
3443 MFloat x, z;
3444 MFloat deltaX = 0.05;
3445 MInt set = 0;
3446 // MInt count=0;
3447 MFloat radius;
3448 for(MInt cellId = 0; cellId < noCells; cellId++) {
3449 x = c_coordinate(cellId, 0);
3450 z = c_coordinate(cellId, 2);
3451 radius = sqrt(POW2(x) + POW2(z));
3452
3453 if((radius < 0.5 + 0.3)) {
3454 MFloat maxG = ABS(radius) - (0.53 + deltaX);
3455 a_levelSetFunctionG(cellId, set) =
3456 m_initialFlameHeight * sqrt(2.0 - 1.0) * maxG + c_coordinate(cellId, 1) - m_yOffsetFlameTube;
3457
3458 // level set function outside of the domain
3459 } else {
3460 a_levelSetFunctionG(cellId, set) = c_coordinate(cellId, 1) + 0.0;
3461 }
3462 // if(approx(a_levelSetFunctionG( cellId , set) , 0.0, MFloatEps))
3463 // count++;
3464 }
3465
3466 for(MInt cellId = 0; cellId < noCells; cellId++) {
3467 for(MInt s = 1; s < m_noSets; s++)
3468 a_levelSetFunctionG(cellId, s) = a_levelSetFunctionG(cellId, 0);
3469 }
3470 break;
3471 }
3472
3473 default: {
3474 break; // some testcases do not need initialization
3475 }
3476 }
3477 }
3478
3479 // initialize all old cell variables
3480 if(m_semiLagrange) {
3481 for(MInt set = 0; set < m_noSets; set++) {
3482 for(MInt cellId = 0; cellId < noCells; cellId++) {
3483 a_oldLevelSetFunctionG(cellId, set) = a_levelSetFunctionG(cellId, set);
3484 }
3485 }
3486 }
3487 m_log << "Level set function initialized on " << noCells << " cells" << endl;
3488}
3489
3490//----------------------------------------------------------------------------
3491
3492
3512template <MInt nDim>
3514 TRACE();
3515
3516 // check dimension
3517 IF_CONSTEXPR(nDim == 1) mTerm(1, AT_, "Initialize G Field from STL does not support 1D problems");
3518 // MInt maxLevel = maxLevel();
3519
3520 MInt initMode = 1; // (Recommended version!)
3534 initMode = Context::getSolverProperty<MInt>("GFieldFromSTLInitMode", m_solverId, AT_, &initMode);
3535
3536 // define lambda for setting a_hasPositiveSign with MInts
3537 auto signToBool = [](const MInt& plusMinus) { return (plusMinus > 0) ? true : false; };
3538
3539 // a) Initialization:
3540 //---------------------------------------------------------------------------------------------------
3541 if(ConstructFlag) {
3542 switch(ConstructFlag) {
3543 case 1:
3544 // Use all G-cells:
3545 {
3546 // 1) Reset a_isGZeroCell
3547 for(MInt set = m_startSet; set < m_noSets; set++) {
3548 for(MInt GcellId = 0; GcellId < a_noCells(); GcellId++) {
3549 a_isGZeroCell(GcellId, set) = false;
3550 }
3551 }
3552
3553 // Initialization of the collected-levelset!
3554 for(MInt set = 0; set < m_startSet; set++) {
3555 for(MInt GcellId = 0; GcellId < a_noCells(); GcellId++) {
3556 a_levelSetFunctionG(GcellId, set) = -std::numeric_limits<MFloat>::infinity();
3557 }
3558 }
3559
3560 // 2) Determine the Levelset-Sign
3561 for(MInt set = m_startSet; set < m_noSets; set++) {
3562 for(MInt GcellId = 0; GcellId < a_noCells(); GcellId++) {
3563 MFloat target[3] = {0, 0, 0};
3564 if(a_isHalo(GcellId)) continue;
3565 if(!c_isLeafCell(GcellId)) continue;
3566 // if(a_level(GcellId) < maxLevel ) continue;
3567
3568 for(MInt Dir = 0; Dir < nDim; Dir++)
3569 target[Dir] = c_coordinate(GcellId, Dir);
3570
3571 if(m_GCtrlPntMethod == 1 || m_GCtrlPntMethod == 3) m_gCtrlPnt.CtrlPnt1_quvw(target);
3572 a_hasPositiveSign(GcellId, set) = signToBool(determineLevelSetSignFromSTL(target, set));
3573 if(m_levelSetSign[set] < 0) {
3574 a_hasPositiveSign(GcellId, set) = signToBool(-a_levelSetSign(GcellId, set));
3575 }
3576 a_levelSetFunctionG(GcellId, set) = a_levelSetSign(GcellId, set);
3577 }
3578 }
3579
3580 // 3) Update G0-Cells
3581 determineG0Cells();
3582
3583 // 4) Determine the distance to the Levelset-Interface (levelSet-value)
3584 for(MInt set = m_startSet; set < m_noSets; set++) {
3585 MInt noCells = a_noG0Cells(set);
3586 if(initMode > 0 && initMode < 3) noCells = a_noCells();
3587 for(MInt count = 0; count < noCells; count++) {
3588 MInt cellId = -1;
3589 if(initMode == 0 || initMode == 3) {
3590 cellId = a_G0CellId(count, set);
3591 } else {
3592 cellId = count;
3593 }
3594 if(a_isHalo(cellId)) continue;
3595 if(!c_isLeafCell(cellId)) continue;
3596 // if(a_level(cellId) < maxLevel ) continue;
3597
3598 if(initMode == 2) {
3599 MFloat radius{};
3600 for(MInt n = 0; n < nDim; n++) {
3601 radius += c_coordinate(cellId, n) * c_coordinate(cellId, n);
3602 }
3603 radius = sqrt(radius);
3604
3605 MFloat lvs = radius - 0.5;
3606 a_levelSetFunctionG(cellId, set) = lvs;
3607
3608 } else {
3609 MInt closestElement;
3610 IF_CONSTEXPR(nDim == 2) {
3611 MFloat closestPoint[2] = {F0, F0};
3612 MFloat refPoint[2] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1)};
3613 a_levelSetFunctionG(cellId, set) *=
3614 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3615 }
3616 else IF_CONSTEXPR(nDim == 3) {
3617 MFloat closestPoint[3] = {F0, F0, F0};
3618 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
3619 a_levelSetFunctionG(cellId, set) *=
3620 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3621 }
3622 }
3623 }
3624 }
3625 break;
3626 }
3627 case 2:
3628 case 3:
3629 case 5:
3630 // Use only band-cells:
3631 {
3632 if(m_GCtrlPntMethod == 2 && ConstructFlag != 5) {
3633 // control point method 2 needs to update normal vector, bounding box and adt
3634 m_gCtrlPnt.CtrlPnt2_UpdateAllNormalVector();
3635 m_gCtrlPnt.CtrlPnt2_Update();
3636 }
3637
3638 // Initialization of the collected-levelset!
3639 for(MInt set = 0; set < m_startSet; set++) {
3640 if(ConstructFlag == 5 && !m_geometryChange[set]) continue;
3641 for(MInt id = 0; id < a_noBandCells(set); id++) {
3642 const MInt cellId = a_bandCellId(id, set);
3643 a_levelSetFunctionG(cellId, set) = -std::numeric_limits<MFloat>::infinity();
3644 }
3645 }
3646
3647 // 2) Determine the Levelset-Sign
3648 for(MInt set = m_startSet; set < m_noSets; set++) {
3649 if(ConstructFlag == 5 && !m_geometryChange[set]) continue;
3650 for(MInt id = 0; id < a_noBandCells(set); id++) {
3651 const MInt cellId = a_bandCellId(id, set);
3652 MFloat target[3] = {0, 0, 0};
3653 if(a_isHalo(cellId)) continue;
3654 if(!c_isLeafCell(cellId)) continue;
3655 // if(a_level(GcellId) < maxLevel ) continue;
3656
3657 for(MInt Dir = 0; Dir < nDim; Dir++)
3658 target[Dir] = c_coordinate(cellId, Dir);
3659
3660 if(m_GCtrlPntMethod == 1 || m_GCtrlPntMethod == 3) m_gCtrlPnt.CtrlPnt1_quvw(target);
3661 a_hasPositiveSign(cellId, set) = signToBool(determineLevelSetSignFromSTL(target, set));
3662 if(m_levelSetSign[set] < 0) {
3663 a_hasPositiveSign(cellId, set) = signToBool(-a_levelSetSign(cellId, set));
3664 }
3665 a_levelSetFunctionG(cellId, set) = a_levelSetSign(cellId, set);
3666 }
3667 }
3668
3669 // 3) Update G0-Cells and Band-Cells
3670 for(MInt set = 0; set < m_noSets; set++) {
3671 std::vector<MInt>().swap(m_bandCells[set]);
3672 }
3673 determineG0Cells();
3674 determineBandCells();
3675
3676 // 4) Determine the distance to the Levelset-Interface (levelSet-value)
3677 for(MInt set = m_startSet; set < m_noSets; set++) {
3678 if(ConstructFlag == 5 && !m_geometryChange[set]) continue;
3679 MInt noCells = a_noG0Cells(set);
3680 if(initMode > 0 && initMode < 3) noCells = a_noBandCells(set);
3681
3682 for(MInt count = 0; count < noCells; count++) {
3683 MInt cellId = -1;
3684 if(initMode == 0 || initMode == 3) {
3685 cellId = a_G0CellId(count, set);
3686 } else {
3687 cellId = a_bandCellId(count, set);
3688 }
3689 if(a_isHalo(cellId)) continue;
3690 if(!c_isLeafCell(cellId)) continue;
3691 // if(a_level(GcellId) < maxLevel ) continue;
3692
3693 if(initMode == 2) {
3694 MFloat radius{};
3695 for(MInt n = 0; n < nDim; n++) {
3696 radius += c_coordinate(cellId, n) * c_coordinate(cellId, n);
3697 }
3698 radius = sqrt(radius);
3699
3700 const MFloat lvs = radius - 0.5;
3701 a_levelSetFunctionG(cellId, set) = lvs;
3702
3703 } else {
3704 MInt closestElement;
3705 IF_CONSTEXPR(nDim == 2) {
3706 MFloat closestPoint[2] = {F0, F0};
3707 MFloat refPoint[2] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1)};
3708 // Reset newly added band cells
3709 if(abs(a_levelSetFunctionG(cellId, set)) > 1.0) {
3710 a_hasPositiveSign(cellId, set) = signToBool(determineLevelSetSignFromSTL(refPoint, set));
3711 if(m_levelSetSign[set] < 0) {
3712 a_hasPositiveSign(cellId, set) = signToBool(-a_levelSetSign(cellId, set));
3713 }
3714 a_levelSetFunctionG(cellId, set) = a_levelSetSign(cellId, set);
3715 }
3716 a_levelSetFunctionG(cellId, set) *=
3717 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3718 }
3719 else IF_CONSTEXPR(nDim == 3) {
3720 MFloat closestPoint[3] = {F0, F0, F0};
3721 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
3722 // Reset newly added band cells
3723 if(abs(a_levelSetFunctionG(cellId, set)) > 1.0) {
3724 a_hasPositiveSign(cellId, set) = signToBool(determineLevelSetSignFromSTL(refPoint, set));
3725 if(m_levelSetSign[set] < 0) {
3726 a_hasPositiveSign(cellId, set) = signToBool(-a_levelSetSign(cellId, set));
3727 }
3728 a_levelSetFunctionG(cellId, set) = a_levelSetSign(cellId, set);
3729 }
3730 a_levelSetFunctionG(cellId, set) *=
3731 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3732 }
3733 }
3734 }
3735 }
3736 break;
3737 }
3738 case 6:
3739 // Use all cells; Update oldLevelSet:
3740 {
3741 // Initialization of the collected-levelset!
3742 for(MInt set = 0; set < m_startSet; set++) {
3743 if(!m_geometryChange[set]) continue;
3744 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
3745 a_oldLevelSetFunctionG(cellId, set) = -std::numeric_limits<MFloat>::infinity();
3746 }
3747 }
3748
3749 // 2) Determine the Levelset-Sign
3750 for(MInt set = m_startSet; set < m_noSets; set++) {
3751 if(!m_geometryChange[set]) continue;
3752 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
3753 MFloat target[3] = {0, 0, 0};
3754 if(a_isHalo(cellId)) continue;
3755 if(!c_isLeafCell(cellId)) continue;
3756
3757 for(MInt Dir = 0; Dir < nDim; Dir++)
3758 target[Dir] = c_coordinate(cellId, Dir);
3759
3760 if(m_GCtrlPntMethod == 1 || m_GCtrlPntMethod == 3) m_gCtrlPnt.CtrlPnt1_quvw(target);
3761 a_hasPositiveSign(cellId, set) = signToBool(determineLevelSetSignFromSTL(target, set));
3762 if(m_levelSetSign[set] < 0) {
3763 a_hasPositiveSign(cellId, set) = signToBool(-a_levelSetSign(cellId, set));
3764 }
3765 a_oldLevelSetFunctionG(cellId, set) = a_levelSetSign(cellId, set);
3766 }
3767 }
3768
3769 // 4) Determine the distance to the Levelset-Interface (levelSet-value)
3770 for(MInt set = m_startSet; set < m_noSets; set++) {
3771 if(!m_geometryChange[set]) continue;
3772 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
3773 if(a_isHalo(cellId)) continue;
3774 if(!c_isLeafCell(cellId)) continue;
3775 // if(a_level(GcellId) < maxLevel ) continue;
3776
3777 if(initMode == 2) {
3778 MFloat radius{};
3779 for(MInt n = 0; n < nDim; n++) {
3780 radius += c_coordinate(cellId, n) * c_coordinate(cellId, n);
3781 }
3782 radius = sqrt(radius);
3783
3784 const MFloat lvs = radius - 0.5;
3785 a_oldLevelSetFunctionG(cellId, set) = lvs;
3786
3787 } else {
3788 MInt closestElement;
3789 if(nDim == 2) {
3790 MFloat closestPoint[2] = {F0, F0};
3791 MFloat refPoint[2] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1)};
3792 a_oldLevelSetFunctionG(cellId, set) *=
3793 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3794 } else if(nDim == 3) {
3795 MFloat closestPoint[3] = {F0, F0, F0};
3796 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
3797 a_oldLevelSetFunctionG(cellId, set) *=
3798 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3799 }
3800 }
3801 }
3802 }
3803 break;
3804 }
3805 case 4:
3806 // on the run construction of newly refined cells for stationary sets
3807 {
3808 ASSERT(initMode == 1, "");
3809 ASSERT(m_STLReinitMode == 2, "");
3810
3811 // Initialization of the levelset!
3812 for(auto it = m_refinedCells.begin(); it != m_refinedCells.end(); it++) {
3813 const MInt cellId = it->first;
3814 const MInt set = it->second;
3815 ASSERT(cellId > -1 && cellId < a_noCells(), "");
3816 if(set > 0) {
3817 ASSERT(!m_computeSet_backup[set] || m_maxLevelChange, "");
3818 ASSERT(set >= 0 && set < m_noSets, "");
3819 a_oldLevelSetFunctionG(cellId, set) = -std::numeric_limits<MFloat>::infinity();
3820 } else {
3821 for(MInt setI = m_startSet; setI < m_noSets; setI++) {
3822 if(!m_maxLevelChange && m_computeSet_backup[setI] && !m_virtualSurgery) continue;
3823 a_oldLevelSetFunctionG(cellId, setI) = -std::numeric_limits<MFloat>::infinity();
3824 }
3825 }
3826 }
3827
3828 // 2) Determine the Levelset-Sign
3829 for(auto it = m_refinedCells.begin(); it != m_refinedCells.end(); it++) {
3830 const MInt cellId = it->first;
3831 const MInt set = it->second;
3832 if(a_isHalo(cellId)) continue;
3833 if(!c_isLeafCell(cellId)) continue;
3834 // if(a_level(GcellId) < maxLevel ) continue;
3835 MFloat target[3] = {0, 0, 0};
3836 for(MInt dir = 0; dir < nDim; dir++) {
3837 target[dir] = c_coordinate(cellId, dir);
3838 }
3839 ASSERT(m_GCtrlPntMethod == 2, "");
3840 if(set > 0) {
3841 a_hasPositiveSign(cellId, set) = signToBool(determineLevelSetSignFromSTL(target, set));
3842 if(m_levelSetSign[set] < 0) {
3843 a_hasPositiveSign(cellId, set) = signToBool(-a_levelSetSign(cellId, set));
3844 }
3845 a_oldLevelSetFunctionG(cellId, set) = a_levelSetSign(cellId, set);
3846 } else {
3847 for(MInt setI = m_startSet; setI < m_noSets; setI++) {
3848 if(!m_maxLevelChange && m_computeSet_backup[setI] && !m_virtualSurgery) continue;
3849 a_hasPositiveSign(cellId, setI) = signToBool(determineLevelSetSignFromSTL(target, setI));
3850 if(m_levelSetSign[setI] < 0) {
3851 a_hasPositiveSign(cellId, setI) = signToBool(-a_levelSetSign(cellId, setI));
3852 }
3853 a_oldLevelSetFunctionG(cellId, setI) = a_levelSetSign(cellId, setI);
3854 }
3855 }
3856 }
3857
3858
3859 // 4) Determine the distance to the Levelset-Interface (levelSet-value)
3860 for(auto it = m_refinedCells.begin(); it != m_refinedCells.end(); it++) {
3861 const MInt cellId = it->first;
3862 const MInt set = it->second;
3863 if(a_isHalo(cellId)) continue;
3864 if(!c_isLeafCell(cellId)) continue;
3865 // if(a_level(GcellId) < maxLevel ) continue;
3866 if(set > 0) {
3867 MInt closestElement;
3868 IF_CONSTEXPR(nDim == 2) {
3869 MFloat closestPoint[2] = {F0, F0};
3870 MFloat refPoint[2] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1)};
3871 a_oldLevelSetFunctionG(cellId, set) *=
3872 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set, m_sphereRadiusLimit);
3873 }
3874 else IF_CONSTEXPR(nDim == 3) {
3875 MFloat closestPoint[3] = {F0, F0, F0};
3876 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
3877 a_oldLevelSetFunctionG(cellId, set) *=
3878 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set, m_sphereRadiusLimit);
3879 }
3880 } else {
3881 for(MInt setI = m_startSet; setI < m_noSets; setI++) {
3882 if(!m_maxLevelChange && m_computeSet_backup[setI] && !m_virtualSurgery) continue;
3883 MInt closestElement;
3884 IF_CONSTEXPR(nDim == 2) {
3885 MFloat closestPoint[2] = {F0, F0};
3886 MFloat refPoint[2] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1)};
3887 a_oldLevelSetFunctionG(cellId, setI) *=
3888 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, setI, m_sphereRadiusLimit);
3889 }
3890 else IF_CONSTEXPR(nDim == 3) {
3891 MFloat closestPoint[3] = {F0, F0, F0};
3892 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
3893 a_oldLevelSetFunctionG(cellId, setI) *=
3894 computeDistanceFromSTL(refPoint, &closestElement, closestPoint, setI, m_sphereRadiusLimit);
3895 }
3896 }
3897 }
3898 }
3899 break;
3900 }
3901 default: {
3902 mTerm(1, AT_, "Unknown constructFlag");
3903 }
3904 }
3905 }
3906
3907 // b) reinitialization
3908 //---------------------------------------------------------------------------------------------------
3909 if(ConstructFlag == 0 || ConstructFlag == 2) {
3910 if(m_STLReinitMode == 2) return;
3911 IF_CONSTEXPR(nDim == 2) {
3912 if(m_STLReinitMode != 0) {
3913 computeNormalVectors();
3914 computeCurvature();
3915 return;
3916 }
3917 }
3918
3919 MInt tmp_gReinitIterations = m_gReinitIterations;
3920 m_gReinitIterations =
3921 Context::getSolverProperty<MInt>("gReinitIterationsForGFieldFromSTL", m_solverId, AT_, &m_gReinitIterations);
3922
3938 if(m_STLReinitMode == 0 || m_STLReinitMode == 3 || m_STLReinitMode == 1) {
3939 levelSetConstrainedReinitialization(2, m_startSet, m_noSets, 1);
3940 }
3941 computeNormalVectors();
3942 computeCurvature();
3943 if(m_STLReinitMode == 0 || m_STLReinitMode == 1) {
3944 levelSetConstrainedReinitialization(2, m_startSet, m_noSets, 1);
3945 } else if(m_STLReinitMode == 3) {
3946 levelSetHighOrderConstrainedReinitialization(2, m_startSet, m_noSets, 1);
3947 }
3948
3949 m_gReinitIterations = tmp_gReinitIterations;
3950
3951 if(m_STLReinitMode == 0 || m_STLReinitMode == 3) {
3952 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
3953 if(a_isHalo(cellId)) continue;
3954 if(!c_isLeafCell(cellId)) continue;
3955 if(a_level(cellId) != a_maxGCellLevel()) continue;
3956 for(MInt dir = 0; dir < m_noDirs; dir++) {
3957 const MInt nghbrId = c_neighborId(cellId, dir);
3958 if(nghbrId == -1 || nghbrId == cellId) {
3959 MFloat refPoint[3] = {F0, F0, F0};
3960 for(MInt i = 0; i < nDim; i++) {
3961 refPoint[i] = c_coordinate(cellId, i);
3962 }
3963 MInt closestElement;
3964 MFloat closestPoint[3] = {F0, F0, F0};
3965 for(MInt set = m_startSet; set < m_noSets; set++) {
3966 MFloat sign = determineLevelSetSignFromSTL(refPoint, set);
3967 if(m_levelSetSign[set] < 0) sign *= -1.0;
3968 MFloat phi = sign * computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3969
3970 a_levelSetFunctionG(cellId, set) = phi;
3971 }
3972 }
3973 }
3974 }
3975 } else if(m_STLReinitMode == 1) {
3976 // However, with Reinitialization on all G-cell-levels.
3977 // Timw: inserted, just as above, to allow for a Correction in Mode1.
3978 // This avoids errors in the G-Field initialization!
3979 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
3980 if(!c_isLeafCell(cellId)) continue;
3981 if(a_level(cellId) != a_maxGCellLevel()) continue;
3982 if(a_isHalo(cellId)) continue;
3983 for(MInt dir = 0; dir < m_noDirs; dir++) {
3984 MInt nghbrId = c_neighborId(cellId, dir);
3985 if(nghbrId == -1 || nghbrId == cellId) {
3986 MFloat refPoint[3] = {F0, F0, F0};
3987 for(MInt i = 0; i < nDim; i++) {
3988 refPoint[i] = c_coordinate(cellId, i);
3989 }
3990 MInt closestElement;
3991 MFloat closestPoint[3] = {F0, F0, F0};
3992 for(MInt set = m_startSet; set < m_noSets; set++) {
3993 MFloat sign = determineLevelSetSignFromSTL(refPoint, set);
3994 if(m_levelSetSign[set] < 0) sign *= -1.0;
3995 MFloat phi = sign * computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
3996 a_levelSetFunctionG(cellId, set) = phi;
3997 }
3998 }
3999 }
4000 }
4001 }
4002 }
4003
4004 exchangeLevelSet();
4005}
4006
4007//---------------------------------------------------------------------------
4008
4009template <MInt nDim>
4011 TRACE();
4012
4013 MInt nghbrId = -1;
4014 MInt containingCell = -1;
4015 MInt containingDomain = -1;
4016
4017 MInt bodyId;
4018 bodyId = m_bodiesToCompute[body];
4019
4020 std::vector<MInt> dir;
4021 dir.resize(2 * nDim);
4022
4023 std::vector<MFloat> vel;
4024 vel.resize(nDim);
4025 MFloat maxVel = -1;
4026 MFloat minVel = std::numeric_limits<MFloat>::max();
4027 MInt dirMax = -1;
4028 MInt dirMin = -1;
4029
4030 rotateLevelSet(2, &vel[0], bodyId, xCoord, xOld, &m_semiLagrange_xRot_STL[body * nDim]);
4031 for(MInt i = 0; i < nDim; i++) {
4032 if(abs(vel[i]) > maxVel) {
4033 dirMax = i;
4034 maxVel = abs(vel[i]);
4035 }
4036 if(abs(vel[i]) < minVel) {
4037 dirMin = i;
4038 minVel = abs(vel[i]);
4039 }
4040 }
4041 for(MInt i = 0; i < nDim; i++) {
4042 if(i == dirMax) {
4043 if(vel[i] >= F0) {
4044 dir[0] = i * 2;
4045 dir[2 * nDim - 1] = i * 2 + 1;
4046 } else {
4047 dir[0] = i * 2 + 1;
4048 dir[2 * nDim - 1] = i * 2;
4049 }
4050 } else if(i == dirMin) {
4051 if(vel[i] >= F0) {
4052 dir[nDim - 1] = i * 2;
4053 dir[nDim] = i * 2 + 1;
4054 } else {
4055 dir[nDim - 1] = i * 2 + 1;
4056 dir[nDim] = i * 2;
4057 }
4058 } else {
4059 if(vel[i] >= F0) {
4060 dir[1] = i * 2;
4061 dir[4] = i * 2 + 1;
4062 } else {
4063 dir[1] = i * 2 + 1;
4064 dir[4] = i * 2;
4065 }
4066 }
4067 }
4068
4069
4070 MInt offset = 0;
4071 MInt oDir[6] = {1, 2, 0, 2, 0, 1};
4072
4073 for(MInt n = 0; n < 2; n++) {
4074 // check neighbors
4075 for(MInt i = 0; i < nDim; i++) {
4076 nghbrId = c_neighborId(cellId, dir[i + offset]);
4077 if(nghbrId == -1) continue;
4078
4079 containingCell = a_containingCell(nghbrId, body);
4080 if(containingCell > -1 && std::find(m_newCells.begin(), m_newCells.end(), nghbrId) == m_newCells.end()) {
4081 a_containingCell(cellId, body) = containingCell;
4082
4083 if(!m_reconstructOldG) {
4084 containingDomain = a_containingDomain(nghbrId, body);
4085 a_containingDomain(cellId, body) = containingDomain;
4086 }
4087
4088 return;
4089 }
4090 }
4091 // check diagonal neighbors
4092 for(MInt i = 0; i < nDim; i++) {
4093 if(!a_hasNeighbor(cellId, dir[i + offset])) continue;
4094 nghbrId = c_neighborId(cellId, dir[i + offset]);
4095 for(MInt j = 0; j < (nDim - 1); j++) {
4096 if(!a_hasNeighbor(nghbrId, dir[oDir[i * 2 + j] + offset])) continue;
4097 nghbrId = c_neighborId(nghbrId, dir[oDir[i * 2 + j] + offset]);
4098
4099 containingCell = a_containingCell(nghbrId, body);
4100 if(containingCell > -1 && std::find(m_newCells.begin(), m_newCells.end(), nghbrId) == m_newCells.end()) {
4101 a_containingCell(cellId, body) = containingCell;
4102 if(!m_reconstructOldG) {
4103 containingDomain = a_containingDomain(nghbrId, body);
4104 a_containingDomain(cellId, body) = containingDomain;
4105 }
4106
4107 return;
4108 }
4109 }
4110 }
4111 offset = nDim;
4112 }
4113 mTerm(1, AT_, "Get containingCell from neighbor did not work!");
4114}
4115
4116
4117//----------------------------------------------------------------------------
4118
4127template <MInt nDim>
4129 TRACE();
4130
4131 if(m_noBodyBndryCndIds > 0) {
4132 ASSERT(m_noBodiesInSet[set] <= m_noBodyBndryCndIds,
4133 to_string(m_noBodiesInSet[set]) + " " + to_string(m_noBodyBndryCndIds));
4134 }
4135
4136 IF_CONSTEXPR(nDim == 2) {
4137 if(m_geometry->pointIsInsideMBElements(target, m_bodyBndryCndIds, m_setToBodiesTable[set], m_noBodiesInSet[set]))
4138 return -1;
4139 }
4140 else {
4141 if(m_geometry->pointIsInsideMBElements2(target, m_bodyBndryCndIds, m_setToBodiesTable[set], m_noBodiesInSet[set]))
4142 return -1;
4143 }
4144 return 1;
4145}
4146
4147
4148//----------------------------------------------------------------------------
4154template <MInt nDim>
4155MFloat LsCartesianSolver<nDim>::computeDistanceFromSTL(MFloat* target, MInt* closestElement, MFloat* closestPoint,
4156 MInt set, MFloat sphereRadiusFactor) {
4157 TRACE();
4158
4159 // class for checking if "target" can have normal distance to the STL
4160
4161 GeometryElement<nDim>* mbelements = m_geometry->m_mbelements->a;
4162
4163 MFloat q[3] = {F0, F0, F0};
4164 for(MInt dim = 0; dim < nDim; dim++)
4165 q[dim] = target[dim];
4166
4167 /*********** find the set of nearest geometrical elements to the target *********/
4168 std::vector<MInt> nodeList;
4169 MInt noNodes_set = 0;
4170 *closestElement = -1;
4171 const MFloat cellLength = c_cellLengthAtLevel(a_maxGCellLevel(set));
4172 const MFloat cellHalfLength = c_cellLengthAtLevel(a_maxGCellLevel(set) + 1);
4173 // Initialize mindist
4174 MFloat mindist = -1.0;
4175
4176 MFloat enlargeFactor = 1.01;
4177
4178 const MFloat radiusLimitSphere = sphereRadiusFactor * m_gBandWidth;
4179
4180 while(noNodes_set == 0 && enlargeFactor < radiusLimitSphere)
4181 // there is at least one element,otherwise extend the range by enlargeFactor
4182 {
4183 // Get all triangles in currentCell (target)
4184 const MFloat radius = cellHalfLength * enlargeFactor * sqrt(nDim);
4185
4186 nodeList.clear();
4187 m_geometry->getSphereIntersectionMBElements(q, radius, nodeList);
4188 for(MInt node = 0; node < (signed)nodeList.size(); node++) {
4189 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
4190 const MInt body = m_setToBodiesTable[set][b];
4191 const MInt bcId = m_bodyBndryCndIds[body];
4192 if(m_geometry->mbelements[nodeList[node]].m_bndCndId == bcId) {
4193 nodeList[noNodes_set] = nodeList[node];
4194 noNodes_set++;
4195 }
4196 }
4197 }
4198
4199 // Enlarge the boundingbox
4200 enlargeFactor *= 1.5;
4201 }
4202
4203 if(noNodes_set == 0) {
4204 mindist = F2 * m_gBandWidth * cellLength;
4205 return mindist;
4206 }
4207
4208 // loop over the set of nearest geometrical elements
4209 for(MInt inode = 0; inode < noNodes_set; inode++) {
4210 MInt e = nodeList[inode];
4211 GeometryElement<nDim>* el = &mbelements[e];
4212
4213 // check if the target can have normal distance to the current elements
4214 MInt haveNormal = 0;
4215
4216 MFloat transformationMatrix[3][3] = {{F0, F0, F0}, {F0, F0, F0}, {F0, F0, F0}};
4217 haveNormal = checkNormal().PointInsideTriangle(el, q, transformationMatrix);
4218 if(haveNormal) {
4219 // Calculate distance by normal
4220 IF_CONSTEXPR(nDim == 2) {
4221 MFloat n[3] = {0, 0, 0};
4222 MFloat quv[3] = {0, 0, 0};
4223 MFloat v[3] = {0, 0, 0}; // use only one vertex of the element
4224 MFloat vuv[3] = {0, 0, 0};
4225 for(MInt i = 0; i < nDim; i++) {
4226 v[i] = mbelements[e].m_vertices[0][i];
4227 n[i] = mbelements[e].m_normal[i];
4228 }
4229
4230 checkNormal().rotation(q, quv, transformationMatrix);
4231 checkNormal().rotation(v, vuv, transformationMatrix);
4232
4233 MFloat dist = fabs(quv[1] - vuv[1]);
4234 MFloat point[2] = {F0, F0};
4235 if(n[0] * (q[0] - v[0]) + n[1] * (q[1] - v[1]) > F0) {
4236 point[0] = q[0] - n[0] * dist;
4237 point[1] = q[1] - n[1] * dist;
4238 } else {
4239 point[0] = q[0] + n[0] * dist;
4240 point[1] = q[1] + n[1] * dist;
4241 }
4242
4243 if(mindist < 0.0) {
4244 mindist = dist;
4245 *closestElement = e;
4246 closestPoint[0] = point[0];
4247 closestPoint[1] = point[1];
4248 } else {
4249 if(mindist > dist) {
4250 mindist = dist;
4251 *closestElement = e;
4252 closestPoint[0] = point[0];
4253 closestPoint[1] = point[1];
4254 }
4255 }
4256 }
4257 else {
4258 MFloat n[3] = {0, 0, 0};
4259 MFloat v[3] = {0, 0, 0}; // use only one vertex of the element
4260 for(MInt i = 0; i < nDim; i++) {
4261 n[i] = mbelements[e].m_normal[i];
4262 v[i] = mbelements[e].m_vertices[0][i];
4263 }
4264
4265 MFloat d = -(n[0] * v[0] + n[1] * v[1] + n[2] * v[2]);
4266 MFloat dist = fabs(n[0] * q[0] + n[1] * q[1] + n[2] * q[2] + d);
4267 MFloat point[3] = {F0, F0, F0};
4268 if(n[0] * (q[0] - v[0]) + n[1] * (q[1] - v[1]) + n[2] * (q[2] - v[2]) > F0) {
4269 point[0] = q[0] - n[0] * dist;
4270 point[1] = q[1] - n[1] * dist;
4271 point[2] = q[2] - n[2] * dist;
4272 } else {
4273 point[0] = q[0] + n[0] * dist;
4274 point[1] = q[1] + n[1] * dist;
4275 point[2] = q[2] + n[2] * dist;
4276 }
4277 if(mindist < 0.0) {
4278 mindist = dist;
4279 *closestElement = e;
4280 closestPoint[0] = point[0];
4281 closestPoint[1] = point[1];
4282 closestPoint[2] = point[2];
4283 } else {
4284 if(mindist > dist) {
4285 mindist = dist;
4286 *closestElement = e;
4287 closestPoint[0] = point[0];
4288 closestPoint[1] = point[1];
4289 closestPoint[2] = point[2];
4290 }
4291 }
4292 }
4293 } else {
4294 MInt noVertices;
4295 IF_CONSTEXPR(nDim == 2) {
4296 noVertices = 2;
4297 // Calculate distance by points
4298 for(MInt i = 0; i < noVertices; i++) {
4299 MFloat v[3] = {0, 0, 0};
4300 for(MInt j = 0; j < nDim; j++) {
4301 v[j] = mbelements[e].m_vertices[i][j];
4302 }
4303 MFloat dist = sqrt(pow(q[0] - v[0], 2) + pow(q[1] - v[1], 2) + pow(q[2] - v[2], 2));
4304 if(mindist < 0.0) {
4305 mindist = dist;
4306 *closestElement = e;
4307 closestPoint[0] = v[0];
4308 closestPoint[1] = v[1];
4309 } else {
4310 if(mindist > dist) {
4311 mindist = dist;
4312 *closestElement = e;
4313 closestPoint[0] = v[0];
4314 closestPoint[1] = v[1];
4315 }
4316 }
4317 }
4318 }
4319 else {
4320 noVertices = 3;
4321 for(MInt i = 0; i < noVertices; i++) {
4322 MFloat v1[3] = {0, 0, 0}, v2[3] = {0, 0, 0};
4323 for(MInt j = 0; j < nDim; j++) {
4324 v1[j] = mbelements[e].m_vertices[i][j];
4325 v2[j] = mbelements[e].m_vertices[(i + 1) % noVertices][j];
4326 }
4327 // edge normal distance
4328 MFloat vp[3] = {v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]};
4329 MFloat vq[3] = {q[0] - v1[0], q[1] - v1[1], q[2] - v1[2]};
4330 // normalize by p
4331 MFloat norm_vp = sqrt(vp[0] * vp[0] + vp[1] * vp[1] + vp[2] * vp[2]);
4332 MFloat vp_hat[3] = {vp[0] / norm_vp, vp[1] / norm_vp, vp[2] / norm_vp};
4333 MFloat vq_hat[3] = {vq[0] / norm_vp, vq[1] / norm_vp, vq[2] / norm_vp};
4334 // scaling factor
4335 MFloat I = vp_hat[0] * vq_hat[0] + vp_hat[1] * vq_hat[1] + vp_hat[2] * vq_hat[2];
4336 MFloat dist = 0.0;
4337 MFloat point[3] = {F0, F0, F0};
4338 if((0.0 <= I) && (I <= 1.0)) { // edge normal distance
4339 MFloat x_e[3] = {v1[0] + I * vp[0], v1[1] + I * vp[1], v1[2] + I * vp[2]};
4340 dist = sqrt(POW2(q[0] - x_e[0]) + POW2(q[1] - x_e[1]) + POW2(q[2] - x_e[2]));
4341 point[0] = x_e[0];
4342 point[1] = x_e[1];
4343 point[2] = x_e[2];
4344 } else { // point-to-vertex distance
4345 dist = sqrt(vq[0] * vq[0] + vq[1] * vq[1] + vq[2] * vq[2]);
4346 point[0] = v1[0];
4347 point[1] = v1[1];
4348 point[2] = v1[2];
4349 }
4350
4351 if(mindist < 0.0) {
4352 mindist = dist;
4353 *closestElement = e;
4354 closestPoint[0] = point[0];
4355 closestPoint[1] = point[1];
4356 closestPoint[2] = point[2];
4357 } else {
4358 if(mindist > dist) {
4359 mindist = dist;
4360 *closestElement = e;
4361 closestPoint[0] = point[0];
4362 closestPoint[1] = point[1];
4363 closestPoint[2] = point[2];
4364 }
4365 }
4366 }
4367 }
4368 }
4369 }
4370 return mindist;
4371}
4372
4373//----------------------------------------------------------------------------
4383template <MInt nDim>
4385 TRACE();
4386
4387 //----------- prepare correction ---------//
4388 computeNormalVectorsAtFront();
4389 computeCurvature();
4390 // update control points
4391 m_gCtrlPnt.CtrlPnt2_UpdateAllNormalVector();
4392 m_gCtrlPnt.CtrlPnt2_Update();
4393
4394 //----------- compute gradient of curvature ---------------//
4395 // the gradient of curvature is computed by the central difference.
4396 MInt maxNoG0Cells = 0;
4397 for(MInt set = m_startSet; set < m_noSets; set++) {
4398 if(!m_computeSet[set]) continue;
4399 maxNoG0Cells = mMax(maxNoG0Cells, a_noG0Cells(set));
4400 }
4401 MFloatScratchSpace gradCurvature(maxNoG0Cells * m_maxNoSets, AT_, "gradCurvature");
4402
4403 for(MInt set = m_startSet; set < m_noSets; set++) {
4404 if(!m_computeSet[set]) continue;
4405 for(MInt id = 0; id < a_noG0Cells(set); id++) {
4406 MInt nghbrL, nghbrR, cellId;
4407 gradCurvature[IDX_LSSET(id, set)] = F0;
4408 cellId = a_G0CellId(id, set);
4409 for(MInt i = 0; i < nDim; i++) {
4410 MFloat gradComponent = F0;
4411 nghbrL = c_neighborId(cellId, 2 * i);
4412 nghbrR = c_neighborId(cellId, 2 * i + 1);
4413 gradComponent = (a_curvatureG(nghbrR, set) - a_curvatureG(nghbrL, set)) / (2.0 * m_gCellDistance);
4414 gradCurvature[IDX_LSSET(id, set)] += (gradComponent * gradComponent);
4415 }
4416 gradCurvature[IDX_LSSET(id, set)] = sqrt(gradCurvature[IDX_LSSET(id, set)]);
4417 }
4418 }
4419 //---------- mark cells ----------//
4420
4421 for(MInt set = m_startSet; set < m_noSets; set++) {
4422 if(!m_computeSet[set]) continue;
4423
4440 MInt maxThresholdLevels = 3;
4441 maxThresholdLevels =
4442 Context::getSolverProperty<MInt>("levelSetMaxCorrectionThresholdLevels", m_solverId, AT_, &maxThresholdLevels);
4443 MIntScratchSpace marker(a_noG0Cells(set), AT_, "marker");
4444 list<MInt> m_unmarked;
4445 list<MInt>::iterator it_unmarked;
4446 // initialize marker
4447 for(MInt c = 0; c < a_noG0Cells(set); c++) {
4448 marker[c] = 0;
4449 m_unmarked.push_back(c);
4450 }
4451
4452 // compute thresholds
4453 MInt curThresholdLevel = 1;
4454 while((curThresholdLevel <= maxThresholdLevels) && (m_unmarked.size() != 0)) {
4455 MFloat avgCurvature = 0.0;
4456 it_unmarked = m_unmarked.begin();
4457 // average gradient by RMS
4458 while(it_unmarked != m_unmarked.end()) {
4459 avgCurvature += (gradCurvature[IDX_LSSET(*it_unmarked, set)] * gradCurvature[IDX_LSSET(*it_unmarked, set)]);
4460 it_unmarked++;
4461 }
4462 avgCurvature /= (MFloat)m_unmarked.size();
4463 avgCurvature = sqrt(avgCurvature);
4464 // mark cells for reconstruction
4465 it_unmarked = m_unmarked.begin();
4466 while(it_unmarked != m_unmarked.end()) {
4467 if(gradCurvature[IDX_LSSET(*it_unmarked, set)] > avgCurvature) {
4468 marker[*it_unmarked] = curThresholdLevel;
4469 *it_unmarked = a_noG0Cells(set);
4470 }
4471 it_unmarked++;
4472 }
4473 // clean up marked cells from m_unmarked list
4474 m_unmarked.remove(a_noG0Cells(set));
4475 // increase threshold
4476 curThresholdLevel++;
4477 }
4478 //-------------- correct marked cells ------------------//
4479 for(MInt id = 0; id < a_noG0Cells(set); id++) {
4480 MInt cellId = a_G0CellId(id, set);
4481 m_d[IDX_LSSET(cellId, set)] = F0;
4482 m_correction[IDX_LSSET(cellId, set)] = F0;
4483 if(marker[id] > 0) {
4484 // Sitti Implementation - I (claudia) don't understand why to do this so complcated -> dangerous!
4485 // compute distance
4486 // MFloat q[] = { 0.0, 0.0, 0.0 };
4487 // // extract G0 point from the interface cell
4488 // for( MInt dim=0; dim<nDim; dim++ )
4489 // q[dim] = c_coordinate( cellId , dim )
4490 // + a_levelSetFunctionG( cellId , set)
4491 // * a_normalVectorG( cellId , dim , set );
4492 // MInt closestElement;
4493 // MFloat closestPoint[3] = {F0,F0,F0};
4494 // MFloat dist_q = computeDistanceFromSTL( q, &closestElement, closestPoint, set );
4495 // m_d[ IDX_LSSET(cellId, set) ] = dist_q;
4496 // // determine sign
4497 // MInt sign = determineLevelSetSignFromSTL( q, set );
4498 // m_correction[ IDX_LSSET(cellId, set) ] = sign;
4499 //
4500 // // correction
4501 // a_levelSetFunctionG( cellId , set) = a_levelSetFunctionG( cellId , set) + m_levelSetSign[set] *
4502 // (MFloat)sign*dist_q;
4503
4504 // better use this:
4505
4506 MInt closestElement;
4507 MFloat closestPoint[3] = {F0, F0, F0};
4508 MFloat refPoint[3] = {c_coordinate(cellId, 0), c_coordinate(cellId, 1), c_coordinate(cellId, 2)};
4509 MFloat dist_q = computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
4510 m_d[IDX_LSSET(cellId, set)] = dist_q;
4511 // determine sign
4512 MInt sign = determineLevelSetSignFromSTL(refPoint, set);
4513 m_correction[IDX_LSSET(cellId, set)] = sign;
4514 // correction
4515 a_levelSetFunctionG(cellId, set) = m_levelSetSign[set] * (MFloat)sign * dist_q;
4516 }
4517 }
4518 }
4519}
4520
4521
4522//----------------------------------------------------------------------------
4523
4524
4525// based on all level sets!
4532template <MInt nDim>
4534 TRACE();
4535
4536 MBool regrid = false;
4537
4538 // check whether the G grid needs to be regridded
4539 for(MInt set = m_startSet; set < m_noSets; set++) {
4540 if(!m_computeSet[set]) continue;
4541 for(MInt id = 0; id < a_noBandCells(set); id++) {
4542 if(a_isHalo(a_bandCellId(id, set))) continue;
4543 if(a_regridTriggerG(a_bandCellId(id, set))) {
4544 regrid = true;
4545 m_log << a_bandCellId(id, set) << " with set " << set << " caused regridding " << endl;
4546 break;
4547 }
4548 }
4549 if(regrid) break;
4550 }
4551
4552 return regrid;
4553}
4554
4555
4556// ----------------------------------------------------------------------------------------
4557
4558
4559template <MInt nDim>
4561 TRACE();
4562 //#define orderOfAccuracyTest
4563 MInt startSet;
4564 MInt endSet;
4565 MString reinitMethod = m_reinitMethod;
4566
4567 switch(mode) {
4568 case 0:
4569 startSet = 0;
4570 endSet = 1;
4571 reinitMethod = m_gapReinitMethod;
4572 break;
4573 default:
4574 startSet = m_startSet;
4575 endSet = m_noSets;
4576 break;
4577 }
4578
4579 if(m_semiLagrange) {
4580 ASSERT(reinitMethod == m_gapReinitMethod, "");
4581 ASSERT(m_guaranteeReinit, "");
4582 }
4583
4584
4585#ifndef orderOfAccuracyTest
4586 // compute the reinitialization sensor
4587 if(!mode || ((levelSetReinitializationTrigger() || m_guaranteeReinit) && !m_maintainOuterBandLayers)) {
4588 if(mode && globalTimeStep % m_reinitInterval != 0) return;
4589
4590 // correction scheme
4591 if(m_GFieldInitFromSTL && m_GWithReConstruction && mode) {
4592 // cerr << "correction" << endl;
4593 spatiallyAdaptiveCorrectionFromSTL();
4594 }
4595
4596 // cerr << "reinitialize..."<< endl;
4597
4598 // reinitialize
4599 switch(string2enum(reinitMethod)) {
4600 case CR1: {
4601 levelSetConstrainedReinitialization(1, startSet, endSet, mode);
4602 break;
4603 }
4604 case CR2: {
4605 levelSetConstrainedReinitialization(2, startSet, endSet, mode);
4606 break;
4607 }
4608 case HCR1: {
4609 levelSetHighOrderConstrainedReinitialization(1, startSet, endSet, mode);
4610 break;
4611 }
4612 case HCR2: {
4613 levelSetHighOrderConstrainedReinitialization(2, startSet, endSet, mode);
4614 break;
4615 }
4616 case HCR2_LIMITED: {
4617 levelSetHighOrderConstrainedReinitialization(4, startSet, endSet, mode);
4618 break;
4619 }
4620 case HCR2_FULLREINIT: {
4621 levelSetHighOrderConstrainedReinitialization(6, startSet, endSet, mode);
4622 break;
4623 }
4624 case no:
4625 default: {
4626 break;
4627 }
4628 }
4629 } else {
4630 ASSERT(!m_semiLagrange, "");
4631
4632 // maintain outer band cell layers
4633 switch(string2enum(reinitMethod)) {
4634 case CR1:
4635 case CR2: {
4636 maintainOuterBandLayers(1, startSet, endSet);
4637 break;
4638 }
4639 case HCR1:
4640 case HCR2:
4641 case HCR2_FULLREINIT: {
4642 maintainOuterBandLayers(5, startSet, endSet);
4643 break;
4644 }
4645 case no:
4646 default: {
4647 break;
4648 }
4649 }
4650 }
4651 if(domainId() == 0) {
4652 // write out info
4653 FILE* datei;
4654 stringstream reinitFile;
4655 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
4656 datei = fopen((reinitFile.str()).c_str(), "a+");
4657 fprintf(datei, "\n");
4658 fclose(datei);
4659 }
4660
4661#else
4662 MInt cellId;
4663 MFloat radius;
4664
4665 switch(string2enum(reinitMethod)) {
4666 case CR1: {
4667 levelSetConstrainedReinitialization(1, startSet, endSet, mode);
4668 break;
4669 }
4670 case CR2: {
4671 levelSetConstrainedReinitialization(2, startSet, endSet, mode);
4672 break;
4673 }
4674 case HCR1: {
4675 levelSetHighOrderConstrainedReinitialization(1, startSet, endSet, mode);
4676 break;
4677 }
4678 case HCR2: {
4679 levelSetHighOrderConstrainedReinitialization(2, startSet, endSet, mode);
4680 break;
4681 }
4682 case HCR2_FULLREINIT: {
4683 levelSetHighOrderConstrainedReinitialization(6, startSet, endSet, mode);
4684 break;
4685 }
4686 case no:
4687 default: {
4688 break;
4689 }
4690 }
4691
4692 // compute the error
4694 MFloat error;
4695 error = F0;
4696 MInt set = 0; // defined only for zero level set (m_noSets = 1)
4697 for(MInt id = 0; id < a_noG0Cells(set); id++) {
4698 cellId = a_G0CellId(id, set);
4699 error +=
4700 ABS(sqrt(POW2(c_coordinate(cellId, 0)) + POW2(c_coordinate(cellId, 1))) - 3 + a_levelSetFunctionG(cellId, set));
4701 }
4702 error /= a_noG0Cells(set);
4703 cerr << "Error after reinitialization: " << error << endl;
4704 FILE* datei;
4705 if(globalTimeStep % 1 == 0) {
4706 datei = fopen("ErrorInGamma", "a+");
4707 fprintf(datei, "%d", globalTimeStep);
4708 fprintf(datei, " %f", error);
4709 fprintf(datei, "\n");
4710 fclose(datei);
4711 }
4713#endif
4714}
4715
4716
4717//-----------------------------------------------------------------------------
4718
4719
4720// based on zeroth level-set function
4721template <MInt nDim>
4723 TRACE();
4724
4725 MInt cellId;
4726 MFloat temp = F0, avgDeviation = F0, maxDeviation = F0;
4727 MInt globalNoG0Cells = F0;
4728 MInt set = 0;
4729 //---
4730
4731 for(MInt id = 0; id < a_noG0Cells(set); id++) {
4732 cellId = a_G0CellId(id, set);
4733 if(a_isHalo(cellId)) continue;
4734 temp = F0;
4735 for(MInt i = 0; i < nDim; i++)
4736 temp += POW2(a_levelSetFunctionSlope(cellId, i, set));
4737 temp = POW2(sqrt(temp) - F1);
4738
4739 avgDeviation += temp;
4740 maxDeviation = mMax(maxDeviation, sqrt(temp));
4741 globalNoG0Cells++;
4742 }
4743
4744 MPI_Allreduce(MPI_IN_PLACE, &globalNoG0Cells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "globalNoG0Cells");
4745 MPI_Allreduce(MPI_IN_PLACE, &avgDeviation, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "avgDeviation");
4746 MPI_Allreduce(MPI_IN_PLACE, &maxDeviation, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "maxDeviation");
4747 avgDeviation = sqrt(avgDeviation / (MFloat)globalNoG0Cells);
4748
4749
4750 if(domainId() == 0) {
4751 // write out info
4752 FILE* datei;
4753 stringstream reinitFile;
4754 reinitFile << "Reinitialization_" << m_solverId << "_" << domainId();
4755 datei = fopen((reinitFile.str()).c_str(), "a+");
4756 fprintf(datei, " %d", globalTimeStep);
4757 fprintf(datei, " %f", time());
4758 fprintf(datei, " %f", globalTimeStep * timeStep());
4759 fprintf(datei, " %f", avgDeviation);
4760 fprintf(datei, " %f", maxDeviation);
4761 fprintf(datei, " %f", m_reinitThreshold);
4762 fprintf(datei, " %d", globalNoG0Cells);
4763
4764 fclose(datei);
4765 }
4766
4767 if(fabs(maxDeviation) > m_reinitThreshold && fabs(avgDeviation) > m_reinitThresholdAvg)
4768 return true;
4769 else
4770 return false;
4771}
4772
4773// ----------------------------------------------------------------------------------------
4774
4775
4776template <MInt nDim>
4778 TRACE();
4779
4780 MInt startSet = 0;
4781 MInt endSet = m_noSets;
4782 if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
4783 if(computingSet >= 0) {
4784 startSet = computingSet;
4785 endSet = computingSet + 1;
4786 ASSERT(m_computeSet[computingSet], "");
4787 ASSERT(m_changedSet[computingSet], "");
4788 }
4789
4790 //------------------
4791
4792
4793 for(MInt set = startSet; set < endSet; set++) {
4794 if(!m_computeSet[set]) continue;
4795 // may not be skipped as it is levelSet-value dependand
4796
4797 // reset all cells at the tube boundary
4798 for(MInt id = 0; id < a_noBandBndryCells(set); id++) {
4799 const MInt cellId = a_bandBndryCellId(id, set);
4800 if(a_isHalo(cellId)) {
4801 continue;
4802 }
4803 if(a_level(cellId) > a_maxGCellLevel(0)) continue;
4804
4805 for(MInt d = 0; d < m_noDirs; d++) {
4806 if(a_hasNeighbor(cellId, d) == 0) {
4807 continue;
4808 }
4809 if(!a_inBandG(c_neighborId(cellId, d), set)) {
4810 continue;
4811 }
4812 if(a_isGBoundaryCellG(c_neighborId(cellId, d), set)) {
4813 continue;
4814 }
4815 if(a_levelSetFunctionG(cellId, set) > F0) {
4816 a_levelSetFunctionG(cellId, set) = mMin(a_levelSetFunctionG(cellId, set),
4817 a_levelSetFunctionG(c_neighborId(cellId, d), set) + m_gCellDistance);
4818 } else {
4819 a_levelSetFunctionG(cellId, set) = mMax(a_levelSetFunctionG(cellId, set),
4820 a_levelSetFunctionG(c_neighborId(cellId, d), set) - m_gCellDistance);
4821 }
4822 }
4823 }
4824 }
4825
4826 exchangeLevelSet();
4827}
4828
4829// ----------------------------------------------------------------------------------------
4830
4831
4832// might be speeded up by more intelligent coding (for multiple level-set functions)
4841template <MInt nDim>
4843 TRACE();
4844
4845 MInt startSet = 0;
4846 MInt endSet = m_noSets;
4847 // if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
4848 // TODO labels:LS update testcases, so that the uncommented version above passes!
4849 // this is due to restartVariables on lowerGridLevels not matching otherwise!
4850 if(computingSet >= 0) {
4851 startSet = computingSet;
4852 endSet = computingSet + 1;
4853 ASSERT(m_computeSet[computingSet], "");
4854 }
4855
4856 MBoolScratchSpace skip(a_noCells(), AT_, "skip");
4857 MIntScratchSpace tempCells(a_noCells(), AT_, "tempCells");
4858
4859 //---
4860
4861
4862 for(MInt set = startSet; set < endSet; set++) {
4863 if(!m_computeSet[set]) continue;
4864 // this happens before, determineG0Cells, thus !m_changedSet can not be skipped!
4865
4866 for(MInt cell = 0; cell < a_noCells(); cell++) {
4867 skip.p[cell] = false;
4868 }
4869
4870 // average the level set function to parents of leaf cells
4871 MInt noTempCells = 0;
4872 for(MInt id = 0; id < a_noBandCells(set); id++) {
4873 const MInt cellId = a_bandCellId(id, set);
4874 const MInt parentId = c_parentId(cellId);
4875 if(parentId > -1) {
4876 if(!skip.p[parentId]) {
4877 tempCells.p[noTempCells] = parentId;
4878 noTempCells++;
4879 a_levelSetFunctionG(parentId, set) = F0;
4880 MInt noChildren = c_noChildren(parentId);
4881 if(!(noChildren > 0)) {
4882 cerr << "parent: " << parentId << endl;
4883 cerr << "gcell: " << cellId << endl;
4884 mTerm(1, AT_, "this should not occur: parent g cell with m_noChildIdsG == 0...");
4885 }
4886 for(MInt child = 0; child < IPOW2(nDim); child++) {
4887 if(c_childId(parentId, child) < 0) continue;
4888 a_levelSetFunctionG(parentId, set) += a_levelSetFunctionG(c_childId(parentId, child), set);
4889 }
4890 a_levelSetFunctionG(parentId, set) /= (MFloat)noChildren;
4891 skip.p[parentId] = true;
4892 }
4893 }
4894 }
4895
4896 // average the level set function all the way down
4897 // overwrite tempCells
4898 while(noTempCells > 0) {
4899 const MInt listSize = noTempCells;
4900 noTempCells = 0;
4901 for(MInt cell = 0; cell < listSize; cell++) {
4902 const MInt gCellId = tempCells.p[cell];
4903 const MInt parentId = c_parentId(gCellId);
4904 if(parentId > -1) {
4905 if(!skip.p[parentId]) {
4906 tempCells.p[noTempCells] = parentId;
4907 noTempCells++;
4908 a_levelSetFunctionG(parentId, set) = F0;
4909 MInt noChildren = c_noChildren(parentId);
4910 if(!(noChildren > 0)) {
4911 cerr << parentId << endl;
4912 cerr << "gcell: " << gCellId << endl;
4913 mTerm(1, AT_, "this should not occur: parent g cell with m_noChildIdsG == 0...");
4914 }
4915 for(MInt child = 0; child < IPOW2(nDim); child++) {
4916 if(c_childId(parentId, child) < 0) continue;
4917 a_levelSetFunctionG(parentId, set) += a_levelSetFunctionG(c_childId(parentId, child), set);
4918 }
4919 a_levelSetFunctionG(parentId, set) /= (MFloat)noChildren;
4920 skip.p[parentId] = true;
4921 }
4922 }
4923 }
4924 }
4925 }
4926}
4927
4928template <MInt nDim>
4930 TRACE();
4931
4932 MInt startSet = 0;
4933 MInt endSet = m_noSets;
4934 // if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
4935 // TODO labels:LS update testcases, so that the uncommented version above passes!
4936 // this is due to restartVariables on lowerGridLevels not matching otherwise!
4937 if(computingSet >= 0) {
4938 startSet = computingSet;
4939 endSet = computingSet + 1;
4940 ASSERT(m_computeSet[computingSet], "");
4941 }
4942
4943 MBoolScratchSpace skip(a_noCells(), AT_, "skip");
4944 MIntScratchSpace tempCells(a_noCells(), AT_, "tempCells");
4945
4946 //---
4947
4948
4949 for(MInt set = startSet; set < endSet; set++) {
4950 if(!m_computeSet[set]) continue;
4951 // this happens before, determineG0Cells, thus !m_changedSet can not be skipped!
4952
4953 for(MInt cell = 0; cell < a_noCells(); cell++) {
4954 skip.p[cell] = false;
4955 }
4956
4957 // average the level set function to parents of leaf cells
4958 MInt noTempCells = 0;
4959 for(MInt gCellId = 0; gCellId < a_noCells(); gCellId++) {
4960 if(a_isHalo(gCellId)) continue;
4961 if(!c_isLeafCell(gCellId)) continue;
4962 MInt parentId = c_parentId(gCellId);
4963 if(parentId > -1) {
4964 if(!skip.p[parentId]) {
4965 tempCells.p[noTempCells] = parentId;
4966 noTempCells++;
4967 a_levelSetFunctionG(parentId, set) = F0;
4968 MInt noChildren = c_noChildren(parentId);
4969 if(!(noChildren > 0)) {
4970 cerr << "parent: " << parentId << endl;
4971 cerr << "gcell: " << gCellId << endl;
4972 mTerm(1, AT_, "this should not occur: parent g cell with m_noChildIdsG == 0...");
4973 }
4974 for(MInt child = 0; child < IPOW2(nDim); child++) {
4975 if(c_childId(parentId, child) < 0) continue;
4976 a_levelSetFunctionG(parentId, set) += a_levelSetFunctionG(c_childId(parentId, child), set);
4977 }
4978 a_levelSetFunctionG(parentId, set) /= (MFloat)noChildren;
4979 skip.p[parentId] = true;
4980 }
4981 }
4982 }
4983
4984 // average the level set function all the way down
4985 // overwrite tempCells
4986 while(noTempCells > 0) {
4987 MInt listSize = noTempCells;
4988 noTempCells = 0;
4989 for(MInt cell = 0; cell < listSize; cell++) {
4990 MInt gCellId = tempCells.p[cell];
4991 MInt parentId = c_parentId(gCellId);
4992 if(parentId > -1) {
4993 if(!skip.p[parentId]) {
4994 tempCells.p[noTempCells] = parentId;
4995 noTempCells++;
4996 a_levelSetFunctionG(parentId, set) = F0;
4997 MInt noChildren = c_noChildren(parentId);
4998 if(!(noChildren > 0)) {
4999 cerr << parentId << endl;
5000 cerr << "gcell: " << gCellId << endl;
5001 mTerm(1, AT_, "this should not occur: parent g cell with m_noChildIdsG == 0...");
5002 }
5003 for(MInt child = 0; child < IPOW2(nDim); child++) {
5004 if(c_childId(parentId, child) < 0) continue;
5005 a_levelSetFunctionG(parentId, set) += a_levelSetFunctionG(c_childId(parentId, child), set);
5006 }
5007 a_levelSetFunctionG(parentId, set) /= (MFloat)noChildren;
5008 skip.p[parentId] = true;
5009 }
5010 }
5011 }
5012 }
5013 }
5014}
5015
5016
5017// ----------------------------------------------------------------------------------------
5018
5019
5035template <MInt nDim>
5037 TRACE();
5038 MInt startSet = 0;
5039 MInt endSet = m_noSets;
5040 if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
5041 if(computingSet >= 0) {
5042 startSet = computingSet;
5043 endSet = computingSet + 1;
5044 ASSERT(m_computeSet[computingSet], "");
5045 ASSERT(m_changedSet[computingSet], "");
5046 }
5047 const MInt noSets = endSet - startSet;
5048
5049
5050 // if computingSet is explicitly set to zero, reset noBandcells
5051 // default is: computingSet = -1, zero is only used for operations on the collected level-set function
5052 if(computingSet == 0) m_bandCells[computingSet].clear();
5053 //---end of initialization
5054
5055 for(MInt set = startSet; set < endSet; set++) {
5056 if(!m_computeSet[set]) continue;
5057 if(computingSet < 0 && m_levelSetMb) m_changedSet[set] = false;
5058
5059 // reset g cut cell counter
5060 std::vector<MInt>().swap(m_G0Cells[set]);
5061
5062 if(a_noBandCells(set) == 0) {
5063 // use all leaf-cells
5064 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
5065 a_inBandG(cellId, set) = false;
5066 a_isGBoundaryCellG(cellId, set) = false;
5067 a_isGZeroCell(cellId, set) = false;
5068 }
5069 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
5070 if(!c_isLeafCell(cellId)) continue;
5071 if(approx(a_levelSetFunctionG(cellId, set), F0, MFloatEps) && !a_isHalo(cellId)) {
5072 a_inBandG(cellId, set) = true;
5073 a_isGBoundaryCellG(cellId, set) = true;
5074 m_G0Cells[set].push_back(cellId);
5075 a_isGZeroCell(cellId, set) = true;
5076 if(!a_wasGZeroCell(cellId, set)) m_changedSet[set] = true;
5077
5078 } else {
5079 for(MInt d = 0; d < m_noDirs; d++) {
5080 MInt parentId = cellId;
5081 // consider level-jumps between neighbors:
5082 // important if working with very small geometries embedded in a huge domain
5083 // -> huge level differences
5084 MInt nghbrId = -1;
5085 if(!a_hasNeighbor(cellId, d)) {
5086 while(true) {
5087 parentId = c_parentId(parentId);
5088 if(parentId == -1) break;
5089 if(a_hasNeighbor(parentId, d)) {
5090 if(c_noChildren(c_neighborId(parentId, d)) == 0) break;
5091 }
5092 }
5093 if(parentId == -1) continue;
5094 nghbrId = c_neighborId(parentId, d);
5095 } else {
5096 nghbrId = c_neighborId(cellId, d);
5097 }
5098 if(nghbrId < 0) continue;
5099 if(!c_isLeafCell(nghbrId)) continue;
5100 if(a_levelSetFunctionG(nghbrId, set) * a_levelSetFunctionG(cellId, set) < F0) {
5101 if(!a_isGZeroCell(cellId, set) && !a_isHalo(cellId)) {
5102 a_inBandG(cellId, set) = true;
5103 a_isGBoundaryCellG(cellId, set) = true;
5104 m_G0Cells[set].push_back(cellId);
5105 a_isGZeroCell(cellId, set) = true;
5106 if(!a_wasGZeroCell(cellId, set)) m_changedSet[set] = true;
5107 }
5108 if(parentId != cellId && !a_isGZeroCell(nghbrId, set) && !a_isHalo(nghbrId)) {
5109 a_inBandG(nghbrId, set) = true;
5110 a_isGBoundaryCellG(nghbrId, set) = true;
5111 m_G0Cells[set].push_back(nghbrId);
5112 a_isGZeroCell(nghbrId, set) = true;
5113 if(!a_wasGZeroCell(nghbrId, set)) m_changedSet[set] = true;
5114 }
5115 }
5116 }
5117 }
5118 }
5119 } else {
5120 // use only previous band-cells, which must be at the highest refinement level!
5121 for(MInt id = 0; id < a_noBandCells(set); id++) {
5122 const MInt cellId = a_bandCellId(id, set);
5123 a_inBandG(cellId, set) = false;
5124 a_isGBoundaryCellG(cellId, set) = false;
5125 a_isGZeroCell(cellId, set) = false;
5126 if(a_isHalo(cellId)) continue;
5127 if(approx(a_levelSetFunctionG(cellId, set), F0, MFloatEps)) {
5128 a_inBandG(cellId, set) = true;
5129 a_isGBoundaryCellG(cellId, set) = true;
5130 m_G0Cells[set].push_back(cellId);
5131 a_isGZeroCell(cellId, set) = true;
5132 if(!a_wasGZeroCell(cellId, set)) m_changedSet[set] = true;
5133 } else {
5134 for(MInt d = 0; d < m_noDirs; d++) {
5135 if(!a_hasNeighbor(cellId, d)) continue;
5136 if(!c_isLeafCell(c_neighborId(cellId, d))) continue;
5137 if((a_levelSetFunctionG(c_neighborId(cellId, d), set) * a_levelSetFunctionG(cellId, set) < F0)) {
5138 a_inBandG(cellId, set) = true;
5139 a_isGBoundaryCellG(cellId, set) = true;
5140 m_G0Cells[set].push_back(cellId);
5141 a_isGZeroCell(cellId, set) = true;
5142 if(!a_wasGZeroCell(cellId, set)) m_changedSet[set] = true;
5143 break;
5144 }
5145 }
5146 }
5147 }
5148 }
5149 // determine the internal level set front cells
5150 a_internalBandLayer(0, set) = 0;
5151 std::vector<MInt>().swap(m_internalBandCells[set]);
5152 for(MInt id = 0; id < a_noG0Cells(set); id++) {
5153 if(!a_isHalo(a_G0CellId(id, set))) {
5154 a_internalBandLayer(0, set)++;
5155 m_internalBandCells[set].push_back(a_G0CellId(id, set));
5156 }
5157 }
5158 }
5159
5160 // exchange G0 cells for all sets with other domains
5161 MBoolScratchSpace tmp_data(a_noCells(), noSets, AT_, "tmp_data");
5162
5163 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5164 for(MInt j = 0; j < noWindowCells(i); j++) {
5165 MInt dataSet = 0;
5166 for(MInt set = startSet; set < endSet; set++) {
5167 tmp_data(windowCellId(i, j), dataSet) = a_isGZeroCell(windowCellId(i, j), set);
5168 dataSet++;
5169 }
5170 }
5171 }
5172 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5173 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
5174 MInt dataSet = 0;
5175 for(MInt set = startSet; set < endSet; set++) {
5176 MInt windowId = grid().azimuthalWindowCell(i, j);
5177 tmp_data(windowId, dataSet) = a_isGZeroCell(windowId, set);
5178 dataSet++;
5179 }
5180 }
5181 }
5182
5183 exchangeDataLS(&tmp_data(0, 0), noSets);
5184
5185 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5186 for(MInt j = 0; j < noHaloCells(i); j++) {
5187 const MInt haloCell = haloCellId(i, j);
5188 MInt dataSet = 0;
5189 for(MInt set = startSet; set < endSet; set++) {
5190 if(!a_isGZeroCell(haloCell, set)) {
5191 a_isGZeroCell(haloCell, set) = tmp_data(haloCellId(i, j), dataSet);
5192 if(a_isGZeroCell(haloCell, set)) {
5193 m_G0Cells[set].push_back(haloCell);
5194 a_inBandG(haloCell, set) = true;
5195 a_isGBoundaryCellG(haloCell, set) = true;
5196 if(!a_wasGZeroCell(haloCell, set)) m_changedSet[set] = true;
5197 }
5198 }
5199 dataSet++;
5200 }
5201 }
5202 }
5203 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5204 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
5205 const MInt haloCell = grid().azimuthalHaloCell(i, j);
5206 MInt dataSet = 0;
5207 for(MInt set = startSet; set < endSet; set++) {
5208 if(!a_isGZeroCell(haloCell, set)) {
5209 a_isGZeroCell(haloCell, set) = tmp_data(haloCell, dataSet);
5210 if(a_isGZeroCell(haloCell, set)) {
5211 m_G0Cells[set].push_back(haloCell);
5212 a_inBandG(haloCell, set) = true;
5213 a_isGBoundaryCellG(haloCell, set) = true;
5214 if(!a_wasGZeroCell(haloCell, set)) {
5215 m_changedSet[set] = true;
5216 }
5217 }
5218 }
5219 dataSet++;
5220 }
5221 }
5222 }
5223
5224 // rebuild G0 cells for phi^0 as set union of G0 cells of phi^i
5225 if(m_buildCollectedLevelSetFunction && m_determineG0CellsMode && computingSet <= 0) {
5226 startSet = 1;
5227 MInt changeSet = 0;
5228 // reset G0 cells of phi^0
5229 for(MInt id = 0; id < a_noG0Cells(changeSet); id++) {
5230 MInt cellId = a_G0CellId(id, changeSet);
5231 a_inBandG(cellId, changeSet) = false;
5232 a_isGBoundaryCellG(cellId, changeSet) = false;
5233 a_isGZeroCell(cellId, changeSet) = false;
5234 }
5235 std::vector<MInt>().swap(m_G0Cells[changeSet]);
5236 for(MInt set = startSet; set < endSet; set++) {
5237 for(MInt id = 0; id < a_noG0Cells(set); id++) {
5238 MInt cellId = a_G0CellId(id, set);
5239 if(!a_isGZeroCell(cellId, changeSet)) {
5240 a_inBandG(cellId, changeSet) = true;
5241 a_isGBoundaryCellG(cellId, changeSet) = true;
5242 m_G0Cells[changeSet].push_back(cellId);
5243 a_isGZeroCell(cellId, changeSet) = true;
5244 if(!a_wasGZeroCell(cellId, changeSet)) m_changedSet[changeSet] = true;
5245 }
5246 }
5247 }
5248 }
5249
5250 // NOTE: the changedSet information is currently only used to skip the identifyBodies call!
5251 // TODO labels:LS,totest check why the determineBandCells can currently not be skipped if the G0-cells stay the same
5252 if(m_levelSetMb) {
5253 for(MInt set = startSet; set < endSet; set++) {
5254 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
5255 if(a_wasGZeroCell(cellId, set) && !a_isGZeroCell(cellId, set)) {
5256 m_changedSet[set] = true;
5257 }
5258 }
5259 }
5260
5261 MIntScratchSpace changedSet(m_noSets, AT_, "changedSet");
5262 for(MInt set = startSet; set < endSet; set++) {
5263 if(m_changedSet[set])
5264 changedSet[set] = 1;
5265 else
5266 changedSet[set] = -1;
5267 }
5268
5269 // exchange m_changedSet-property
5270 MPI_Allreduce(MPI_IN_PLACE, &changedSet[0], m_noSets, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
5271 "changedSet[0]");
5272
5273 for(MInt set = startSet; set < endSet; set++) {
5274 if(changedSet[set] > 0) {
5275 m_changedSet[set] = true;
5276 } else {
5277 m_changedSet[set] = false;
5278 }
5279 if(globalTimeStep <= 0) {
5280 m_changedSet[set] = true;
5281 m_changedSet[0] = true;
5282 }
5283 }
5284
5285 if(computingSet >= 0) ASSERT(m_changedSet[computingSet], "");
5286 }
5287}
5288
5289
5290// ----------------------------------------------------------------------------------------
5291
5292
5293template <MInt nDim>
5295 TRACE();
5296 MInt startSet = 0;
5297 MInt endSet = m_noSets;
5298 if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
5299 if(computingSet >= 0) {
5300 startSet = computingSet;
5301 endSet = computingSet + 1;
5302 ASSERT(m_computeSet[computingSet], "");
5303 ASSERT(m_changedSet[computingSet], "");
5304 }
5305
5306 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
5307
5308 MIntScratchSpace temp(a_noCells(), AT_, "temp");
5309 MIntScratchSpace lastLayer(a_noCells(), AT_, "lastLayer");
5310
5311 //---
5312
5313 for(MInt set = startSet; set < endSet; set++) {
5314 if(!m_computeSet[set]) continue;
5315
5316 // if( computingSet < 0 && !m_changedSet[set] &&
5317 // (m_levelSetMb) && !m_LsRotate) continue;
5318
5319 // reset band cell counters
5320 std::vector<MInt>().swap(m_bandBndryCells[set]);
5321
5322 // put the level set G0-cells into the band
5323 a_bandLayer(0, set) = a_noG0Cells(set);
5324 MInt layerCount = 1;
5325 MInt cnt = 0;
5326
5327 std::vector<MInt>().swap(m_bandCells[set]);
5328 for(MInt id = 0; id < a_noG0Cells(set); id++) {
5329 m_bandCells[set].push_back(a_G0CellId(id, set));
5330 }
5331
5332 // only then extend the first layer
5333 // by adding all existing neighbors which are not Halo-Cells to the band and lastLayer
5334 for(MInt id = 0; id < a_noG0Cells(set); id++) {
5335 const MInt cellId = a_G0CellId(id, set);
5336 a_isGBoundaryCellG(cellId, set) = false;
5337 // activate all neighbors
5338 for(MInt dir = 0; dir < m_noDirs; dir++) {
5339 const MInt nghbrId = c_neighborId(cellId, dir);
5340 if(nghbrId == -1) continue;
5341 if(a_isHalo(nghbrId)) continue;
5342 if(a_inBandG(nghbrId, set)) continue;
5343 lastLayer.p[cnt++] = nghbrId;
5344 a_inBandG(nghbrId, set) = true;
5345 m_bandCells[set].push_back(nghbrId);
5346 }
5347 }
5348
5349 // exchange band cells for the current set with other domains
5350 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5351 for(MInt j = 0; j < noWindowCells(i); j++) {
5352 tmp_data(windowCellId(i, j)) = a_inBandG(windowCellId(i, j), set);
5353 }
5354 }
5355 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5356 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
5357 MInt windowId = grid().azimuthalWindowCell(i, j);
5358 tmp_data(windowId) = a_inBandG(windowId, set);
5359 }
5360 }
5361
5362 exchangeDataLS(&tmp_data(0), 1);
5363
5364 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5365 for(MInt j = 0; j < noHaloCells(i); j++) {
5366 const MInt halocell = haloCellId(i, j);
5367 if(!a_inBandG(halocell, set)) {
5368 a_inBandG(halocell, set) = tmp_data(halocell);
5369 if(a_inBandG(halocell, set)) {
5370 m_bandCells[set].push_back(halocell);
5371 lastLayer.p[cnt++] = halocell;
5372 }
5373 }
5374 }
5375 }
5376 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5377 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
5378 const MInt haloCell = grid().azimuthalHaloCell(i, j);
5379 if(!a_inBandG(haloCell, set)) {
5380 a_inBandG(haloCell, set) = tmp_data(haloCell);
5381 if(a_inBandG(haloCell, set)) {
5382 m_bandCells[set].push_back(haloCell);
5383 lastLayer.p[cnt++] = haloCell;
5384 }
5385 }
5386 }
5387 }
5388
5389 a_bandLayer(layerCount, set) = a_noBandCells(set);
5390
5391 // extend all other layers
5392 // no add all layers iterativly
5393 while(layerCount < m_gBandWidth) {
5394 MInt tempCnt = 0;
5395 for(MInt c = 0; c < cnt; c++) {
5396 a_isGBoundaryCellG(lastLayer.p[c], set) = false;
5397 // activate all neighbors
5398 for(MInt dir = 0; dir < m_noDirs; dir++) {
5399 const MInt nghbrId = c_neighborId(lastLayer.p[c], dir);
5400 if(nghbrId == -1) continue;
5401 if(a_isHalo(nghbrId)) continue;
5402 if(a_inBandG(nghbrId, set)) continue;
5403 temp.p[tempCnt++] = nghbrId;
5404 a_inBandG(nghbrId, set) = true;
5405 m_bandCells[set].push_back(nghbrId);
5406 }
5407 }
5408
5409
5410 // exchange band cells for all sets with other domains
5411 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5412 for(MInt j = 0; j < noWindowCells(i); j++) {
5413 tmp_data(windowCellId(i, j)) = a_inBandG(windowCellId(i, j), set);
5414 }
5415 }
5416 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5417 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
5418 MInt windowId = grid().azimuthalWindowCell(i, j);
5419 tmp_data(windowId) = a_inBandG(windowId, set);
5420 }
5421 }
5422
5423 exchangeDataLS(&tmp_data(0), 1);
5424
5425 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5426 for(MInt j = 0; j < noHaloCells(i); j++) {
5427 const MInt halocell = haloCellId(i, j);
5428 if(!a_inBandG(halocell, set)) {
5429 a_inBandG(halocell, set) = tmp_data(halocell);
5430 if(a_inBandG(halocell, set)) {
5431 m_bandCells[set].push_back(halocell);
5432 temp.p[tempCnt++] = halocell;
5433 }
5434 }
5435 }
5436 }
5437 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5438 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
5439 const MInt haloCell = grid().azimuthalHaloCell(i, j);
5440 if(!a_inBandG(haloCell, set)) {
5441 a_inBandG(haloCell, set) = tmp_data(haloCell);
5442 if(a_inBandG(haloCell, set)) {
5443 m_bandCells[set].push_back(haloCell);
5444 temp.p[tempCnt++] = haloCell;
5445 }
5446 }
5447 }
5448 }
5449
5450 layerCount++;
5451 a_bandLayer(layerCount, set) = a_noBandCells(set);
5452 cnt = tempCnt;
5453 for(MInt c = 0; c < tempCnt; c++) {
5454 lastLayer.p[c] = temp.p[c];
5455 }
5456 }
5457
5458
5459 // set the last-layer as a_isGBoundaryCellG!
5460 // determine the G boundary cells
5461 for(MInt c = 0; c < cnt; c++) {
5462 a_isGBoundaryCellG(lastLayer.p[c], set) = true;
5463 m_bandBndryCells[set].push_back(lastLayer.p[c]);
5464 }
5465
5466 // set the internal band layers
5467 // only relevant for reinitialization!
5468 for(MInt layer = 1; layer < m_gBandWidth + 1; layer++) {
5469 a_internalBandLayer(layer, set) = a_internalBandLayer(layer - 1, set);
5470 for(MInt id = a_bandLayer(layer - 1, set); id < a_bandLayer(layer, set); id++) {
5471 if(!a_isHalo(a_bandCellId(id, set))) {
5472 a_internalBandLayer(layer, set)++;
5473 m_internalBandCells[set].push_back(a_bandCellId(id, set));
5474 }
5475 }
5476 }
5477 }
5478}
5479
5480
5481// ----------------------------------------------------------------------------------------
5482
5483
5494template <MInt nDim>
5496 TRACE();
5497
5498 for(MInt set = 0; set < m_noSets; set++) {
5499 if(!m_computeSet[set]) continue;
5500 switch(m_levelSetBoundaryCondition) {
5501 case 19940404: {
5502 MInt noGBndryCellsBackup = a_noGBndryCells(set);
5503
5504 // inflow boundary
5505 MInt nghbrXL = -1, nghbrXR = -1, nghbrXL2 = -1, nghbrXR2 = -1, parent, cellId;
5506 MInt nghbrYL = -1, nghbrYR = -1, nghbrYL2 = -1, nghbrYR2 = -1;
5507
5508 // reset g boundary information for level set domain boundary cells
5509 for(MInt id = 0; id < a_noBandCells(set); id++) {
5510 a_isBndryCellG(a_bandCellId(id, set)) = false;
5511 }
5512
5513 std::vector<MInt>().swap(m_gBndryCells[set]);
5514
5515 for(MInt id = 0; id < a_noBandCells(set); id++) {
5516 cellId = a_bandCellId(id, set);
5517 if(a_isHalo(cellId)) continue;
5518
5519 nghbrXL = c_neighborId(cellId, 0);
5520 nghbrXL2 = c_neighborId(nghbrXL, 0);
5521 nghbrXR = c_neighborId(cellId, 1);
5522 nghbrXR2 = c_neighborId(nghbrXR, 1);
5523
5524 nghbrYL = c_neighborId(cellId, 2);
5525 nghbrYL2 = c_neighborId(nghbrYL, 2);
5526 nghbrYR = c_neighborId(cellId, 3);
5527 nghbrYR2 = c_neighborId(nghbrYR, 3);
5528
5529 for(MInt i = 0; i < nDim; i++) {
5530 parent = c_parentId(cellId);
5531
5532 if(a_hasNeighbor(cellId, 2 + i) == 0) {
5533 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5534 m_gBndryCells[set].push_back(cellId);
5535 a_isGBoundaryCellG(cellId, set) = true;
5536 a_isBndryCellG(cellId) = true;
5537 }
5538 }
5539
5540 if(a_hasNeighbor(nghbrXL, 2 + i) == 0) {
5541 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5542 m_gBndryCells[set].push_back(cellId);
5543 a_isGBoundaryCellG(cellId, set) = true;
5544 a_isBndryCellG(cellId) = true;
5545 }
5546 if(!a_isHalo(nghbrXL))
5547 if(a_inBandG(nghbrXL, set) && a_level(nghbrXL) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXL)) {
5548 m_gBndryCells[set].push_back(nghbrXL);
5549 a_isGBoundaryCellG(nghbrXL, set) = true;
5550 a_isBndryCellG(nghbrXL) = true;
5551 }
5552 }
5553
5554 if(a_hasNeighbor(nghbrXL2, 2 + i) == 0) {
5555 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5556 m_gBndryCells[set].push_back(cellId);
5557 a_isGBoundaryCellG(cellId, set) = true;
5558 a_isBndryCellG(cellId) = true;
5559 }
5560 if(!a_isHalo(nghbrXL2))
5561 if(a_inBandG(nghbrXL2, set) && a_level(nghbrXL2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXL2)) {
5562 m_gBndryCells[set].push_back(nghbrXL2);
5563 a_isGBoundaryCellG(nghbrXL2, set) = true;
5564 a_isBndryCellG(nghbrXL2) = true;
5565 }
5566 }
5567
5568 if(a_hasNeighbor(nghbrXR, 2 + i) == 0) {
5569 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5570 m_gBndryCells[set].push_back(cellId);
5571 a_isGBoundaryCellG(cellId, set) = true;
5572 a_isBndryCellG(cellId) = true;
5573 }
5574 if(!a_isHalo(nghbrXR))
5575 if(a_inBandG(nghbrXR, set) && a_level(nghbrXR) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXR)) {
5576 m_gBndryCells[set].push_back(nghbrXR);
5577 a_isGBoundaryCellG(nghbrXR, set) = true;
5578 a_isBndryCellG(nghbrXR) = true;
5579 }
5580 }
5581
5582 if(a_hasNeighbor(nghbrXR2, 2 + i) == 0) {
5583 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5584 m_gBndryCells[set].push_back(cellId);
5585 a_isGBoundaryCellG(cellId, set) = true;
5586 a_isBndryCellG(cellId) = true;
5587 }
5588 if(!a_isHalo(nghbrXR2))
5589 if(a_inBandG(nghbrXR2, set) && a_level(nghbrXR2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXR2)) {
5590 m_gBndryCells[set].push_back(nghbrXR2);
5591 a_isGBoundaryCellG(nghbrXR2, set) = true;
5592 a_isBndryCellG(nghbrXR2) = true;
5593 }
5594 }
5595
5596 if(a_hasNeighbor(nghbrYL, i) == 0) {
5597 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5598 m_gBndryCells[set].push_back(cellId);
5599 a_isGBoundaryCellG(cellId, set) = true;
5600 a_isBndryCellG(cellId) = true;
5601 }
5602 if(!a_isHalo(nghbrYL))
5603 if(a_inBandG(nghbrYL, set) && a_level(nghbrYL) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYL)) {
5604 m_gBndryCells[set].push_back(nghbrYL);
5605 a_isGBoundaryCellG(nghbrYL, set) = true;
5606 a_isBndryCellG(nghbrYL) = true;
5607 }
5608 }
5609
5610 if(a_hasNeighbor(nghbrYL2, i) == 0) {
5611 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5612 m_gBndryCells[set].push_back(cellId);
5613 a_isGBoundaryCellG(cellId, set) = true;
5614 a_isBndryCellG(cellId) = true;
5615 }
5616 if(!a_isHalo(nghbrYL2))
5617 if(a_inBandG(nghbrYL2, set) && a_level(nghbrYL2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYL2)) {
5618 m_gBndryCells[set].push_back(nghbrYL2);
5619 a_isGBoundaryCellG(nghbrYL2, set) = true;
5620 a_isBndryCellG(nghbrYL2) = true;
5621 }
5622 }
5623
5624 if(a_hasNeighbor(nghbrYR, i) == 0) {
5625 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5626 m_gBndryCells[set].push_back(cellId);
5627 a_isGBoundaryCellG(cellId, set) = true;
5628 a_isBndryCellG(cellId) = true;
5629 }
5630 if(!a_isHalo(nghbrYR))
5631 if(a_inBandG(nghbrYR, set) && a_level(nghbrYR) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYR)) {
5632 m_gBndryCells[set].push_back(nghbrYR);
5633 a_isGBoundaryCellG(nghbrYR, set) = true;
5634 a_isBndryCellG(nghbrYR) = true;
5635 }
5636 }
5637
5638 if(a_hasNeighbor(nghbrYR2, i) == 0) {
5639 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5640 m_gBndryCells[set].push_back(cellId);
5641 a_isGBoundaryCellG(cellId, set) = true;
5642 a_isBndryCellG(cellId) = true;
5643 }
5644 if(!a_isHalo(nghbrYR2))
5645 if(a_inBandG(nghbrYR2, set) && a_level(nghbrYR2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYR2)) {
5646 m_gBndryCells[set].push_back(nghbrYR2);
5647 a_isGBoundaryCellG(nghbrYR2, set) = true;
5648 a_isBndryCellG(nghbrYR2) = true;
5649 }
5650 }
5651
5652 if(parent > -1) {
5653 if(a_hasNeighbor(parent, 2 * i) == 0) {
5654 for(MInt ch = 0; ch < IPOW2(nDim); ch++) {
5655 if(c_childId(parent, ch) < 0) continue;
5656 if(a_isHalo(c_childId(parent, ch))) continue;
5657 if(a_isBndryCellG(c_childId(parent, ch))) continue;
5658 if(!a_inBandG(c_childId(parent, ch), set)) continue;
5659 if(a_level(c_childId(parent, ch)) != a_maxGCellLevel()) continue;
5660 m_gBndryCells[set].push_back(c_childId(parent, ch));
5661 a_isGBoundaryCellG(c_childId(parent, ch), set) = true;
5662 a_isBndryCellG(c_childId(parent, ch)) = true;
5663 }
5664 }
5665 }
5666
5667 if(parent > -1)
5668 if(a_hasNeighbor(parent, 2 * i + 1) == 0) {
5669 for(MInt ch = 0; ch < IPOW2(nDim); ch++) {
5670 if(c_childId(parent, ch) < 0) continue;
5671 if(a_isHalo(c_childId(parent, ch))) continue;
5672 if(a_isBndryCellG(c_childId(parent, ch))) continue;
5673 if(!a_inBandG(c_childId(parent, ch), set)) continue;
5674 if(a_level(c_childId(parent, ch)) != a_maxGCellLevel()) continue;
5675 m_gBndryCells[set].push_back(c_childId(parent, ch));
5676 a_isGBoundaryCellG(c_childId(parent, ch), set) = true;
5677 a_isBndryCellG(c_childId(parent, ch)) = true;
5678 }
5679 }
5680 }
5681 }
5682
5683 MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
5684 MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
5685 // gather:
5686 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5687 sendBufferSize.p[i] = 0;
5688 for(MInt j = 0; j < noWindowCells(i); j++) {
5689 m_intSendBuffers[i][sendBufferSize.p[i]++] = a_isBndryCellG(windowCellId(i, j));
5690 }
5691 }
5692 if(grid().azimuthalPeriodicity()) {
5693 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5694 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
5695 m_intSendBuffers[i][sendBufferSize.p[i]++] = a_isBndryCellG(grid().azimuthalWindowCell(i, j));
5696 }
5697 }
5698 }
5699
5700 // exchange data -> send, receive
5701 exchangeIntBuffers(sendBufferSize.getPointer(), receiveBufferSize.getPointer(), 9, 1);
5702
5703 // scatter:
5704 // update the window cell list with the halo cells
5705
5706 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5707#ifdef LS_DEBUG
5708 // MInt windowBndryCnt = 0;
5709 // check, if received data size matches expected size:
5710 if(receiveBufferSize.p[i] != noHaloCells(i))
5711 mTerm(1, AT_, "this was not expected to happen: wrong number of window information...");
5712#endif
5713 for(MInt j = 0; j < noHaloCells(i); j++) {
5714 MInt haloCell = haloCellId(i, j);
5715 // check if window cell is a boundary cell, otherwise it'll be overwritten from the neighbor domains
5716 if(m_intReceiveBuffers[i][j]) {
5717 a_isBndryCellG(haloCell) = m_intReceiveBuffers[i][j];
5718 a_isGBoundaryCellG(haloCell, set) = m_intReceiveBuffers[i][j];
5719 if(a_isBndryCellG(haloCell)) {
5720 m_gBndryCells[set].push_back(haloCell);
5721 }
5722 }
5723 }
5724 }
5725 if(grid().azimuthalPeriodicity()) {
5726 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
5727 MInt offset = noHaloCells(grid().azimuthalNeighborDomain(i));
5728 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
5729 MInt n = offset + j;
5730 MInt haloCell = grid().azimuthalHaloCell(i, j);
5731 if(m_intReceiveBuffers[i][n]) {
5732 a_isBndryCellG(haloCell) = m_intReceiveBuffers[i][n];
5733 a_isGBoundaryCellG(haloCell, set) = m_intReceiveBuffers[i][n];
5734 if(a_isBndryCellG(haloCell)) {
5735 m_gBndryCells[set].push_back(haloCell);
5736 }
5737 }
5738 }
5739 }
5740 }
5741 if(noGBndryCellsBackup != a_noGBndryCells(set) || globalTimeStep == 0) {
5742 m_log << "Number of level set boundary cells changed: " << endl;
5743 m_log << a_noGBndryCells(set) << " G boundary cells created..." << endl;
5744 }
5745 break;
5746 }
5747 case 17516: {
5748 MInt noGBndryCellsBackup = a_noGBndryCells(set);
5749 MFloat deltaX = m_flameRadiusOffset;
5750
5751 if(m_twoFlames) {
5752 std::vector<MInt>().swap(m_gBndryCells[set]);
5753 for(MInt id = 0; id < a_noBandCells(set); id++) {
5754 if(c_coordinate(a_bandCellId(id, set), 1) < F0 || c_coordinate(a_bandCellId(id, set), 1) > m_gCellDistance)
5755 continue;
5756 m_gBndryCells[set].push_back(a_bandCellId(id, set));
5757 }
5758
5759 } else {
5760 // inflow boundary
5761 MInt nghbrXL = -1, nghbrXR = -1, nghbrXL2 = -1, nghbrXR2 = -1, parent, cellId;
5762 MInt nghbrYL = -1, nghbrYR = -1, nghbrYL2 = -1, nghbrYR2 = -1;
5763
5764 // reset g boundary information for level set domain boundary cells
5765 for(MInt id = 0; id < a_noBandCells(set); id++) {
5766 a_isBndryCellG(a_bandCellId(id, set)) = false;
5767 }
5768
5769 std::vector<MInt>().swap(m_gBndryCells[set]);
5770
5771 for(MInt id = 0; id < a_noBandCells(set); id++) {
5772 cellId = a_bandCellId(id, set);
5773 if(a_isHalo(cellId)) continue;
5774
5775 nghbrXL = c_neighborId(cellId, 0);
5776 nghbrXL2 = c_neighborId(nghbrXL, 0);
5777 nghbrXR = c_neighborId(cellId, 1);
5778 nghbrXR2 = c_neighborId(nghbrXR, 1);
5779
5780 nghbrYL = c_neighborId(cellId, 2);
5781 nghbrYL2 = c_neighborId(nghbrYL, 2);
5782 nghbrYR = c_neighborId(cellId, 3);
5783 nghbrYR2 = c_neighborId(nghbrYR, 3);
5784
5785 if(c_coordinate(cellId, 1) < (m_yOffsetFlameTube - 0.1)) continue;
5786
5787 if(c_coordinate(cellId, 1) > (m_yOffsetFlameTube + 0.1)) continue;
5788
5789 if(ABS(c_coordinate(cellId, 0)) > (m_radiusFlameTube + deltaX + 0.1)) continue;
5790
5791 for(MInt i = 0; i < nDim; i++) {
5792 parent = c_parentId(cellId);
5793
5794 if(a_hasNeighbor(cellId, 2 + i) == 0) {
5795 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5796 m_gBndryCells[set].push_back(cellId);
5797 a_isGBoundaryCellG(cellId, set) = true;
5798 a_isBndryCellG(cellId) = true;
5799 }
5800 }
5801
5802 if(a_hasNeighbor(nghbrXL, 2 + i) == 0) {
5803 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5804 // if(!a_isBndryCellG(cellId))
5805 m_gBndryCells[set].push_back(cellId);
5806 a_isGBoundaryCellG(cellId, set) = true;
5807 a_isBndryCellG(cellId) = true;
5808 }
5809 if(!a_isHalo(nghbrXL))
5810 if(a_inBandG(nghbrXL, set) && a_level(nghbrXL) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXL)) {
5811 // if(a_inBandG(nghbrXL, set ) && !a_isBndryCellG(nghbrXL))
5812 m_gBndryCells[set].push_back(nghbrXL);
5813 a_isGBoundaryCellG(nghbrXL, set) = true;
5814 a_isBndryCellG(nghbrXL) = true;
5815 }
5816 }
5817
5818 if(a_hasNeighbor(nghbrXL2, 2 + i) == 0) {
5819 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5820 // if(!a_isBndryCellG(cellId))
5821 m_gBndryCells[set].push_back(cellId);
5822 a_isGBoundaryCellG(cellId, set) = true;
5823 a_isBndryCellG(cellId) = true;
5824 }
5825 if(!a_isHalo(nghbrXL2))
5826 if(a_inBandG(nghbrXL2, set) && a_level(nghbrXL2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXL2)) {
5827 // if(a_inBandG(nghbrXL2, set ) && !a_isBndryCellG(nghbrXL2))
5828 m_gBndryCells[set].push_back(nghbrXL2);
5829 a_isGBoundaryCellG(nghbrXL2, set) = true;
5830 a_isBndryCellG(nghbrXL2) = true;
5831 }
5832 }
5833
5834 if(a_hasNeighbor(nghbrXR, 2 + i) == 0) {
5835 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5836 // if(!a_isBndryCellG(cellId))
5837 m_gBndryCells[set].push_back(cellId);
5838 a_isGBoundaryCellG(cellId, set) = true;
5839 a_isBndryCellG(cellId) = true;
5840 }
5841 if(!a_isHalo(nghbrXR))
5842 if(a_inBandG(nghbrXR, set) && a_level(nghbrXR) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXR)) {
5843 // if(a_inBandG(nghbrXR, set ) && !a_isBndryCellG(nghbrXR))
5844 m_gBndryCells[set].push_back(nghbrXR);
5845 a_isGBoundaryCellG(nghbrXR, set) = true;
5846 a_isBndryCellG(nghbrXR) = true;
5847 }
5848 }
5849
5850 if(a_hasNeighbor(nghbrXR2, 2 + i) == 0) {
5851 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5852 // if(!a_isBndryCellG(cellId))
5853 m_gBndryCells[set].push_back(cellId);
5854 a_isGBoundaryCellG(cellId, set) = true;
5855 a_isBndryCellG(cellId) = true;
5856 }
5857 if(!a_isHalo(nghbrXR2))
5858 if(a_inBandG(nghbrXR2, set) && a_level(nghbrXR2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrXR2)) {
5859 // if(a_inBandG(nghbrXR2, set ) && !a_isBndryCellG(nghbrXR2))
5860 m_gBndryCells[set].push_back(nghbrXR2);
5861 a_isGBoundaryCellG(nghbrXR2, set) = true;
5862 a_isBndryCellG(nghbrXR2) = true;
5863 }
5864 }
5865
5866 if(a_hasNeighbor(nghbrYL, i) == 0) {
5867 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5868 // if(!a_isBndryCellG(cellId))
5869 m_gBndryCells[set].push_back(cellId);
5870 a_isGBoundaryCellG(cellId, set) = true;
5871 a_isBndryCellG(cellId) = true;
5872 }
5873 if(!a_isHalo(nghbrYL))
5874 if(a_inBandG(nghbrYL, set) && a_level(nghbrYL) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYL)) {
5875 // if(a_inBandG(nghbrYL, set ) && !a_isBndryCellG(nghbrYL))
5876 m_gBndryCells[set].push_back(nghbrYL);
5877 a_isGBoundaryCellG(nghbrYL, set) = true;
5878 a_isBndryCellG(nghbrYL) = true;
5879 }
5880 }
5881
5882 if(a_hasNeighbor(nghbrYL2, i) == 0) {
5883 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5884 // if(!a_isBndryCellG(cellId))
5885 m_gBndryCells[set].push_back(cellId);
5886 a_isGBoundaryCellG(cellId, set) = true;
5887 a_isBndryCellG(cellId) = true;
5888 }
5889 if(!a_isHalo(nghbrYL2))
5890 if(a_inBandG(nghbrYL2, set) && a_level(nghbrYL2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYL2)) {
5891 // if(a_inBandG(nghbrYL2, set ) && !a_isBndryCellG(nghbrYL2))
5892 m_gBndryCells[set].push_back(nghbrYL2);
5893 a_isGBoundaryCellG(nghbrYL2, set) = true;
5894 a_isBndryCellG(nghbrYL2) = true;
5895 }
5896 }
5897
5898 if(a_hasNeighbor(nghbrYR, i) == 0) {
5899 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5900 // if(!a_isBndryCellG(cellId))
5901 m_gBndryCells[set].push_back(cellId);
5902 a_isGBoundaryCellG(cellId, set) = true;
5903 a_isBndryCellG(cellId) = true;
5904 }
5905 if(!a_isHalo(nghbrYR))
5906 if(a_inBandG(nghbrYR, set) && a_level(nghbrYR) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYR)) {
5907 // if(a_inBandG(nghbrYR, set ) && !a_isBndryCellG(nghbrYR))
5908 m_gBndryCells[set].push_back(nghbrYR);
5909 a_isGBoundaryCellG(nghbrYR, set) = true;
5910 a_isBndryCellG(nghbrYR) = true;
5911 }
5912 }
5913
5914 if(a_hasNeighbor(nghbrYR2, i) == 0) {
5915 if(a_level(cellId) == a_maxGCellLevel() && !a_isBndryCellG(cellId)) {
5916 // if(!a_isBndryCellG(cellId))
5917 m_gBndryCells[set].push_back(cellId);
5918 a_isGBoundaryCellG(cellId, set) = true;
5919 a_isBndryCellG(cellId) = true;
5920 }
5921 if(!a_isHalo(nghbrYR2))
5922 if(a_inBandG(nghbrYR2, set) && a_level(nghbrYR2) == a_maxGCellLevel() && !a_isBndryCellG(nghbrYR2)) {
5923 // if(a_inBandG(nghbrYR2, set ) && !a_isBndryCellG(nghbrYR2))
5924 m_gBndryCells[set].push_back(nghbrYR2);
5925 a_isGBoundaryCellG(nghbrYR2, set) = true;
5926 a_isBndryCellG(nghbrYR2) = true;
5927 }
5928 }
5929
5930 if(parent > -1) {
5931 if(a_hasNeighbor(parent, 2 * i) == 0) {
5932 for(MInt ch = 0; ch < IPOW2(nDim); ch++) {
5933 if(c_childId(parent, ch) < 0) continue;
5934 if(a_isHalo(c_childId(parent, ch))) continue;
5935 if(a_isBndryCellG(c_childId(parent, ch))) continue;
5936 if(!a_inBandG(c_childId(parent, ch), set)) continue;
5937 if(a_level(c_childId(parent, ch)) != a_maxGCellLevel()) continue;
5938 m_gBndryCells[set].push_back(c_childId(parent, ch));
5939 a_isGBoundaryCellG(c_childId(parent, ch), set) = true;
5940 a_isBndryCellG(c_childId(parent, ch)) = true;
5941 }
5942 }
5943 }
5944
5945 // parent = c_parentId(parent);
5946 //
5947 // parent = c_parentId( cellId );
5948 if(parent > -1)
5949 if(a_hasNeighbor(parent, 2 * i + 1) == 0) {
5950 for(MInt ch = 0; ch < IPOW2(nDim); ch++) {
5951 if(c_childId(parent, ch) < 0) continue;
5952 if(a_isHalo(c_childId(parent, ch))) continue;
5953 if(a_isBndryCellG(c_childId(parent, ch))) continue;
5954 if(!a_inBandG(c_childId(parent, ch), set)) continue;
5955 if(a_level(c_childId(parent, ch)) != a_maxGCellLevel()) continue;
5956 m_gBndryCells[set].push_back(c_childId(parent, ch));
5957 a_isGBoundaryCellG(c_childId(parent, ch), set) = true;
5958 a_isBndryCellG(c_childId(parent, ch)) = true;
5959 }
5960 }
5961 // parent = c_parentId(parent);
5962 //
5963 }
5964 }
5965 }
5966
5967 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
5968
5969 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5970 for(MInt j = 0; j < noWindowCells(i); j++) {
5971 tmp_data(windowCellId(i, j)) = a_isBndryCellG(windowCellId(i, j));
5972 }
5973 }
5974
5975 exchangeDataLS(&tmp_data(0), 1);
5976
5977 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
5978 for(MInt j = 0; j < noHaloCells(i); j++) {
5979 const MInt haloCell = haloCellId(i, j);
5980 // check if window cell is a boundary cell, otherwise it'll be overwritten from the neighbor domains
5981 if(tmp_data(haloCell)) {
5983 a_isBndryCellG(haloCell) = tmp_data(haloCell);
5984 a_isGBoundaryCellG(haloCell, set) = tmp_data(haloCell);
5985 if(a_isBndryCellG(haloCell)) {
5986 m_gBndryCells[set].push_back(haloCell);
5987 }
5988 }
5989 }
5990 }
5991
5992 if(noGBndryCellsBackup != a_noGBndryCells(set) || globalTimeStep == 0) {
5993 m_log << "Number of level set boundary cells changed: " << endl;
5994 m_log << a_noGBndryCells(set) << " G boundary cells created..." << endl;
5995 }
5996 break;
5997 }
5998
5999 case 1751600: {
6000 MInt noGBndryCellsBackup = a_noGBndryCells(set);
6001 MFloat deltaX = m_flameRadiusOffset;
6002 MInt nghbrId, nghbrIdT;
6003 MInt cnt;
6004
6005 // reset g boundary information for level set domain boundary cells
6006 for(MInt id = 0; id < a_noBandCells(set); id++) {
6007 a_isBndryCellG(a_bandCellId(id, set)) = false;
6008 }
6009
6010 std::vector<MInt>().swap(m_gBndryCells[set]);
6011
6012 for(MInt id = 0; id < a_noBandCells(set); id++) {
6013 MInt cellId = a_bandCellId(id, set);
6014
6015 if(a_isHalo(cellId)) continue;
6016
6017 if(a_level(cellId) != a_maxGCellLevel()) continue;
6018
6019
6020 IF_CONSTEXPR(nDim == 3) {
6021 if(c_coordinate(cellId, 1) < (m_yOffsetFlameTube - 0.05)) continue;
6022
6023 if(c_coordinate(cellId, 1) > (m_yOffsetFlameTube + 0.1)) continue;
6024
6025 if(ABS(c_coordinate(cellId, 0)) > (m_jetHalfWidth + 0.3)) continue;
6026
6027 if(ABS(c_coordinate(cellId, 0)) < (m_jetHalfWidth - 0.1)
6028 && ABS(c_coordinate(cellId, 2)) < (m_jetHalfLength - 0.10))
6029 continue;
6030
6031 if(ABS(c_coordinate(cellId, 2)) > (m_jetHalfLength + 0.3)) continue;
6032 }
6033 else {
6034 if(c_coordinate(cellId, 1) < (m_yOffsetFlameTube - 0.1)) continue;
6035
6036 if(c_coordinate(cellId, 1) > (m_yOffsetFlameTube + 0.1)) continue;
6037
6038 if(ABS(c_coordinate(cellId, 0)) > (m_radiusFlameTube + deltaX + 0.1)) continue;
6039 }
6040 for(MInt dirId = 0; dirId < nDim * 2; dirId++) {
6041 if(a_hasNeighbor(cellId, dirId) == 0 && a_level(cellId) == a_maxGCellLevel()) {
6042 a_isGBoundaryCellG(cellId, set) = true;
6043 a_isBndryCellG(cellId) = true;
6044 m_gBndryCells[set].push_back(cellId);
6045 }
6046 for(MInt dirIdS = 0; dirIdS < nDim * 2; dirIdS++) {
6047 if(dirId == dirIdS) continue;
6048 cnt = 0;
6049 nghbrId = cellId;
6050 while(cnt < 0) {
6051 MInt noNghbrIds = a_hasNeighbor(nghbrId, dirIdS);
6052 if(noNghbrIds == 0) break;
6053
6054 nghbrId = c_neighborId(nghbrId, dirIdS);
6055 if(nghbrId == -1) break;
6056
6057 if(a_isHalo(nghbrId)) break;
6058 if(!a_inBandG(nghbrId, set)) break;
6059 if(a_level(nghbrId) != a_maxGCellLevel()) break;
6060 if(!a_isBndryCellG(nghbrId)) {
6061 a_isGBoundaryCellG(nghbrId, set) = true;
6062 a_isBndryCellG(nghbrId) = true;
6063 m_gBndryCells[set].push_back(nghbrId);
6064 }
6065 for(MInt dirIdT = 0; dirIdT < nDim * 2; dirIdT++) {
6066 MInt noNghbrIdsT = a_hasNeighbor(nghbrId, dirIdT);
6067 if(noNghbrIdsT == 0) continue;
6068
6069 nghbrIdT = c_neighborId(nghbrId, dirIdT);
6070 if(nghbrIdT == -1) continue;
6071
6072 if(a_isHalo(nghbrIdT)) continue;
6073
6074 if(!a_inBandG(nghbrIdT, set)) continue;
6075 if(!a_isBndryCellG(nghbrIdT)) {
6076 a_isGBoundaryCellG(nghbrIdT, set) = true;
6077 a_isBndryCellG(nghbrIdT) = true;
6078 m_gBndryCells[set].push_back(nghbrIdT);
6079 }
6080 }
6081
6082
6083 if(noDomains() > 1 && cnt == m_noHaloLayers + 1) {
6084 stringstream errorMessage;
6085 errorMessage << "cnt is equal to " << cnt << " exiting ....";
6086 mTerm(1, AT_, errorMessage.str());
6087 }
6088 cnt++;
6089 }
6090 }
6091 }
6092 }
6093
6094 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
6095
6096 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
6097 for(MInt j = 0; j < noWindowCells(i); j++) {
6098 tmp_data(windowCellId(i, j)) = a_isBndryCellG(windowCellId(i, j));
6099 }
6100 }
6101
6102 exchangeDataLS(&tmp_data(0), 1);
6103
6104 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
6105 for(MInt j = 0; j < noHaloCells(i); j++) {
6106 const MInt haloCell = haloCellId(i, j);
6107 if(tmp_data(haloCell)) {
6108 a_isBndryCellG(haloCell) = tmp_data(haloCell);
6109 a_isGBoundaryCellG(haloCell, set) = tmp_data(haloCell);
6110 if(a_isBndryCellG(haloCell)) {
6111 m_gBndryCells[set].push_back(haloCell);
6112 }
6113 }
6114 }
6115 }
6116 if(noGBndryCellsBackup != a_noGBndryCells(set) || globalTimeStep == 0) {
6117 m_log << "Number of level set boundary cells changed: " << endl;
6118 m_log << a_noGBndryCells(set) << " G boundary cells created..." << endl;
6119 }
6120 break;
6121 }
6122
6123 // massive parallel
6124 case 5401000: {
6125 MInt noGBndryCellsBackup = a_noGBndryCells(set);
6126 // MFloat deltaX = m_flameRadiusOffset;
6127 MInt nghbrId, nghbrIdT;
6128 MInt cnt;
6129 MFloat radius;
6130 // reset g boundary information for level set domain boundary cells
6131 for(MInt id = 0; id < a_noBandCells(set); id++) {
6132 a_isBndryCellG(a_bandCellId(id, set)) = false;
6133 }
6134 std::vector<MInt>().swap(m_gBndryCells[set]);
6135 for(MInt id = 0; id < a_noBandCells(set); id++) {
6136 MInt cellId = a_bandCellId(id, set);
6137
6138 radius = sqrt(POW2(c_coordinate(cellId, 0)) + POW2(c_coordinate(cellId, 2)));
6139
6140
6141 if(a_isHalo(cellId)) continue;
6142 if(a_level(cellId) != a_maxGCellLevel()) continue;
6143 IF_CONSTEXPR(nDim == 3) {
6144 if(c_coordinate(cellId, 1) < (m_yOffsetFlameTube - 0.05)) continue;
6145 if(c_coordinate(cellId, 1) > (m_yOffsetFlameTube + 0.1)) continue;
6146 if(radius > (0.55)) continue;
6147 if(radius < 0.48) continue;
6148 }
6149 else {
6150 // if(c_coordinate(cellId, 1)<(m_yOffsetFlameTube-0.1))
6151 // continue;
6152 // if(c_coordinate(cellId, 1)>(m_yOffsetFlameTube+0.1))
6153 // continue;
6154 // if(ABS(c_coordinate(cellId, 0))> (m_radiusFlameTube+deltaX+0.1))
6155 // continue;
6156 }
6157 for(MInt dirId = 0; dirId < nDim * 2; dirId++) {
6158 if(a_hasNeighbor(cellId, dirId) == 0 && a_level(cellId) == a_maxGCellLevel()) {
6159 if(!a_isBndryCellG(cellId)) {
6160 a_isGBoundaryCellG(cellId, set) = true;
6161 a_isBndryCellG(cellId) = true;
6162 m_gBndryCells[set].push_back(cellId);
6163 }
6164
6165 // go in all other directions
6166 for(MInt dirIdS = 0; dirIdS < nDim * 2; dirIdS++) {
6167 if(dirId == dirIdS) continue;
6168 cnt = 0;
6169 nghbrId = cellId;
6170 while(cnt < 0) { // Stephan/Jerry
6171 // nghbrId= c_neighborId(nghbrId, dirIdS);
6172 // if(nghbrId==-1)
6173 // break;
6174
6175 MInt noNghbrIds = a_hasNeighbor(nghbrId, dirIdS);
6176 if(noNghbrIds == 0) // use noNghbrs because of determineStructured...() which
6177 // sets the neighbor to the current cell if there is no
6178 // neighbor
6179 break;
6180
6181 nghbrId = c_neighborId(nghbrId, dirIdS);
6182 if(nghbrId == -1) // just to be sure
6183 break;
6184 // don't add halo cells to the list, the info will be send to the other domains
6185 // and they update the window cells
6186 if(a_isHalo(nghbrId)) break;
6187 if(!a_inBandG(nghbrId, set)) break;
6188 if(a_level(nghbrId) != a_maxGCellLevel()) break;
6189 if(!a_isBndryCellG(nghbrId)) {
6190 a_isGBoundaryCellG(nghbrId, set) = true;
6191 a_isBndryCellG(nghbrId) = true;
6192 m_gBndryCells[set].push_back(nghbrId);
6193 }
6194 // go in all other directions
6195 for(MInt dirIdT = 0; dirIdT < nDim * 2; dirIdT++) {
6196 // if(dirIdT==dirId)
6197 // continue;
6198 // if(dirIdT==dirIdS)
6199 // continue;
6200
6201 MInt noNghbrIdsT = a_hasNeighbor(nghbrId, dirIdT);
6202 if(noNghbrIdsT == 0) // use noNghbrs because of determineStructured...() which
6203 // sets the neighbor to the current cell if there is no
6204 // neighbor
6205 continue;
6206
6207 nghbrIdT = c_neighborId(nghbrId, dirIdT);
6208 if(nghbrIdT == -1) // just to be sure
6209 continue;
6210 if(a_isHalo(nghbrIdT)) continue;
6211
6212 if(!a_inBandG(nghbrIdT, set)) continue;
6213 if(!a_isBndryCellG(nghbrIdT)) {
6214 a_isGBoundaryCellG(nghbrIdT, set) = true;
6215 a_isBndryCellG(nghbrIdT) = true;
6216 m_gBndryCells[set].push_back(nghbrIdT);
6217 }
6218 }
6219
6220
6221 if(noDomains() > 1 && cnt == m_noHaloLayers + 1) {
6222 stringstream errorMessage;
6223 errorMessage << "cnt is equal to " << cnt << " exiting ....";
6224 mTerm(1, AT_, errorMessage.str());
6225 }
6226 cnt++;
6227 }
6228 }
6229 }
6230 }
6231 }
6232 // exchange halo boundary cells for all sets with other domains
6233 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
6234
6235 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
6236 for(MInt j = 0; j < noWindowCells(i); j++) {
6237 tmp_data(windowCellId(i, j)) = a_isBndryCellG(windowCellId(i, j));
6238 }
6239 }
6240
6241 exchangeDataLS(&tmp_data(0), 1);
6242
6243 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
6244 for(MInt j = 0; j < noHaloCells(i); j++) {
6245 const MInt haloCell = haloCellId(i, j);
6246 if(tmp_data(haloCell)) {
6248 a_isBndryCellG(haloCell) = tmp_data(haloCell);
6249 a_isGBoundaryCellG(haloCell, set) = tmp_data(haloCell);
6250 if(a_isBndryCellG(haloCell)) {
6251 m_gBndryCells[set].push_back(haloCell);
6252 }
6253 }
6254 }
6255 }
6256 if(noGBndryCellsBackup != a_noGBndryCells(set) || globalTimeStep == 0) {
6257 m_log << "Number of level set boundary cells changed: " << endl;
6258 m_log << a_noGBndryCells(set) << " G boundary cells created...xy" << endl;
6259 }
6260 break;
6261 }
6262 default: {
6263 break; // most testcases do not need this
6264 }
6265 }
6266 }
6267}
6268
6269
6270// ----------------------------------------------------------------------------------------
6271
6272
6280template <MInt nDim>
6282 TRACE();
6283
6284 if(m_levelSetRans) return;
6285 if(m_virtualSurgery) return;
6286
6287 MInt startSet = 0;
6288 MInt endSet = m_noSets;
6289 if(m_buildCollectedLevelSetFunction && globalTimeStep > 0) startSet = 1;
6290 if(computingSet >= 0) {
6291 startSet = computingSet;
6292 endSet = computingSet + 1;
6293 ASSERT(m_computeSet[computingSet], "");
6294 m_changedSet[computingSet] = true;
6295 ASSERT(m_changedSet[computingSet], "");
6296 }
6297
6298
6299 //---
6300 // set level set function outside of the band
6301 for(MInt set = startSet; set < endSet; set++) {
6302 if(!m_computeSet[set]) continue;
6303 if(!m_changedSet[set] && m_levelSetMb && a_maxGCellLevel(set) == maxRefinementLevel()) continue;
6304
6305 for(MInt cell = 0; cell < a_noCells(); cell++) {
6306 if(a_inBandG(cell, set)) continue;
6307 if(a_level(cell) > a_maxGCellLevel(0)) continue;
6308
6309 if(c_noChildren(cell) > 0 && m_levelSetMb) { // on lower levels:
6310 if(a_levelSetFunctionG(cell, set) > m_outsideGValue) {
6311 a_levelSetFunctionG(cell, set) = m_outsideGValue;
6312 } else if(a_levelSetFunctionG(cell, set) < -m_outsideGValue) {
6313 a_levelSetFunctionG(cell, set) = -m_outsideGValue;
6314 }
6315 } else { // leaf-cells which are not in the band!
6316
6317 if(a_levelSetFunctionG(cell, set) > F0) {
6318 a_levelSetFunctionG(cell, set) = m_outsideGValue;
6319 } else {
6320 a_levelSetFunctionG(cell, set) = -m_outsideGValue;
6321 }
6322
6323 if(!m_semiLagrange) {
6324 a_correctedBurningVelocity(cell, set) = F0;
6325 for(MInt i = 0; i < nDim; i++) {
6326 a_extensionVelocityG(cell, i, set) = F0;
6327 a_normalVectorG(cell, i, set) = F0;
6328 }
6329 a_curvatureG(cell, set) = F0;
6330 }
6331 }
6332 }
6333 }
6334}
6335
6336template <MInt nDim>
6338 TRACE();
6339
6340 // set level set function outside of the band
6341 for(MInt set = 0; set < m_noSets; set++) {
6342 for(MInt cell = 0; cell < noInternalCells(); cell++) {
6343 if(a_oldLevelSetFunctionG(cell, set) > m_outsideGValue) {
6344 a_oldLevelSetFunctionG(cell, set) = m_outsideGValue;
6345 } else if(a_oldLevelSetFunctionG(cell, set) < -m_outsideGValue) {
6346 a_oldLevelSetFunctionG(cell, set) = -m_outsideGValue;
6347 }
6348 }
6349 }
6350}
6351// ----------------------------------------------------------------------------------------
6352
6353
6363template <MInt nDim>
6365 TRACE();
6366
6367 ASSERT(m_lsCollectorMode == 0 || m_lsCollectorMode == 2 || m_lsCollectorMode == 3, "");
6368
6369
6370 IF_CONSTEXPR(nDim == 2) {
6371 MInt cellId, nghbrL, nghbrL2, nghbrR, nghbrR2;
6372 // MBool boundary= false;
6373 MBool oneSidedR = false;
6374 MBool oneSidedL = false;
6375 MFloat FgCellDistanceL2R2 = m_FgCellDistance * F1B4, FgCellDistanceLR = m_FgCellDistance * F1B2;
6376 MFloat levelSetNegative = F0, levelSetPlus = F0;
6377 MFloat filterCoord = m_filterFlameTubeEdgesDistance + 0.0234;
6378 MFloat cR = -9999.9, cL = -9999.9; //,cR2=-9999.9,cL2=-9999.9;
6379 MBool filter = false;
6380
6381 MInt startSet = 0;
6382 MInt endSet = m_noSets;
6383 if(computingSet >= 0) {
6384 startSet = computingSet;
6385 endSet = computingSet + 1;
6386 }
6387 //---
6388
6389#ifdef standardStencil
6390
6391 for(MInt set = startSet; set < endSet; set++) {
6392 if(!m_computeSet[set]) continue;
6393 for(MInt id = 0; id < a_noBandCells(set); id++) {
6394 cellId = a_bandCellId(id, set);
6395
6396 if(a_isHalo(cellId)) continue;
6397
6398 // compute the second derivatives
6399 for(MInt i = 0; i < nDim; i++) {
6400 grad2G[i] =
6401 (a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i + 1], set)
6402 + a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i], set) - F2 * a_levelSetFunctionG(cellId, set))
6403 * POW2(Fdx);
6404 }
6405
6406 // compute the mixed derivatives
6407
6408 // dummy:
6409 mixedDerivative = 0.01;
6410 mTerm(1, AT_, "ERROR: check code.. this part is assumed to not be used ");
6411
6412 // compute the denominator
6413 denominator = F0;
6414 for(MInt i = 0; i < nDim; i++) {
6415 denominator += POW2(a_levelSetFunctionSlope(cellId, i, set));
6416 }
6417 denominator = F1 / POW2(denominator);
6418 denominator = sqrt(denominator * denominator * denominator);
6419
6420 a_curvatureG(cellId, set) = -denominator
6421 * (grad2G[0] * POW2(a_levelSetFunctionSlope(cellId, 1, set))
6422 + grad2G[1] * POW2(a_levelSetFunctionSlope(cellId, 0, set))
6423 - F2 * a_levelSetFunctionSlope(cellId, 0, set)
6424 * a_levelSetFunctionSlope(cellId, 1, set) * mixedDerivative);
6425 }
6426 }
6427#else
6428
6429 if(m_fourthOrderNormalCurvatureComputation) {
6430 for(MInt set = startSet; set < endSet; set++) {
6431 if(!m_computeSet[set]) continue;
6432 for(MInt id = 0; id < a_noBandCells(set); id++) {
6433 cellId = a_bandCellId(id, set);
6434
6435 // reset curvature
6436 a_curvatureG(cellId, set) = F0;
6437 if(a_isHalo(cellId)) continue;
6438
6439 for(MInt i = 0; i < nDim; i++) {
6440 oneSidedR = false;
6441 oneSidedL = false;
6442 filter = false;
6443
6444 FgCellDistanceL2R2 = m_FgCellDistance * F1B4;
6445 FgCellDistanceLR = m_FgCellDistance * F1B2;
6446
6447 nghbrL = c_neighborId(cellId, 2 * i);
6448 nghbrL2 = c_neighborId(nghbrL, 2 * i);
6449
6450 nghbrR = c_neighborId(cellId, 2 * i + 1);
6451 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
6452
6453 // reduce to second order
6454 if(!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR2, set)) {
6455 nghbrR2 = nghbrR;
6456 nghbrL2 = nghbrL;
6457 FgCellDistanceL2R2 = FgCellDistanceLR;
6458 }
6459
6460 // reduce to second order on boundaries (like for the Landau simulations)
6461 if(a_hasNeighbor(nghbrL, 2 * i) == 0 || a_hasNeighbor(nghbrR, 2 * i + 1) == 0) {
6462 // reduce to second order
6463 nghbrR2 = nghbrR;
6464 nghbrL2 = nghbrL;
6465 FgCellDistanceL2R2 = FgCellDistanceLR;
6466 }
6467
6468 // take onesided differences directly on the boundary
6469 // no neighbors in positive direction
6470 if(a_hasNeighbor(cellId, 2 * i + 1) == 0 || a_hasNeighbor(nghbrR, 2 * i + 1) == 0
6471 || a_hasNeighbor(nghbrR2, 2 * i + 1) == 0) {
6472 oneSidedL = true;
6473
6474 a_curvatureG(cellId, set) = F0;
6475 /*
6476 - m_FgCellDistance *
6477
6478 ( a * a_normalVectorG( cellId , i, set) ) +
6479 b * a_normalVectorG( nghbrL , i, set ) +
6480 c * a_normalVectorG( nghbrL2 , i, set ) );
6481 */
6482 }
6483
6484 // no neighbors in negative direction
6485 if(a_hasNeighbor(cellId, 2 * i) == 0 || a_hasNeighbor(nghbrL, 2 * i) == 0
6486 || a_hasNeighbor(nghbrL2, 2 * i) == 0) {
6487 oneSidedR = true;
6488
6489 a_curvatureG(cellId, set) = F0;
6490 /*
6491 m_FgCellDistance *
6492
6493 ( a * a_normalVectorG( cellId , i, set ) +
6494 b * a_normalVectorG( nghbrR , i, set ) +
6495 c * a_normalVectorG( nghbrR2 , i, set ) );
6496 */
6497 }
6498
6499 // filtering
6500 if(!oneSidedR && !oneSidedL && m_filterFlameTubeEdges) {
6501 if(c_coordinate(cellId, 1) < filterCoord) {
6502 // compute second order curvature values at surfaces (staggered points)
6503
6504 cR = (a_normalVectorG(nghbrR, i, set) - a_normalVectorG(cellId, i, set)) * m_FgCellDistance;
6505
6506 cL = (a_normalVectorG(cellId, i, set) - a_normalVectorG(nghbrL, i, set)) * m_FgCellDistance;
6507
6508 // compute via second order interpolation the curvature back to the cell centers
6509 a_curvatureG(cellId, 0) += (F1B2 * (cR + cL));
6510 filter = true;
6511 }
6512 }
6513
6514 if(!filter) {
6515 if(!oneSidedR && !oneSidedL) {
6516 a_curvatureG(cellId, set) +=
6517
6518 F4B3 * FgCellDistanceLR *
6519
6520 (a_normalVectorG(nghbrR, i, set) - a_normalVectorG(nghbrL, i, set))
6521
6522 - F1B3 * FgCellDistanceL2R2 *
6523
6524 (a_normalVectorG(nghbrR2, i, set) - a_normalVectorG(nghbrL2, i, set));
6525 }
6526 }
6527 }
6528 if(m_curvatureDamp) {
6529 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6530 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6531
6532 a_curvatureG(cellId, set) = F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0))
6533 * a_curvatureG(cellId, set);
6534 }
6535 }
6536 }
6537 } else {
6538 for(MInt set = startSet; set < endSet; set++) {
6539 if(!m_computeSet[set]) continue;
6540 for(MInt id = 0; id < a_noBandCells(set); id++) {
6541 cellId = a_bandCellId(id, set);
6542
6543 a_curvatureG(cellId, set) = F0;
6544 if(a_isHalo(cellId)) continue;
6545
6546 if(!a_isGBoundaryCellG(cellId, set)) {
6547 // second order old code
6548 a_curvatureG(cellId, set) = F1B2 * m_FgCellDistance
6549 * (a_normalVectorG(a_bandNghbrIdsG(cellId, 1, set), 0, set)
6550 - a_normalVectorG(a_bandNghbrIdsG(cellId, 0, set), 0, set)
6551 + a_normalVectorG(a_bandNghbrIdsG(cellId, 3, set), 1, set)
6552 - a_normalVectorG(a_bandNghbrIdsG(cellId, 2, set), 1, set));
6553
6554 if(m_curvatureDamp) {
6555 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6556 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6557
6558 a_curvatureG(cellId, set) = F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0))
6559 * a_curvatureG(cellId, set);
6560 }
6561 }
6562 }
6563#endif
6564 }
6565}
6566
6567// exchange curavture on halo cells, cause they are needed for the Markstein length computation!
6568exchangeDataLS(&a_curvatureG(0, 0), m_maxNoSets);
6569 }
6570 else {
6571 MInt cellId;
6572 MInt startSet = 0;
6573 MInt endSet = m_noSets;
6574 if(computingSet >= 0) {
6575 startSet = computingSet;
6576 endSet = computingSet + 1;
6577 }
6578 //---
6579 for(MInt set = startSet; set < endSet; set++) {
6580 if(!m_computeSet[set]) continue;
6581 for(MInt id = 0; id < a_noBandCells(set); id++) {
6582 cellId = a_bandCellId(id, set);
6583 if(a_isHalo(cellId)) continue;
6584
6585 if(!a_isGBoundaryCellG(cellId, set)) {
6586#ifdef standardStencil
6587 // compute the second derivatives
6588 for(MInt i = 0; i < nDim; i++) {
6589 grad2G[i] =
6590 (a_levelSetFunctionG(c_neighborId(cellId, 2 * i + 1), set)
6591 + a_levelSetFunctionG(c_neighborId(cellId, 2 * i), set) - F2 * a_levelSetFunctionG(cellId, set))
6592 * POW2(m_FgCellDistance);
6593 }
6594
6595 // order: xy,xz,yz
6596 mixedDerivative[0] = F1B4 * POW2(m_FgCellDistance)
6597 * (a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 0), 2 + 0), set)
6598 + a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 1), 2 + 1), set)
6599 - a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 0), 2 + 1), set)
6600 - a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 1), 2 + 0), set));
6601 mixedDerivative[1] = F1B4 * POW2(m_FgCellDistance)
6602 * (a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 0), 4 + 0), set)
6603 + a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 1), 4 + 1), set)
6604 - a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 0), 4 + 1), set)
6605 - a_levelSetFunctionG(c_neighborId(c_neighborId(cellId, 1), 4 + 0), set));
6606 mixedDerivative[2] =
6607 F1B4 * POW2(m_FgCellDistance)
6608 * (a_levelSetFunctionG(c_neighborId(c_neighborId(c_neighborId(cellId, 2), 2 + 0), 4 + 0), set)
6609 + a_levelSetFunctionG(c_neighborId(c_neighborId(c_neighborId(cellId, 2), 2 + 1), 4 + 1), set)
6610 - a_levelSetFunctionG(c_neighborId(c_neighborId(c_neighborId(cellId, 2), 2 + 0), 4 + 1), set)
6611 - a_levelSetFunctionG(c_neighborId(c_neighborId(c_neighborId(cellId, 2), 2 + 1), 4 + 0), set));
6612
6613 // compute the denominator
6614 denominator = F0;
6615 for(MInt i = 0; i < nDim; i++) {
6616 denominator += POW2(a_levelSetFunctionSlope(cellId, i, set));
6617 }
6618 denominator = F1 / POW2(denominator);
6619 denominator = sqrt(denominator * denominator * denominator);
6620
6621 a_curvatureG(cellId, set) =
6622 -denominator
6623 * (POW2(grad2G[0])
6624 * (POW2(a_levelSetFunctionSlope(cellId, 1, set)) + POW2(a_levelSetFunctionSlope(cellId, 2, set)))
6625 + POW2(grad2G[1])
6626 * (POW2(a_levelSetFunctionSlope(cellId, 0, set)) + POW2(a_levelSetFunctionSlope(cellId, 2, set)))
6627 + POW2(grad2G[2])
6628 * (POW2(a_levelSetFunctionSlope(cellId, 0, set)) + POW2(a_levelSetFunctionSlope(cellId, 1, set)))
6629 - F2
6630 * (mixedDerivative[0] * a_levelSetFunctionSlope(cellId, 0, set)
6631 * a_levelSetFunctionSlope(cellId, 1, set)
6632 + mixedDerivative[1] * a_levelSetFunctionSlope(cellId, 0, set)
6633 * a_levelSetFunctionSlope(cellId, 2, set)
6634 + mixedDerivative[2] * a_levelSetFunctionSlope(cellId, 1, set)
6635 * a_levelSetFunctionSlope(cellId, 2, set)));
6636
6637#else
6638
6639 a_curvatureG(cellId, set) = F1B2 * m_FgCellDistance
6640 * (a_normalVectorG(a_bandNghbrIdsG(cellId, 1, set), 0, set)
6641 - a_normalVectorG(a_bandNghbrIdsG(cellId, 0, set), 0, set)
6642 + a_normalVectorG(a_bandNghbrIdsG(cellId, 3, set), 1, set)
6643 - a_normalVectorG(a_bandNghbrIdsG(cellId, 2, set), 1, set)
6644 + a_normalVectorG(a_bandNghbrIdsG(cellId, 5, set), 2, set)
6645 - a_normalVectorG(a_bandNghbrIdsG(cellId, 4, set), 2, set));
6646
6647 if(m_curvatureDamp) {
6648 MFloat levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6649 MFloat levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6650
6651 a_curvatureG(cellId, set) *= F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0));
6652 }
6653#endif
6654 }
6655 }
6656 }
6657
6658
6659 // exchange curvature
6660 exchangeDataLS(&a_curvatureG(0, 0), m_maxNoSets);
6661 }
6662}
6663
6676template <MInt nDim>
6678 TRACE();
6679 IF_CONSTEXPR(nDim == 2) {
6680 MInt cellId, nghbrL, nghbrL2, nghbrR, nghbrR2;
6681 // MBool boundary= false;
6682 MBool oneSidedR = false;
6683 MBool oneSidedL = false;
6684 MFloat FgCellDistanceL2R2 = m_FgCellDistance * F1B4, FgCellDistanceLR = m_FgCellDistance * F1B2;
6685 MFloat levelSetNegative = F0, levelSetPlus = F0;
6686 //---
6687
6688
6689#ifdef standardStencil
6690
6691 for(MInt set = 0; set < m_noSets; set++) {
6692 if(!m_computeSet[set]) continue;
6693 for(MInt id = 0; id < a_noBandCells(set); id++) {
6694 cellId = a_bandCellId(id, set);
6695 if(a_isHalo(cellId)) continue;
6696
6697 // compute the second derivatives
6698 for(MInt i = 0; i < nDim; i++) {
6699 grad2G[i] =
6700 (a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i + 1], set)
6701 + a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i], set) - F2 * a_levelSetFunctionG(cellId, set))
6702 * POW2(Fdx);
6703 }
6704
6705 // compute the mixed derivatives
6706
6707 // dummy:
6708 mixedDerivative = 0.01;
6709 mTerm(1, AT_, "ERROR: check code.. this part is assumed to not be used ");
6710
6711 // compute the denominator
6712 denominator = F0;
6713 for(MInt i = 0; i < nDim; i++) {
6714 denominator += POW2(a_levelSetFunctionSlope(cellId, i, set));
6715 }
6716 denominator = F1 / POW2(denominator);
6717 denominator = sqrt(denominator * denominator * denominator);
6718
6719 a_curvatureG(cellId, set) = -denominator
6720 * (grad2G[0] * POW2(a_levelSetFunctionSlope(cellId, 1, set))
6721 + grad2G[1] * POW2(a_levelSetFunctionSlope(cellId, 0, set))
6722 - F2 * a_levelSetFunctionSlope(cellId, 0, set)
6723 * a_levelSetFunctionSlope(cellId, 1, set) * mixedDerivative);
6724 }
6725 }
6726
6727#else
6728
6729 if(m_fourthOrderNormalCurvatureComputation) {
6730 for(MInt set = 0; set < m_noSets; set++) {
6731 if(!m_computeSet[set]) continue;
6732 for(MInt id = 0; id < a_noBandCells(set); id++) {
6733 cellId = a_bandCellId(id, set);
6734
6735 // reset curvature
6736 a_curvatureG(cellId, set) = F0;
6737 if(a_isHalo(cellId)) continue;
6738
6739 for(MInt i = 0; i < nDim; i++) {
6740 oneSidedR = false;
6741 oneSidedL = false;
6742
6743 FgCellDistanceL2R2 = m_FgCellDistance * F1B4;
6744 FgCellDistanceLR = m_FgCellDistance * F1B2;
6745
6746 nghbrL = c_neighborId(cellId, 2 * i);
6747 nghbrL2 = c_neighborId(nghbrL, 2 * i);
6748 nghbrR = c_neighborId(cellId, 2 * i + 1);
6749 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
6750
6751 if(a_hasNeighbor(nghbrL2, 2 * i) != 0 && a_hasNeighbor(nghbrR2, 2 * i + 1) != 0) {
6752 // reduce to second order on band boundaries
6753 if((!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR2, set))) {
6754 nghbrR2 = nghbrR;
6755 nghbrL2 = nghbrL;
6756 FgCellDistanceL2R2 = m_FgCellDistance * F1B2;
6757 }
6758 }
6759
6760 if(!oneSidedR && !oneSidedL) {
6761 a_curvatureG(cellId, set) +=
6762
6763 F4B3 * FgCellDistanceLR *
6764
6765 (a_normalVectorG(nghbrR, i, set) - a_normalVectorG(nghbrL, i, set))
6766
6767 - F1B3 * FgCellDistanceL2R2 *
6768
6769 (a_normalVectorG(nghbrR2, i, set) - a_normalVectorG(nghbrL2, i, set));
6770 }
6771 }
6772 if(m_curvatureDamp) {
6773 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6774 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6775
6776 a_curvatureG(cellId, set) *= F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0));
6777 }
6778 }
6779 }
6780 } else {
6781 // second order code
6782 for(MInt set = 0; set < m_noSets; set++) {
6783 if(!m_computeSet[set]) continue;
6784 for(MInt id = 0; id < a_noBandCells(set); id++) {
6785 cellId = a_bandCellId(id, set);
6786 a_curvatureG(cellId, set) = F0;
6787 if(a_isHalo(cellId)) continue;
6788
6789 if(!a_isGBoundaryCellG(cellId, set)) {
6790 a_curvatureG(cellId, set) = F1B2 * m_FgCellDistance
6791 * (a_normalVectorG(a_bandNghbrIdsG(cellId, 1, set), 0, set)
6792 - a_normalVectorG(a_bandNghbrIdsG(cellId, 0, set), 0, set)
6793 + a_normalVectorG(a_bandNghbrIdsG(cellId, 3, set), 1, set)
6794 - a_normalVectorG(a_bandNghbrIdsG(cellId, 2, set), 1, set));
6795
6796 if(m_curvatureDamp) {
6797 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6798 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6799
6800 a_curvatureG(cellId, set) *=
6801 F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0));
6802 }
6803 }
6804 }
6805 }
6806 }
6807#endif
6808 }
6809 else {
6810 mTerm(1, AT_, "ERROR: check 3D implementation, not done ");
6811 MInt cellId, nghbrL, nghbrL2, nghbrR, nghbrR2;
6812 MBool oneSidedR = false;
6813 MBool oneSidedL = false;
6814 MFloat FgCellDistanceL2R2 = m_FgCellDistance * F1B4, FgCellDistanceLR = m_FgCellDistance * F1B2;
6815 MFloat levelSetNegative = F0, levelSetPlus = F0;
6816 //---
6817#ifdef standardStencil
6818 for(MInt set = 0; set < m_noSets; set++) {
6819 if(!m_computeSet[set]) continue;
6820 for(MInt id = 0; id < a_noBandCells(set); id++) {
6821 cellId = a_bandCellId(id, set);
6822 if(a_isHalo(cellId)) continue;
6823 // compute the second derivatives
6824 for(MInt i = 0; i < nDim; i++) {
6825 grad2G[i] =
6826 (a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i + 1], set)
6827 + a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i], set) - F2 * a_levelSetFunctionG(cellId, set))
6828 * POW2(Fdx);
6829 }
6830 // compute the mixed derivatives
6831 for(MInt i = 0; i < nDim; i++) {
6832 grad2G[i] =
6833 (a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i + 1], set)
6834 + a_levelSetFunctionG(m_cells[cellId].m_cells[2 * i], set) - F2 * a_levelSetFunctionG(cellId, set))
6835 * POW2(Fdx);
6836 }
6837 // compute the mixed derivatives
6838 // dummy:
6839 mixedDerivative = 0.01;
6840 mTerm(1, AT_, "ERROR: check code.. this part is assumed to not be used ");
6841
6842 // compute the denominator
6843 denominator = F0;
6844 for(MInt i = 0; i < nDim; i++) {
6845 denominator += POW2(a_levelSetFunctionSlope(cellId, i, set));
6846 }
6847 denominator = F1 / POW2(denominator);
6848 denominator = sqrt(denominator * denominator * denominator);
6849
6850 a_curvatureG(cellId, set) = -denominator
6851 * (grad2G[0] * POW2(a_levelSetFunctionSlope(cellId, 1, set))
6852 + grad2G[1] * POW2(a_levelSetFunctionSlope(cellId, 0, set))
6853 - F2 * a_levelSetFunctionSlope(cellId, 0, set)
6854 * a_levelSetFunctionSlope(cellId, 1, set) * mixedDerivative);
6855 }
6856 }
6857#else
6858
6859 if(m_fourthOrderNormalCurvatureComputation) {
6860 for(MInt set = 0; set < m_noSets; set++) {
6861 if(!m_computeSet[set]) continue;
6862 for(MInt id = 0; id < a_noBandCells(set); id++) {
6863 cellId = a_bandCellId(id, set);
6864 // reset curvature
6865 a_curvatureG(cellId, set) = F0;
6866 if(a_isHalo(cellId)) continue;
6867
6868 for(MInt i = 0; i < nDim; i++) {
6869 oneSidedR = false;
6870 oneSidedL = false;
6871
6872 FgCellDistanceL2R2 = m_FgCellDistance * F1B4;
6873 FgCellDistanceLR = m_FgCellDistance * F1B2;
6874
6875 nghbrL = c_neighborId(cellId, 2 * i);
6876 nghbrL2 = c_neighborId(nghbrL, 2 * i);
6877 nghbrR = c_neighborId(cellId, 2 * i + 1);
6878 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
6879
6880 if(a_hasNeighbor(nghbrL2, 2 * i) != 0 && a_hasNeighbor(nghbrR2, 2 * i + 1) != 0) {
6881 // reduce to second order on band boundaries
6882 if((!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR2, set))) {
6883 nghbrR2 = nghbrR;
6884 nghbrL2 = nghbrL;
6885 FgCellDistanceL2R2 = m_FgCellDistance * F1B2;
6886 }
6887 }
6888
6889 if(!oneSidedR && !oneSidedL) {
6890 a_curvatureG(cellId, set) +=
6891
6892 F4B3 * FgCellDistanceLR *
6893
6894 (a_normalVectorG(nghbrR, i, set) - a_normalVectorG(nghbrL, i, set))
6895
6896 - F1B3 * FgCellDistanceL2R2 *
6897
6898 (a_normalVectorG(nghbrR2, i, set) - a_normalVectorG(nghbrL2, i, set));
6899 }
6900 }
6901 if(m_curvatureDamp) {
6902 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6903 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6904
6905 a_curvatureG(cellId, set) = F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0))
6906 * a_curvatureG(cellId, set);
6907 }
6908 }
6909 }
6910 } else {
6911 for(MInt set = 0; set < m_noSets; set++) {
6912 if(!m_computeSet[set]) continue;
6913 for(MInt id = 0; id < a_noBandCells(set); id++) {
6914 cellId = a_bandCellId(id, set);
6915 if(a_isHalo(cellId)) continue;
6916
6917 if(!a_isGBoundaryCellG(cellId, set)) {
6918 // second order old code
6919 a_curvatureG(cellId, set) = F1B2 * m_FgCellDistance
6920 * (a_normalVectorG(a_bandNghbrIdsG(cellId, 1, set), 0, set)
6921 - a_normalVectorG(a_bandNghbrIdsG(cellId, 0, set), 0, set)
6922 + a_normalVectorG(a_bandNghbrIdsG(cellId, 3, set), 1, set)
6923 - a_normalVectorG(a_bandNghbrIdsG(cellId, 2, set), 1, set));
6924
6925 if(m_curvatureDamp) {
6926 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
6927 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
6928
6929 a_curvatureG(cellId, set) = F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0))
6930 * a_curvatureG(cellId, set);
6931 }
6932 }
6933 }
6934 }
6935 }
6936#endif
6937 }
6938 //#endif
6939}
6940
6941//#endif
6942
6943
6944//----------------------------------------------------------------------------
6945
6946
6947template <MInt nDim>
6949 TRACE();
6950
6951 ASSERT(m_lsCollectorMode == 0 || m_lsCollectorMode == 3, "");
6952
6953 if(m_gRKStep == 0) {
6954 if(globalTimeStep % 100 == 0) {
6955 if(domainId() == 0) {
6956 cerr << "time step #" << globalTimeStep << " - time " << m_time << endl;
6957 }
6958 }
6959
6960 switch(m_levelSetTestCase) {
6961 case 50431:
6962 case 504312: {
6963 for(MInt set = m_startSet; set < m_noSets; set++) {
6964 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6965 a_extensionVelocityG(cellId, 0, set) = PI / 31.4 * (-c_coordinate(cellId, 1));
6966 a_extensionVelocityG(cellId, 1, set) = PI / 31.4 * (c_coordinate(cellId, 0));
6967 if(m_levelSetTestCase == 504312) {
6968 a_extensionVelocityG(cellId, 0, set) *= -1;
6969 a_extensionVelocityG(cellId, 1, set) *= -1;
6970 }
6971 a_flameSpeedG(cellId, set) = F0;
6972 }
6973 }
6974 break;
6975 }
6976
6977 case 203: {
6978 // Zalesak's problem
6979 for(MInt set = m_startSet; set < m_noSets; set++) {
6980 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
6981 // flow velocities are not set for this levelSet-testcase!
6982 // fvSolverD().a_variable(cellId, 0) = fvSolverD().m_rhoInfinity * PI / 31.4 * (-c_coordinate(cellId, 1));
6983 // fvSolverD().a_variable(cellId, 1) = fvSolverD().m_rhoInfinity * PI / 31.4 * (c_coordinate(cellId, 0));
6984 a_extensionVelocityG(cellId, 0, set) = PI / 31.4 * (-c_coordinate(cellId, 1));
6985 a_extensionVelocityG(cellId, 1, set) = PI / 31.4 * (c_coordinate(cellId, 0));
6986 a_flameSpeedG(cellId, set) = F0;
6987 }
6988 }
6989 break;
6990 }
6991 case 3012: {
6992 /*************** Translation *************/
6993 MFloat Vtrans[3] = {F0, F0, F0};
6994 MFloatScratchSpace VtransBodies(m_noEmbeddedBodies, 3, AT_, "VtransBodies");
6995 for(MInt body = 0; body < m_noEmbeddedBodies; body++) {
6996 computeBodyPropertiesForced(2, Vtrans, body, time());
6997 for(MInt i = 0; i < 3; i++) {
6998 VtransBodies(body, i) = Vtrans[i];
6999 }
7000 }
7001 /***************************************************************************************************************/
7002
7003 /************** Define Velocity over the G0 cells **************/
7004 for(MInt set = m_startSet; set < m_noSets; set++) {
7005 if(!m_computeSet[set]) {
7006 continue;
7007 }
7008 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7009 MInt cellId = a_G0CellId(id, set);
7010 MInt body = a_bodyIdG(cellId, set);
7011 if(body > -1) {
7012 a_extensionVelocityG(cellId, 0, set) = VtransBodies(body, 0);
7013 a_extensionVelocityG(cellId, 1, set) = VtransBodies(body, 1);
7014 IF_CONSTEXPR(nDim == 3) { a_extensionVelocityG(cellId, 2, set) = VtransBodies(body, 2); }
7015 } else {
7016 a_extensionVelocityG(cellId, 0, set) = F0;
7017 a_extensionVelocityG(cellId, 1, set) = F0;
7018 IF_CONSTEXPR(nDim == 3) { a_extensionVelocityG(cellId, 2, set) = F0; }
7019 }
7020 }
7021 }
7022
7023
7024 /****************** Updating control points: need new time step **************/
7025 MFloat dx[3] = {F0, F0, F0};
7026 MFloat x1[3] = {F0, F0, F0};
7027 MFloat x0[3] = {F0, F0, F0};
7028 if(m_GCtrlPntMethod == 2 && m_initialCondition != 31) {
7029 // Movable STL
7030 MInt bcId = 0;
7031 for(MInt body = 0; body < m_noEmbeddedBodies; body++) {
7032 bcId = m_bodyBndryCndIds[body];
7033 computeBodyPropertiesForced(1, x1, body, time() + timeStep());
7034 computeBodyPropertiesForced(1, x0, body, time());
7035 for(MInt i = 0; i < 3; i++) {
7036 dx[i] = (x1[i] - x0[i]);
7037 }
7038 m_gCtrlPnt.CtrlPnt2_shiftSTL(bcId, dx);
7039 }
7040 }
7041 /********************* Update Level Set time ***************************/
7042 m_time += timeStep();
7043 break;
7044 }
7045 default:
7046 break;
7047 }
7048 }
7049}
7050
7051
7052// ----------------------------------------------------------------------------------------
7053
7064template <MInt nDim>
7066 TRACE();
7067
7068 ASSERT(m_lsCollectorMode == 0 || m_lsCollectorMode == 2 || m_lsCollectorMode == 3, m_lsCollectorMode);
7069
7070 MFloat FgradG;
7071 MFloat epsilon = m_gCellDistance * 0.00000001;
7072 // const MFloat Fdx = F1B2 * m_FgCellDistance;
7073 MInt cellId, nghbrL, nghbrL2, nghbrR, nghbrR2;
7074 // MBool boundary= false;
7075 MBool oneSidedR = false;
7076 MBool oneSidedL = false;
7077 MFloat FgCellDistanceL2R2 = m_FgCellDistance * F1B4, FgCellDistanceLR = m_FgCellDistance * F1B2;
7078 MFloat filterCoord = m_filterFlameTubeEdgesDistance + 0.0234;
7079 MFloat a = -F3B2, b = F2, c = -F1B2;
7080 MBool filter = false;
7081 MFloat levelSlopeR = -9999.9, levelSlopeL = -9999.9;
7082
7083 MInt startSet = 0;
7084 MInt endSet = m_noSets;
7085 if(computingSet >= 0) {
7086 startSet = computingSet;
7087 endSet = computingSet + 1;
7088 }
7089
7090 exchangeLevelSet();
7091
7092 //---
7093 if(m_fourthOrderNormalCurvatureComputation) {
7094 for(MInt set = startSet; set < endSet; set++) {
7095 if(!m_computeSet[set]) continue;
7096 for(MInt id = 0; id < a_noBandCells(set); id++) {
7097 cellId = a_bandCellId(id, set);
7098
7099 for(MInt i = 0; i < nDim; i++) {
7100 oneSidedR = false;
7101 oneSidedL = false;
7102 filter = false;
7103
7104 FgCellDistanceL2R2 = m_FgCellDistance * F1B4;
7105 FgCellDistanceLR = m_FgCellDistance * F1B2;
7106
7107 nghbrL = c_neighborId(cellId, 2 * i);
7108 nghbrL2 = c_neighborId(nghbrL, 2 * i);
7109 nghbrR = c_neighborId(cellId, 2 * i + 1);
7110 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
7111
7112 if((!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR2, set)
7113 || (a_isGBoundaryCellG(nghbrL2, set) || a_isGBoundaryCellG(nghbrR2, set)))) {
7114 // reduce to second order
7115 nghbrR2 = nghbrR;
7116 nghbrL2 = nghbrL;
7117 FgCellDistanceL2R2 = FgCellDistanceLR;
7118 }
7119
7120 // reduce to second order on boundaries (like for the Landau simulations)
7121 if(a_hasNeighbor(nghbrL, 2 * i) == 0 || a_hasNeighbor(nghbrR, 2 * i + 1) == 0) {
7122 // reduce to second order
7123 nghbrR2 = nghbrR;
7124 nghbrL2 = nghbrL;
7125 FgCellDistanceL2R2 = FgCellDistanceLR;
7126 }
7127 /*
7128 if(a_hasNeighbor( cellId , 2*i )==0 ||
7129 a_hasNeighbor( cellId , 2*i+1 )==0
7130 ) {
7131 // reduce to second order
7132 nghbrR2 = nghbrR;
7133 nghbrL2 = nghbrL;
7134 FgCellDistanceL2R2 = FgCellDistanceLR;
7135 }
7136 */
7137
7138 // take onesided differences directly on the boundary
7139 // no neighbors in positive direction
7140 if(a_hasNeighbor(cellId, 2 * i + 1) == 0) {
7141 oneSidedL = true;
7142
7143 a_levelSetFunctionSlope(cellId, i, set) =
7144
7145 -m_FgCellDistance *
7146
7147 (a * a_levelSetFunctionG(cellId, set) + b * a_levelSetFunctionG(nghbrL, set)
7148 + c * a_levelSetFunctionG(nghbrL2, set));
7149 }
7150
7151 // no neighbors in negative direction
7152 if(a_hasNeighbor(cellId, 2 * i) == 0) {
7153 oneSidedR = true;
7154
7155 a_levelSetFunctionSlope(cellId, i, set) =
7156
7157 m_FgCellDistance *
7158
7159 (a * a_levelSetFunctionG(cellId, set) + b * a_levelSetFunctionG(nghbrR, set)
7160 + c * a_levelSetFunctionG(nghbrR2, set));
7161 }
7162
7163 // filtering
7164 if(!oneSidedR && !oneSidedL && m_filterFlameTubeEdges) {
7165 if(c_coordinate(cellId, 1) < filterCoord) {
7166 // compute second order curvature values at surfaces (staggered points)
7167
7168 levelSlopeR = (a_levelSetFunctionG(nghbrR, set) - a_levelSetFunctionG(cellId, set)) * m_FgCellDistance;
7169
7170 levelSlopeL = (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(nghbrL, set)) * m_FgCellDistance;
7171
7172 // compute via second order interpolation the curvature back to the cell centers
7173 a_levelSetFunctionSlope(cellId, i, set) = (F1B2 * (levelSlopeR + levelSlopeL));
7174 filter = true;
7175 }
7176 }
7177
7178 if(!filter) {
7179 if(!oneSidedR && !oneSidedL) {
7180 a_levelSetFunctionSlope(cellId, i, set) =
7181
7182 F4B3 * FgCellDistanceLR *
7183
7184 (a_levelSetFunctionG(nghbrR, set) - a_levelSetFunctionG(nghbrL, set))
7185
7186 - F1B3 * FgCellDistanceL2R2 *
7187
7188 (a_levelSetFunctionG(nghbrR2, set) - a_levelSetFunctionG(nghbrL2, set));
7189 }
7190 }
7191 FgradG = POW2(a_levelSetFunctionSlope(cellId, 0, set));
7192 for(MInt k = 1; k < nDim; k++)
7193 FgradG += POW2(a_levelSetFunctionSlope(cellId, k, set));
7194
7195 FgradG = F1 / mMax(epsilon, sqrt(FgradG));
7196
7197 for(MInt k = 0; k < nDim; k++)
7198 a_normalVectorG(cellId, k, set) = -FgradG * a_levelSetFunctionSlope(cellId, k, set);
7199 }
7200 }
7201 }
7202 } else {
7203 for(MInt set = startSet; set < endSet; set++) {
7204 if(!m_computeSet[set]) continue;
7205
7206 for(MInt id = 0; id < a_noBandCells(set); id++) {
7207 cellId = a_bandCellId(id, set);
7208 if(a_isHalo(cellId)) continue;
7209 // second order code
7210 /*
7211 for( MInt i=0; i<nDim; i++ )
7212 a_levelSetFunctionSlope( cellId ,i, set) =
7213 ( a_levelSetFunctionG( c_neighborId( cellId , 2*i+1 ) , set) -
7214 a_levelSetFunctionG( c_neighborId( cellId , 2*i ) , set) ) * Fdx;
7215 */
7216 // Valgrind fix !! One-sided differences if one neighbor missing. It should be checked why this situation can
7217 // occur!!!!
7218 for(MInt i = 0; i < nDim; i++) {
7219 MInt n0 = c_neighborId(cellId, 2 * i);
7220 MInt n1 = c_neighborId(cellId, 2 * i + 1);
7221 if(n0 < 0) n0 = cellId;
7222 if(n1 < 0) n1 = cellId;
7223 a_levelSetFunctionSlope(cellId, i, set) = (a_levelSetFunctionG(n1, set) - a_levelSetFunctionG(n0, set))
7224 / (c_coordinate(n1, i) - c_coordinate(n0, i));
7225 }
7226
7227 FgradG = POW2(a_levelSetFunctionSlope(cellId, 0, set));
7228 for(MInt i = 1; i < nDim; i++)
7229 FgradG += POW2(a_levelSetFunctionSlope(cellId, i, set));
7230 FgradG = F1 / mMax(epsilon, sqrt(FgradG));
7231 for(MInt i = 0; i < nDim; i++)
7232 a_normalVectorG(cellId, i, set) = -FgradG * a_levelSetFunctionSlope(cellId, i, set);
7233 }
7234 }
7235 }
7236
7237 // exchange normal vectors on halo cells, cause they are needed for the curvature computation!
7238 exchangeDataLS(&a_normalVectorG(0, 0, 0), m_maxNoSets * nDim);
7239}
7240
7241
7242// ----------------------------------------------------------------------------------------
7243
7257template <MInt nDim>
7259 TRACE();
7260
7261 MFloat FgradG;
7262 MFloat epsilon = m_gCellDistance * 0.00000001;
7263 const MFloat Fdx = F1B2 * m_FgCellDistance;
7264 MInt cellId, nghbrL, nghbrL2, nghbrR, nghbrR2;
7265 // MBool boundary= false;
7266 MBool oneSidedR = false;
7267 MBool oneSidedL = false;
7268 MFloat FgCellDistanceL2R2 = m_FgCellDistance * F1B4, FgCellDistanceLR = m_FgCellDistance * F1B2;
7269
7270 //---
7271
7272 if(m_fourthOrderNormalCurvatureComputation) {
7273 for(MInt set = 0; set < m_noSets; set++) {
7274 if(!m_computeSet[set]) continue;
7275 for(MInt id = 0; id < a_noBandCells(set); id++) {
7276 cellId = a_bandCellId(id, set);
7277
7278 for(MInt i = 0; i < nDim; i++) {
7279 oneSidedR = false;
7280 oneSidedL = false;
7281
7282 FgCellDistanceL2R2 = m_FgCellDistance * F1B4;
7283 FgCellDistanceLR = m_FgCellDistance * F1B2;
7284
7285 nghbrL = c_neighborId(cellId, 2 * i);
7286 nghbrL2 = c_neighborId(nghbrL, 2 * i);
7287 nghbrR = c_neighborId(cellId, 2 * i + 1);
7288 nghbrR2 = c_neighborId(nghbrR, 2 * i + 1);
7289
7290 if(a_hasNeighbor(nghbrL2, 2 * i) != 0 && a_hasNeighbor(nghbrR2, 2 * i + 1) != 0) {
7291 if((!a_inBandG(nghbrL2, set) || !a_inBandG(nghbrR2, set))) {
7292 // reduce to second order
7293 nghbrR2 = nghbrR;
7294 nghbrL2 = nghbrL;
7295 FgCellDistanceL2R2 = FgCellDistanceLR;
7296 }
7297 }
7298
7299 if(!oneSidedR && !oneSidedL) {
7300 a_levelSetFunctionSlope(cellId, i, set) =
7301
7302 F4B3 * FgCellDistanceLR *
7303
7304 (a_levelSetFunctionG(nghbrR, set) - a_levelSetFunctionG(nghbrL, set))
7305
7306 - F1B3 * FgCellDistanceL2R2 *
7307
7308 (a_levelSetFunctionG(nghbrR2, set) - a_levelSetFunctionG(nghbrL2, set));
7309 }
7310 }
7311 FgradG = POW2(a_levelSetFunctionSlope(cellId, 0, set));
7312 for(MInt i = 1; i < nDim; i++)
7313 FgradG += POW2(a_levelSetFunctionSlope(cellId, i, set));
7314
7315 FgradG = F1 / mMax(epsilon, sqrt(FgradG));
7316
7317 for(MInt i = 0; i < nDim; i++)
7318 a_normalVectorG(cellId, i, set) = -FgradG * a_levelSetFunctionSlope(cellId, i, set);
7319 }
7320 }
7321 } else {
7322 for(MInt set = 0; set < m_noSets; set++) {
7323 if(!m_computeSet[set]) continue;
7324 for(MInt id = 0; id < a_noBandCells(set); id++) {
7325 cellId = a_bandCellId(id, set);
7326
7327 // second order code
7328
7329 for(MInt i = 0; i < nDim; i++)
7330 a_levelSetFunctionSlope(cellId, i, set) = (a_levelSetFunctionG(c_neighborId(cellId, 2 * i + 1), set)
7331 - a_levelSetFunctionG(c_neighborId(cellId, 2 * i), set))
7332 * Fdx;
7333
7334 FgradG = POW2(a_levelSetFunctionSlope(cellId, 0, set));
7335 for(MInt i = 1; i < nDim; i++)
7336 FgradG += POW2(a_levelSetFunctionSlope(cellId, i, set));
7337 FgradG = F1 / mMax(epsilon, sqrt(FgradG));
7338 for(MInt i = 0; i < nDim; i++)
7339 a_normalVectorG(cellId, i, set) = -FgradG * a_levelSetFunctionSlope(cellId, i, set);
7340 }
7341 }
7342 }
7343
7344 // exchange normal vectors on halo cells, cause they are needed for the curvature computation!
7345 exchangeDataLS(&a_normalVectorG(0, 0, 0), m_maxNoSets * nDim);
7346}
7347
7348
7349// ----------------------------------------------------------------------------------------
7350
7351
7352// author: Daniel Hartmann, 2007
7353template <MInt nDim>
7355 TRACE();
7356
7357 MFloat FgradG;
7358 const MFloat Fdx = F1B2 * m_FgCellDistance;
7359 //---
7360
7361 for(MInt set = 0; set < m_noSets; set++) {
7362 if(!m_computeSet[set]) continue;
7363 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7364 for(MInt i = 0; i < nDim; i++)
7365 a_levelSetFunctionSlope(a_G0CellId(id, set), i, set) =
7366 (a_levelSetFunctionG(c_neighborId(a_G0CellId(id, set), 2 * i + 1), set)
7367 - a_levelSetFunctionG(c_neighborId(a_G0CellId(id, set), 2 * i), set))
7368 * Fdx;
7369
7370 FgradG = POW2(a_levelSetFunctionSlope(a_G0CellId(id, set), 0, set));
7371 for(MInt i = 1; i < nDim; i++)
7372 FgradG += POW2(a_levelSetFunctionSlope(a_G0CellId(id, set), i, set));
7373 FgradG = F1 / sqrt(FgradG);
7374 for(MInt i = 0; i < nDim; i++)
7375 a_normalVectorG(a_G0CellId(id, set), i, set) = -FgradG * a_levelSetFunctionSlope(a_G0CellId(id, set), i, set);
7376 }
7377 }
7378}
7379
7380//-----------------------------------------------------------------------------------------
7381
7382
7389template <MInt nDim>
7391 // create the cell lists
7392 // cell list: internal cells without cut and bndry cells
7393 MInt cellListSize = 0;
7394
7395 // reset scratch array
7396 MIntScratchSpace gWindowCell(m_maxNoCells, AT_, "gWindowCell");
7397 gWindowCell.fill(0);
7398
7399 fill_n(m_cellList, m_maxNoCells, -1);
7400
7401 for(MInt id = 0; id < a_noBandCells(set); id++) {
7402 const MInt cellId = a_bandCellId(id, set);
7403 gWindowCell[cellId] = 0;
7404
7405 if(a_isGZeroCell(cellId, set)) {
7406 continue;
7407 }
7408
7409 if(a_level(cellId) != a_maxGCellLevel()) {
7410 continue;
7411 }
7412
7413 if(a_isHalo(cellId)) {
7414 continue;
7415 }
7416
7417 MInt count = 0;
7418 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
7419 if(a_hasNeighbor(cellId, dirId) && a_hasNeighbor(c_neighborId(cellId, dirId), dirId)
7420 && !a_isGBoundaryCellG(cellId, set) && !a_isGBoundaryCellG(c_neighborId(cellId, dirId), set)) {
7421 count++;
7422 }
7423 }
7424
7425 if(count == m_noDirs) {
7426 m_cellList[cellListSize++] = cellId;
7427 if(a_isWindow(cellId)) {
7428 gWindowCell[cellId] = 1;
7429 }
7430 }
7431 }
7432
7433 // exchange:
7434 // add halo cells to the list
7435 MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
7436 MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
7437 // gather:
7438 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7439 sendBufferSize.p[i] = 0;
7440 for(MInt j = 0; j < noWindowCells(i); j++) {
7441 m_intSendBuffers[i][sendBufferSize.p[i]++] = gWindowCell[windowCellId(i, j)];
7442 }
7443 }
7444 if(grid().azimuthalPeriodicity()) {
7445 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
7446 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
7447 m_intSendBuffers[i][sendBufferSize.p[i]++] = gWindowCell[grid().azimuthalWindowCell(i, j)];
7448 }
7449 }
7450 }
7451
7452 // exchange data -> send, receive
7453 exchangeIntBuffers(sendBufferSize.getPointer(), receiveBufferSize.getPointer(), 11, 1);
7454
7455 // scatter:
7456 // update the list and add halo cells which are needed for hyperbolic extension
7457 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7458#ifdef LS_DEBUG
7459 // check, if received data size matches expected size:
7460 if(receiveBufferSize.p[i] != noHaloCells(i))
7461 mTerm(1, AT_, "this was not expected to happen: wrong number of halo information...");
7462#endif
7463 for(MInt j = 0; j < noHaloCells(i); j++) {
7464 MInt haloCell = haloCellId(i, j);
7465 if(m_intReceiveBuffers[i][j] == 1) {
7466 m_cellList[cellListSize++] = haloCell;
7467 }
7468 }
7469 // cerr << "number of cells " << haloCnt << " added from neighbor domain " << grid().neighborDomain(i) << endl;
7470 }
7471
7472 if(grid().azimuthalPeriodicity()) {
7473 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
7474 MInt offset = noHaloCells(grid().azimuthalNeighborDomain(i));
7475 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
7476 MInt n = offset + j;
7477 MInt haloCell = grid().azimuthalHaloCell(i, j);
7478 if(m_intReceiveBuffers[i][n] == 1) {
7479 m_cellList[cellListSize++] = haloCell;
7480 }
7481 }
7482 }
7483 }
7484
7485 // TODO labels:LS maxNoCells vs a_noCells
7486 MFloatScratchSpace velocity(m_maxNoCells, AT_, "velocity");
7487
7488 for(MInt n = 0; n < nDim; n++) {
7489 velocity.fill(0.0);
7490
7491 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7492 const MInt cellId = a_G0CellId(id, set);
7493 if(a_isHalo(cellId)) {
7494 continue;
7495 }
7496
7497 velocity[cellId] = a_extensionVelocityG(cellId, n, set);
7498 }
7499
7500 for(MInt cell = 0; cell < cellListSize; cell++) {
7501 const MInt cellId = m_cellList[cell];
7502 velocity[cellId] = F0;
7503 }
7504
7505 hyperbolicExtensionOpt(velocity.getPointer(), m_cellList, cellListSize, m_extVelConvergence, set);
7506
7507 // TODO labels:LS Why? Seems redundant
7508 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7509 const MInt cellId = a_G0CellId(id, set);
7510 a_extensionVelocityG(cellId, n, set) = velocity[cellId];
7511 }
7512
7513 for(MInt cell = 0; cell < cellListSize; cell++) {
7514 const MInt cellId = m_cellList[cell];
7515 a_extensionVelocityG(cellId, n, set) = velocity[cellId];
7516 }
7517 }
7518}
7519
7520// ----------------------------------------------------------------------------------------
7527template <MInt nDim>
7529 TRACE();
7530
7531 ASSERT(m_lsCollectorMode == 0, "");
7532
7533 MInt cellId;
7534 MInt cellListSize;
7535 MFloatScratchSpace q(m_maxNoCells, AT_, "q");
7536 MIntScratchSpace gWindowCell(m_maxNoCells, AT_, "gWindowCell");
7537 MInt count = 0;
7538 MFloat FdampingDistanceFlameBase = F1 / m_dampingDistanceFlameBase;
7539 MFloat dampCoord = m_dampingDistanceFlameBase + m_yOffsetFlameTube;
7540 MFloat FextensionDampingDistanceFlameBase = F1 / m_dampingDistanceFlameBaseExtVel;
7541 MFloat extensionDampCoord = m_dampingDistanceFlameBaseExtVel + m_yOffsetFlameTube;
7542 MFloat levelSetPlus = F0, levelSetNegative = F0; //, curvatureFactor=F0;
7543 //---
7544
7545 // create the cell lists
7546 // cell list: internal cells without cut and bndry cells
7547 // bc cells : boundary cells
7548 cellListSize = 0;
7549
7550 // reset scratch array
7551 q.fill(F0);
7552 gWindowCell.fill(0);
7553
7554 for(MInt c = 0; c < m_maxNoCells; c++) {
7555 m_cellList[c] = -1;
7556 }
7557
7558 for(MInt id = 0; id < a_noBandCells(set); id++) {
7559 cellId = a_bandCellId(id, set);
7560 gWindowCell[cellId] = 0;
7561 if(a_isGZeroCell(cellId, set)) continue;
7562
7563 count = 0;
7564 if(a_level(cellId) != a_maxGCellLevel()) continue;
7565
7566 if(a_isHalo(cellId)) continue;
7567
7568 for(MInt dirId = 0; dirId < m_noDirs; dirId++) {
7569 if(a_hasNeighbor(cellId, dirId) && a_hasNeighbor(c_neighborId(cellId, dirId), dirId) &&
7570 // a_hasNeighbor( cellId , opposite[dirId] ) &&
7571 // a_hasNeighbor( c_neighborId( cellId , opposite[dirId] ) , opposite[dirId] ) &&
7572 !a_isGBoundaryCellG(cellId, set) && !a_isGBoundaryCellG(c_neighborId(cellId, dirId), set)) {
7573 count++;
7574 }
7575 }
7576 if(count == m_noDirs) {
7577 m_cellList[cellListSize++] = cellId;
7578 // for debugging
7579 // a_stretchG( cellId , 0) = 1;
7580 if(a_isWindow(cellId)) gWindowCell[cellId] = 1;
7581 }
7582 }
7583
7584 // exchange:
7585 // add halo cells to the list
7586 MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
7587 MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
7588 // gather:
7589 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7590 sendBufferSize.p[i] = 0;
7591 for(MInt j = 0; j < noWindowCells(i); j++) {
7592 m_intSendBuffers[i][sendBufferSize.p[i]++] = gWindowCell[windowCellId(i, j)];
7593 }
7594 }
7595 if(grid().azimuthalPeriodicity()) {
7596 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
7597 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
7598 m_intSendBuffers[i][sendBufferSize.p[i]++] = gWindowCell[grid().azimuthalWindowCell(i, j)];
7599 }
7600 }
7601 }
7602
7603 // exchange data -> send, receive
7604 exchangeIntBuffers(sendBufferSize.getPointer(), receiveBufferSize.getPointer(), 11, 1);
7605
7606 // scatter:
7607 // update the list and add halo cells which are needed for hyperbolic extension
7608 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
7609#ifdef LS_DEBUG
7610 // MInt haloCnt = 0;
7611 // check, if received data size matches expected size:
7612 if(receiveBufferSize.p[i] != noHaloCells(i))
7613 mTerm(1, AT_, "this was not expected to happen: wrong number of halo information...");
7614#endif
7615 for(MInt j = 0; j < noHaloCells(i); j++) {
7616 MInt haloCell = haloCellId(i, j);
7617 if(m_intReceiveBuffers[i][j] == 1) {
7618 m_cellList[cellListSize++] = haloCell;
7619 // for debugging
7620 // a_stretchG( haloCell , 0) = 1;
7621 // haloCnt++;
7622 }
7623 }
7624 // m_log << "number of cells " << haloCnt << " added from neighbor domain " << grid().neighborDomain(i) <<
7625 // endl;
7626 // cerr << "number of cells " << haloCnt << " added from neighbor domain " << grid().neighborDomain(i) << endl;
7627 }
7628
7629 if(grid().azimuthalPeriodicity()) {
7630 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
7631 MInt offset = noHaloCells(grid().azimuthalNeighborDomain(i));
7632 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
7633 MInt n = offset + j;
7634 MInt haloCell = grid().azimuthalHaloCell(i, j);
7635 if(m_intReceiveBuffers[i][n] == 1) {
7636 m_cellList[cellListSize++] = haloCell;
7637 }
7638 }
7639 }
7640 }
7641
7642
7643 // compute the extension velocity of G0 cut cells
7644 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7645 cellId = a_G0CellId(id, set);
7646
7647 a_correctedBurningVelocity(cellId, set) =
7648 a_flameSpeedG(cellId, set) * (F1 - a_curvatureG(cellId, set) * m_marksteinLength);
7649
7650 for(MInt i = 0; i < nDim; i++) {
7651 a_extensionVelocityG(cellId, i, set) += a_normalVectorG(cellId, i, set) * m_rhoFlameTube * FfluidDensity[id]
7652 * a_correctedBurningVelocity(cellId, set);
7653 }
7654 }
7655
7656 if(cellListSize < a_noG0Cells(set)) {
7657 cerr << "Error: number of cells in cell list is smaller than number of G0 cells" << cellListSize
7658 << " , noG0cells: " << a_noG0Cells(set) << endl;
7659 }
7660
7661 IF_CONSTEXPR(nDim == 2) {
7662 // iterative extension
7663 for(MInt i = 0; i < nDim; i++) {
7664 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7665 cellId = a_G0CellId(id, set);
7666 if(a_isHalo(cellId)) continue;
7667
7668 q.p[cellId] = a_extensionVelocityG(cellId, i, set);
7669 if(c_coordinate(cellId, 1) < extensionDampCoord) {
7670 q.p[cellId] = a_extensionVelocityG(cellId, i, set) * FextensionDampingDistanceFlameBase
7671 * (c_coordinate(cellId, 1) - m_yOffsetFlameTube);
7672 }
7673 }
7674 // needed otherwise solution for previous space direction is used
7675 for(MInt cell = 0; cell < cellListSize; cell++) {
7676 cellId = m_cellList[cell];
7677 q.p[cellId] = F0;
7678 }
7679
7680 hyperbolicExtensionOpt(q.getPointer(), m_cellList, cellListSize, m_extVelConvergence, set);
7681
7682 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7683 cellId = a_G0CellId(id, set);
7684 a_extensionVelocityG(cellId, i, set) = q.p[cellId];
7685 }
7686
7687 for(MInt cell = 0; cell < cellListSize; cell++) {
7688 cellId = m_cellList[cell];
7689 a_extensionVelocityG(cellId, i, set) = q.p[cellId];
7690 }
7691 }
7692
7693 if(m_useCorrectedBurningVelocity) {
7694 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7695 cellId = a_G0CellId(id, set);
7696 if(a_isHalo(cellId)) continue;
7697 q.p[cellId] = a_correctedBurningVelocity(cellId, set);
7698 }
7699 hyperbolicExtensionOpt(q.getPointer(), m_cellList, cellListSize, m_extVelConvergence, set);
7700
7701 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7702 cellId = a_G0CellId(id, set);
7703 a_correctedBurningVelocity(cellId, set) = q.p[cellId];
7704 }
7705 for(MInt cell = 0; cell < cellListSize; cell++) {
7706 cellId = m_cellList[cell];
7707 a_correctedBurningVelocity(cellId, set) = q.p[cellId];
7708 }
7709 }
7710
7711 if(m_hyperbolicCurvature)
7712 hyperbolicExtensionOpt(&a_curvatureG(0, 0), m_cellList, cellListSize, m_extVelConvergence, set);
7713
7714 for(MInt id = 0; id < a_noBandCells(set); id++) {
7715 cellId = a_bandCellId(id, set);
7716
7717 if(c_coordinate(cellId, 1) < m_yOffsetFlameTube) {
7718 a_curvatureG(cellId, set) = F0;
7719 for(MInt i = 0; i < nDim; i++) {
7720 a_extensionVelocityG(cellId, i, set) = F0;
7721 }
7722 continue;
7723 }
7724 // linearly damping of curvature to flame base
7725 if(c_coordinate(cellId, 1) < dampCoord) {
7726 a_curvatureG(cellId, set) *= FdampingDistanceFlameBase * (c_coordinate(cellId, 1) - 0.0234);
7727 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
7728 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
7729 a_curvatureG(cellId, set) *= F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0));
7730 }
7731 // linearly damping of extension velocity to flame base
7732 if(c_coordinate(cellId, 1) < extensionDampCoord) {
7733 for(MInt i = 0; i < nDim; i++) {
7734 a_extensionVelocityG(cellId, i, set) *=
7735 FextensionDampingDistanceFlameBase * (c_coordinate(cellId, 1) - m_yOffsetFlameTube);
7736 }
7737 }
7738 }
7739 // 3D
7740 }
7741 else {
7742 // iterative extension
7743 for(MInt i = 0; i < nDim; i++) {
7744 /* MFloat tmp=F0;
7745 MFloat tmpM=2147483647;
7746 */
7747 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7748 cellId = a_G0CellId(id, set);
7749 if(a_isHalo(cellId)) continue;
7750
7751
7752 q.p[cellId] = a_extensionVelocityG(cellId, i, set);
7753
7754 if(c_coordinate(cellId, 1) < extensionDampCoord) {
7755 q.p[cellId] *= FextensionDampingDistanceFlameBase * (c_coordinate(cellId, 1) - m_yOffsetFlameTube);
7756 }
7757 if(c_coordinate(cellId, 1) < m_yOffsetFlameTube) {
7758 q.p[cellId] = F0;
7759 }
7760 }
7761 // needed otherwise solution for previous space direction is used
7762 for(MInt cell = 0; cell < cellListSize; cell++) {
7763 cellId = m_cellList[cell];
7764 q.p[cellId] = F0;
7765 }
7766
7767 hyperbolicExtensionOpt(q.getPointer(), m_cellList, cellListSize, m_extVelConvergence, set);
7768
7769 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7770 cellId = a_G0CellId(id, set);
7771 a_extensionVelocityG(cellId, i, set) = q.p[cellId];
7772 }
7773
7774 for(MInt cell = 0; cell < cellListSize; cell++) {
7775 cellId = m_cellList[cell];
7776 a_extensionVelocityG(cellId, i, set) = q.p[cellId];
7777 }
7778 }
7779
7780 if(m_useCorrectedBurningVelocity) {
7781 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7782 cellId = a_G0CellId(id, set);
7783 if(a_isHalo(cellId)) continue;
7784 q.p[cellId] = a_correctedBurningVelocity(cellId, set);
7785 }
7786 hyperbolicExtensionOpt(q.getPointer(), m_cellList, cellListSize, m_extVelConvergence, set);
7787
7788 for(MInt id = 0; id < a_noG0Cells(set); id++) {
7789 cellId = a_G0CellId(id, set);
7790 a_correctedBurningVelocity(cellId, set) = q.p[cellId];
7791 }
7792 for(MInt cell = 0; cell < cellListSize; cell++) {
7793 cellId = m_cellList[cell];
7794 a_correctedBurningVelocity(cellId, set) = q.p[cellId];
7795 }
7796 }
7797
7798 if(m_hyperbolicCurvature)
7799 hyperbolicExtensionOpt(&a_curvatureG(0, 0), m_cellList, cellListSize, m_extVelConvergence, set);
7800
7801 for(MInt id = 0; id < a_noBandCells(set); id++) {
7802 cellId = a_bandCellId(id, set);
7803
7804 if(c_coordinate(cellId, 1) < m_yOffsetFlameTube) {
7805 a_curvatureG(cellId, set) = F0;
7806 for(MInt i = 0; i < nDim; i++) {
7807 a_extensionVelocityG(cellId, i, set) = F0;
7808 }
7809 continue;
7810 }
7811 // linearly damping of curvature to flame base
7812 if(c_coordinate(cellId, 1) < dampCoord) {
7813 a_curvatureG(cellId, set) *= FdampingDistanceFlameBase * (c_coordinate(cellId, 1) - m_yOffsetFlameTube);
7814 levelSetNegative = a_levelSetFunctionG(cellId, set) - (m_noReactionCells / m_curvatureDampFactor);
7815 levelSetPlus = a_levelSetFunctionG(cellId, set) + (m_noReactionCells / m_curvatureDampFactor);
7816 a_curvatureG(cellId, set) *= F1B4 * (1 + tanh(levelSetPlus * 100.0)) * (1 - tanh(levelSetNegative * 100.0));
7817 }
7818 // linearly damping of extension velocity to flame base
7819 if(c_coordinate(cellId, 1) < extensionDampCoord) {
7820 for(MInt i = 0; i < nDim; i++) {
7821 a_extensionVelocityG(cellId, i, set) *=
7822 FextensionDampingDistanceFlameBase * (c_coordinate(cellId, 1) - m_yOffsetFlameTube);
7823 }
7824 }
7825 }
7826 }
7827
7828 DEBUG("LsCartesianSolver::computeExtensionVelocityGEQUPVMarksteinOpt return", MAIA_DEBUG_TRACE_OUT);
7829}
7830
7831// ----------------------------------------------------------------------------------------
7832
7833
7844template <MInt nDim>
7846 MFloat convergenceCriterion, MInt set) {
7847 TRACE();
7848 m_log << "ERROR, WARNING, you are using hyperbolicExtensionOpt... look at the code and make sure the "
7849 "'optimization' below '//euler solver' is not commented since it is wrong"
7850 << endl;
7851
7852 MInt cellId;
7853 MInt iteration;
7854 MInt nghbrL, nghbrR;
7855 MFloat dtEULER = m_extVelCFL * m_gCellDistance;
7856 MFloat eps = 0.000000001;
7857 MFloat qOld = F0;
7858 MInt minIteration;
7859 MFloatScratchSpace levelSetRHS(m_maxNoCells, AT_, "levelSetRHS");
7860
7861 // compute minimum iterations to transport the velocity to the band cells
7862 minIteration = m_gBandWidth / m_extVelCFL;
7863
7864 //---
7865
7866 // initialize
7867 iteration = 0;
7868 MFloat res = 0;
7869
7870 for(MInt cell = 0; cell < cellListSize; cell++) {
7871 cellId = cellList[cell];
7872 m_signG[IDX_LSSET(cellId, set)] =
7873 a_levelSetFunctionG(cellId, set) / mMax(eps, fabs(a_levelSetFunctionG(cellId, set)));
7874 }
7875
7876 exchangeLs(q, set, 1);
7877
7878 // Stephan: this condition assures a fully extension of the velocity with a certain convergence criterion,
7879 // - minIteration: necessary because otherwise a wrong user defined extVelIteration number could lead to
7880 // unwanted velocity oscillations
7881 // - checking another time convergenceCriterion is necessary otherwise the minimum number of iterations could
7882 // be reached but the convergence criterion is not reached!
7883 // TODO labels:LS,totest check wether extVelIterations could be removed?!
7884 // TODO labels:LS,toenhance unified method of reinitialization
7885 while(iteration < m_extVelIterations || iteration < minIteration || res < convergenceCriterion) {
7886 // apply outer boundary condition d(fExt_i) / d(x_i) = 0
7887 /*
7888 for( MInt cell = 0; cell < noBcCells; cell++ ) {
7889 cellId = bcCellList[ cell ];
7890 q[ cellId ] = bc*q[ linkedInternalCell[cellId] ];
7891 }
7892 */
7893 res = F0;
7894 for(MInt cell = 0; cell < cellListSize; cell++) {
7895 cellId = cellList[cell];
7896 levelSetRHS[cellId] = F0;
7897 if(a_isHalo(cellId)) continue;
7898 for(MInt i = 0; i < nDim; i++) {
7899 nghbrL = c_neighborId(cellId, 2 * i); //[ cellId*m_noDirs + 2*i ];
7900 nghbrR = c_neighborId(cellId, 2 * i + 1); // nghbrs[ cellId*m_noDirs + 2*i+1 ];
7901 levelSetRHS[cellId] += mMax(m_signG[IDX_LSSET(cellId, set)] * (-a_normalVectorG(cellId, i, set)), F0)
7902 * (q[cellId] - q[nghbrL]) * m_FgCellDistance
7903 + mMin(m_signG[IDX_LSSET(cellId, set)] * (-a_normalVectorG(cellId, i, set)), F0)
7904 * (q[nghbrR] - q[cellId]) * m_FgCellDistance;
7905 }
7906
7907
7908 // Euler solver //this commented part may not be commented... this "optimization" by stephan introduces a
7909 // direction dependency of the solution. This has to be uncommented before using this function!!
7910 /* for( MInt cell = 0; cell < cellListSize; cell++ ) {
7911 cellId = cellList[ cell ];
7912 if( a_isHalo( cellId ) )
7913 continue;
7914 */
7915 qOld = q[cellId];
7916 q[cellId] = qOld - dtEULER * levelSetRHS[cellId];
7917 res = mMax(res, ABS(q[cellId] - qOld));
7918 }
7919
7920 exchangeLs(q, set, 1);
7921
7922 iteration++;
7923
7924 MPI_Allreduce(MPI_IN_PLACE, &res, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "res");
7925
7926 switch(m_levelSetBoundaryCondition) {
7927 default: {
7928 // check convergence, if minimum number of iteration is reached
7929 if(res < convergenceCriterion) { //&& iteration> minIteration){
7930
7931 if(domainId() == 0) {
7932 FILE* datei;
7933 stringstream hyperbolicFile;
7934 hyperbolicFile << "hyperbolicExtension";
7935 if(m_noSets > 1) hyperbolicFile << "_s" << set;
7936 hyperbolicFile << "_" << domainId();
7937 datei = fopen((hyperbolicFile.str()).c_str(), "a+");
7938 fprintf(datei, " %d", globalTimeStep);
7939 fprintf(datei, " %-10.10f", res);
7940 fprintf(datei, " %d", iteration);
7941 fprintf(datei, "\n");
7942 fclose(datei);
7943 }
7944
7945
7946 return iteration;
7947 }
7948 }
7949 }
7950 }
7951
7952 if(domainId() == 0) {
7953 FILE* datei;
7954 stringstream hyperbolicFile;
7955 hyperbolicFile << "hyperbolicExtension";
7956 if(m_noSets > 1) hyperbolicFile << "_s" << set;
7957 hyperbolicFile << "_" << domainId();
7958 datei = fopen((hyperbolicFile.str()).c_str(), "a+");
7959 fprintf(datei, " %d", globalTimeStep);
7960 fprintf(datei, " %-10.10f", res);
7961 fprintf(datei, " %d", iteration);
7962 fprintf(datei, "\n");
7963 fclose(datei);
7964 }
7965
7966 return iteration;
7967}
7968
7969
7970//---------------------------------------------------------------------------
7971
7972
7978template <MInt nDim>
7980 TRACE();
7981 if(m_combustion) {
7982 } else if(m_levelSetMb || m_levelSetFv) {
7983 // NOTE: the timeStep is copied from the fv-solver in transferTimeStep in the coupler!
7984 return;
7985 } else if(m_freeSurface) {
7986 // Note: the timeStep is set by the flow solver
7987 return;
7988 } else {
7989 ASSERT(m_timeStepMethod == 8, "");
7990 m_timeStep = m_cfl * m_gCellDistance;
7991 }
7992}
7993
7994
7995//-----------------------------------------------------------------------------
7996
7997
8007template <MInt nDim>
8009 TRACE();
8010
8011 MInt cellId;
8012 MFloat factor;
8013 MFloat FnoChildren = F1 / FPOW2(nDim);
8014 // ---
8015
8016 for(MInt set = 0; set < m_noSets; set++) {
8017 // reset all coarse grid cells
8018 for(MInt id = 0; id < a_noBandCells(set); id++) {
8019 cellId = a_bandCellId(id, set);
8020 while(c_parentId(cellId) > -1) {
8021 cellId = c_parentId(cellId);
8022 a_levelSetFunctionG(cellId, set) = 0;
8023 if(!m_semiLagrange) {
8024 a_correctedBurningVelocity(cellId, set) = 0;
8025 a_curvatureG(cellId, set) = F0;
8026 for(MInt i = 0; i < nDim; i++) {
8027 a_extensionVelocityG(cellId, i, set) = 0;
8028 a_normalVectorG(cellId, i, set) = 0;
8029 }
8030 }
8031 }
8032 }
8033
8034 // update all coarse grid cells
8035 for(MInt id = 0; id < a_noBandCells(set); id++) {
8036 cellId = a_bandCellId(id, set);
8037 factor = F1;
8038 while(c_parentId(cellId) > -1) {
8039 cellId = c_parentId(cellId);
8040 factor *= FnoChildren;
8041 a_levelSetFunctionG(cellId, set) += factor * a_levelSetFunctionG(a_bandCellId(id, set), set);
8042 if(!m_semiLagrange) {
8043 a_correctedBurningVelocity(cellId, set) += factor * a_correctedBurningVelocity(a_bandCellId(id, set), set);
8044 a_curvatureG(cellId, set) += factor * a_curvatureG(a_bandCellId(id, set), set);
8045
8046 for(MInt i = 0; i < nDim; i++) {
8047 a_extensionVelocityG(cellId, i, set) += factor * a_extensionVelocityG(a_bandCellId(id, set), i, set);
8048 a_normalVectorG(cellId, i, set) += factor * a_normalVectorG(a_bandCellId(id, set), i, set);
8049 }
8050 }
8051 }
8052 }
8053 }
8054}
8055
8056
8057//-----------------------------------------------------------------------------
8058
8059
8060// computations are only based on zeroth level-set function!
8068template <MInt nDim>
8070 TRACE();
8071
8072 MFloat deltaFunction; //,deltaFunctionR;
8073 MFloat Dx0, Dxplus, Dxminus, Dy0, Dyplus, Dyminus, sigma, rhoS_L;
8074
8075 const MFloat eps = F1 / FPOW10[10];
8076 MInt cellId;
8077 // MFloat a=-F23B24,b=F7B8,c1=F1B8,d=-F1B24;
8078 // MBool boundary = false;
8079 MInt set = 0;
8080
8081 if(!m_highOrderDeltaFunction) {
8082 m_arcLength = F0;
8083 m_massConsumption = F0;
8084
8085 for(MInt id = 0; id < a_noG0Cells(set); id++) {
8086 deltaFunction = F0;
8087 cellId = a_G0CellId(id, set);
8088 if(a_isHalo(cellId)) continue;
8089
8090 if(a_level(cellId) != a_maxGCellLevel()) continue;
8091 // compute the discrete derivatives
8092 Dx0 = (a_levelSetFunctionG(c_neighborId(cellId, 1), set) - a_levelSetFunctionG(c_neighborId(cellId, 0), set))
8093 * m_FgCellDistance * F1B2;
8094 Dxplus =
8095 (a_levelSetFunctionG(c_neighborId(cellId, 1), set) - a_levelSetFunctionG(cellId, set)) * m_FgCellDistance;
8096 Dxminus =
8097 (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(c_neighborId(cellId, 0), set)) * m_FgCellDistance;
8098 Dy0 = (a_levelSetFunctionG(c_neighborId(cellId, 3), set) - a_levelSetFunctionG(c_neighborId(cellId, 2), set))
8099 * m_FgCellDistance * F1B2;
8100 Dyplus =
8101 (a_levelSetFunctionG(c_neighborId(cellId, 3), set) - a_levelSetFunctionG(cellId, set)) * m_FgCellDistance;
8102 Dyminus =
8103 (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(c_neighborId(cellId, 2), set)) * m_FgCellDistance;
8104 IF_CONSTEXPR(nDim == 3) {
8105 MFloat Dz0 = F0;
8106 MFloat Dzplus = F0;
8107 MFloat Dzminus = F0;
8108 Dz0 = (a_levelSetFunctionG(c_neighborId(cellId, 5), set) - a_levelSetFunctionG(c_neighborId(cellId, 4), set))
8109 * m_FgCellDistance * F1B2;
8110 Dzplus =
8111 (a_levelSetFunctionG(c_neighborId(cellId, 5), set) - a_levelSetFunctionG(cellId, set)) * m_FgCellDistance;
8112 Dzminus =
8113 (a_levelSetFunctionG(cellId, set) - a_levelSetFunctionG(c_neighborId(cellId, 4), set)) * m_FgCellDistance;
8114 sigma = sqrt(POW2(Dx0) + POW2(Dy0) + POW2(Dz0) + eps);
8115
8116 // compute delta function (z contribution)
8117 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 4), set) < F0)
8118 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 4), set) * Dz0)
8119 / (ABS(Dzminus) * ABS(sigma) * POW2(m_gCellDistance));
8120 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 5), set) < F0)
8121 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 5), set) * Dz0)
8122 / (ABS(Dzplus) * ABS(sigma) * POW2(m_gCellDistance));
8123 }
8124 else {
8125 sigma = sqrt(POW2(Dx0) + POW2(Dy0) + eps);
8126 } /*
8127 if(a_levelSetFunctionG( cellId , set) == F0 ||
8128 a_levelSetFunctionG( m_nghbrIdsG[ m_noDirs*cellId ] , set) == F0 ||
8129 a_levelSetFunctionG( m_nghbrIdsG[ m_noDirs*cellId ] + 1, set) == F0 ||
8130 a_levelSetFunctionG( m_nghbrIdsG[ m_noDirs*cellId ] + 2 , set) == F0 ||
8131 a_levelSetFunctionG( m_nghbrIdsG[ m_noDirs*cellId ] + 3 , set) == F0
8132 ){
8133 cerr << "arclength could be affected by levelsetfunction == 0" << endl;
8134 }*/
8135 // compute the delta function (x and y contributions)
8136 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 0), set) < F0)
8137 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 0), set) * Dx0)
8138 / (ABS(Dxminus) * ABS(sigma) * POW2(m_gCellDistance));
8139 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 1), set) < F0)
8140 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 1), set) * Dx0)
8141 / (ABS(Dxplus) * ABS(sigma) * POW2(m_gCellDistance));
8142 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 2), set) < F0)
8143 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 2), set) * Dy0)
8144 / (ABS(Dyminus) * ABS(sigma) * POW2(m_gCellDistance));
8145 if(a_levelSetFunctionG(cellId, set) * a_levelSetFunctionG(c_neighborId(cellId, 3), set) < F0)
8146 deltaFunction += ABS(a_levelSetFunctionG(c_neighborId(cellId, 3), set) * Dy0)
8147 / (ABS(Dyplus) * ABS(sigma) * POW2(m_gCellDistance));
8148
8149 if(m_combustion && m_plenum) {
8150 IF_CONSTEXPR(nDim == 2) {
8151 m_arcLength += deltaFunction * POW2(m_gCellDistance);
8152 rhoS_L = m_rhoFlameTube * a_flameSpeedG(cellId, set) * (F1 - a_curvatureG(cellId, set) * m_marksteinLength);
8153 // rhoS_L = m_rhoFlameTube * a_correctedBurningVelocity(cellId, set);
8154 m_massConsumption += rhoS_L * deltaFunction * sigma * POW2(m_gCellDistance);
8155 // m_massConsumption += a_correctedBurningVelocity(cellId, set) * deltaFunction * sigma * POW2(
8156 // m_gCellDistance );
8157 }
8158 else {
8159 m_arcLength += deltaFunction * POW3(m_gCellDistance);
8160 rhoS_L = m_rhoFlameTube * a_flameSpeedG(cellId, set) * (F1 - a_curvatureG(cellId, set) * m_marksteinLength);
8161 // rhoS_L = m_rhoFlameTube * a_correctedBurningVelocity(cellId, set);
8162 m_massConsumption += rhoS_L * deltaFunction * sigma * POW3(m_gCellDistance);
8163 // m_massConsumption += a_correctedBurningVelocity(cellId, set) * deltaFunction * sigma * POW3(
8164 // m_gCellDistance );
8165 }
8166 } else {
8167 IF_CONSTEXPR(nDim == 2) {
8168 m_arcLength += deltaFunction * POW2(m_gCellDistance);
8169 rhoS_L = m_rhoInfinity * a_flameSpeedG(cellId, set) * (F1 - a_curvatureG(cellId, set) * m_marksteinLength);
8170 m_massConsumption += rhoS_L * deltaFunction * sigma * POW2(m_gCellDistance);
8171 // m_massConsumption += a_correctedBurningVelocity(cellId, set) * deltaFunction * sigma * POW2(
8172 // m_gCellDistance );
8173 }
8174 else {
8175 m_arcLength += deltaFunction * POW3(m_gCellDistance);
8176 rhoS_L = m_rhoInfinity * a_flameSpeedG(cellId, set) * (F1 - a_curvatureG(cellId, set) * m_marksteinLength);
8177 m_massConsumption += rhoS_L * deltaFunction * sigma * POW3(m_gCellDistance);
8178 // m_massConsumption += a_correctedBurningVelocity(cellId, set) * deltaFunction * sigma * POW3(
8179 // m_gCellDistance );
8180 }
8181 }
8182 }
8183 } else {
8185 // stringstream errorMessage;
8186 // errorMessage << "LsCartesianSolver::computeZeroLevelSetArcLength(): switch variable
8187 // 'm_highOrderDeltaFunction' with value " << m_highOrderDeltaFunction << " not matching any case." << endl;
8188 // mTerm(1, AT_, errorMessage.str());
8189 }
8190
8191 MPI_Allreduce(MPI_IN_PLACE, &m_arcLength, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "m_arcLength");
8192 MPI_Allreduce(MPI_IN_PLACE, &m_massConsumption, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
8193 "m_massConsumption");
8194}
8195
8196
8197//-----------------------------------------------------------------------------
8198
8199
8213template <MInt nDim>
8215 TRACE();
8216
8217 // initialize Tables
8218 mAlloc(m_bodyToSetTable, m_noBodyBndryCndIds, "m_bodyToSetTable", 0, AT_);
8219 mAlloc(m_noBodiesInSet, m_maxNoSets, "m_noBodiesInSet", 0, AT_);
8220 mAlloc(m_setToBodiesTable, m_maxNoSets, m_noBodyBndryCndIds, "m_setToBodiesTable", 0, AT_);
8221 MIntScratchSpace bodiesinSet(m_noSets, AT_, "bodiesinSet");
8222 MInt sumbodies = 0;
8223
8224 // 0: read and allocate properties
8225 m_startSet = (m_buildCollectedLevelSetFunction ? 1 : 0);
8226 m_noSets = m_noBodyBndryCndIds + m_startSet; // default
8227 m_noSets = Context::getSolverProperty<MInt>("nodifferentSets", m_solverId, AT_, &m_noSets);
8228
8229 // 1: test if property is set
8230 if(Context::propertyExists("bodiesinSet", m_solverId)) {
8231 for(MInt i = 0; i < m_noSets; i++) {
8232 bodiesinSet[i] = Context::getSolverProperty<MInt>("bodiesinSet", m_solverId, AT_, &bodiesinSet[i], i);
8233 sumbodies = sumbodies + bodiesinSet[i];
8234 }
8235
8236 if(sumbodies != m_noBodyBndryCndIds)
8237 mTerm(1, AT_,
8238 "The number of bodies devided onto the sets does not fit the total number of moving "
8239 "boundery-conditions for mode 11!");
8240 m_noSets = m_noSets + m_startSet; // increased for G0-level
8241
8242 // 2: setup the levelset table
8243 MInt count = 0;
8244 for(MInt j = 0; j < m_noSets; j++) {
8245 for(MInt i = 0; i < bodiesinSet[j]; i++) {
8246 m_bodyToSetTable[count] = j + m_startSet;
8247 m_setToBodiesTable[m_startSet + j][i] = count;
8248 m_noBodiesInSet[m_startSet + j]++;
8249 count++;
8250 }
8251 }
8252
8253 // 3: catch if the propery is not set
8254 } else {
8255 m_startSet = 1;
8256 m_noSets = m_noBodyBndryCndIds + m_startSet;
8257 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
8258 m_bodyToSetTable[i] = i + m_startSet;
8259 m_setToBodiesTable[i + m_startSet][m_noBodiesInSet[i + m_startSet]] = i;
8260 m_noBodiesInSet[i + m_startSet]++;
8261 }
8262 }
8263
8264 if(m_noSets > 0 && domainId() == 0 && m_noBodyBndryCndIds <= 10) {
8265 cerr << " noSets: " << m_noSets << endl;
8266 cerr << " m_bodyToSetTable: ";
8267 for(MInt i = 0; i < m_noBodyBndryCndIds; i++)
8268 cerr << " " << m_bodyToSetTable[i];
8269 cerr << endl;
8270 cerr << " m_noBodiesInSet: ";
8271 for(MInt i = 0; i < m_maxNoSets; i++)
8272 cerr << " " << m_noBodiesInSet[i];
8273 cerr << endl;
8274 cerr << " m_setToBodiesTable: ";
8275 for(MInt i = 0; i < m_maxNoSets; i++) {
8276 cerr << "s" << i << ": ";
8277 for(MInt j = 0; j < m_noBodiesInSet[i]; j++)
8278 cerr << " " << m_setToBodiesTable[i][j];
8279 }
8280 cerr << endl;
8281 }
8282
8283 for(MInt i = 0; i < m_maxNoSets; i++) {
8284 if(m_noBodiesInSet[i] > m_noBodyBndryCndIds) mTerm(1, AT_, to_string(m_noBodiesInSet[i]));
8285 for(MInt j = 0; j < m_noBodyBndryCndIds; j++) {
8286 if(m_setToBodiesTable[i][j] > m_noEmbeddedBodies) mTerm(1, AT_, to_string(m_setToBodiesTable[i][j]));
8287 }
8288 }
8289 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
8290 if(m_bodyToSetTable[i] > m_noSets) mTerm(1, AT_, to_string(m_bodyToSetTable[i]));
8291 }
8292}
8293
8294
8295//-----------------------------------------------------------------------------
8296
8297
8312template <MInt nDim>
8314 MFloat elapsedTime, MBool printPosition) {
8315 TRACE();
8316
8317 ASSERT(!m_combustion && !m_freeSurface, "");
8318
8319 if(m_periodicMovement && globalTimeStep == m_restartTimeStep) {
8320 determinePeriodicDistance();
8321 }
8322
8323
8324 MFloat angle = F0;
8325 MBool& first = m_static_computeBodyProperties_first;
8326 MFloat(&amplitude)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_amplitude;
8327 MFloat(&freqFactor)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_freqFactor;
8328 MFloat(&initialBodyCenter)[s_maxNoEmbeddedBodies * 3] = m_static_computeBodyProperties_initialBodyCenter;
8329 MFloat& Strouhal = m_static_computeBodyProperties_Strouhal;
8330 MFloat(&mu)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_mu;
8331 MFloat(&mu2)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_mu2;
8332 MFloat(&liftStartAngle1)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_liftStartAngle1;
8333 MFloat(&liftEndAngle1)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_liftEndAngle1;
8334 MFloat(&liftStartAngle2)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_liftStartAngle2;
8335 MFloat(&liftEndAngle2)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_liftEndAngle2;
8336 MFloat(&circleStartAngle)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_circleStartAngle;
8337 MFloat(&normal)[s_maxNoEmbeddedBodies * 3] = m_static_computeBodyProperties_normal;
8338 MInt(&bodyToFunction)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_bodyToFunction;
8339 MFloat& omega = m_static_computeBodyProperties_omega;
8340 MFloat& rotAngle = m_static_computeBodyProperties_rotAngle;
8341 MFloat(&temperature)[s_maxNoEmbeddedBodies] = m_static_computeBodyProperties_temperature;
8342
8343
8344 if(first) {
8345 const MInt noEmbeddedBodies = m_noEmbeddedBodies;
8346
8347 if(noEmbeddedBodies > s_maxNoEmbeddedBodies) {
8348 mTerm(1, AT_, "Error in computeBodyProperties: too many embedded Bodies!");
8349 }
8350
8351 // 1: set default values:
8352 Strouhal = 0.2;
8353 for(MInt k = 0; k < s_maxNoEmbeddedBodies; k++) {
8354 amplitude[k] = 0.1;
8355 freqFactor[k] = 1.0;
8356 bodyToFunction[k] = 1;
8357 for(MInt i = 0; i < nDim; i++) {
8358 initialBodyCenter[k * nDim + i] = F0;
8359 normal[k * nDim + i] = F0;
8360 }
8361 normal[k * nDim + 0] = 1.0;
8362 liftStartAngle1[k] = F0;
8363 liftEndAngle1[k] = PI;
8364 liftStartAngle2[k] = 3.0 * PI;
8365 liftEndAngle2[k] = 4.0 * PI;
8366 circleStartAngle[k] = F0;
8367 temperature[k] = 1;
8368 }
8369
8370 if(m_levelSetLb) {
8371 MFloat MaLb = Context::getSolverProperty<MFloat>("Ma", m_solverId, AT_);
8372 for(MInt k = 0; k < s_maxNoEmbeddedBodies; k++) {
8373 amplitude[k] = MaLb * LBCS;
8374 }
8375 }
8376
8377 // 2: read Properties
8378
8391 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8392 amplitude[i] = Context::getSolverProperty<MFloat>("amplitudes", m_solverId, AT_, &amplitude[i], i);
8393 }
8394
8395 if(m_levelSetLb) {
8396 MFloat MaLb = Context::getSolverProperty<MFloat>("Ma", m_solverId, AT_);
8397 for(MInt k = 0; k < s_maxNoEmbeddedBodies; k++) {
8398 amplitude[k] *= MaLb / F1BCS;
8399 }
8400 }
8401
8414 for(MInt i = 0; i < noEmbeddedBodies; i++)
8415 freqFactor[i] = Context::getSolverProperty<MFloat>("freqFactors", m_solverId, AT_, &freqFactor[i], i);
8416
8429 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8430 bodyToFunction[i] =
8431 Context::getSolverProperty<MInt>("bodyMovementFunctions", m_solverId, AT_, &bodyToFunction[i], i);
8432 }
8433 Strouhal = Context::getSolverProperty<MFloat>("Strouhal", m_solverId, AT_, &Strouhal);
8434
8445 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8446 for(MInt j = 0; j < nDim; j++) {
8447 initialBodyCenter[i * nDim + j] = Context::getSolverProperty<MFloat>(
8448 "initialBodyCenters", m_solverId, AT_, &initialBodyCenter[i * nDim + j], i * nDim + j);
8449 }
8450 }
8451
8452 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8453 for(MInt j = 0; j < nDim; j++) {
8454 normal[i * nDim + j] = Context::getSolverProperty<MFloat>("bodyMotionNormals", m_solverId, AT_,
8455 &normal[i * nDim + j], i * nDim + j);
8456 }
8457 }
8471 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8472 liftStartAngle1[i] =
8473 Context::getSolverProperty<MFloat>("liftStartAngles1", m_solverId, AT_, &liftStartAngle1[i], i);
8474 }
8475
8488 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8489 liftStartAngle2[i] =
8490 Context::getSolverProperty<MFloat>("liftStartAngles2", m_solverId, AT_, &liftStartAngle2[i], i);
8491 }
8492
8503 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8504 liftEndAngle1[i] = Context::getSolverProperty<MFloat>("liftEndAngles1", m_solverId, AT_, &liftEndAngle1[i], i);
8505 }
8506
8517 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8518 liftEndAngle2[i] = Context::getSolverProperty<MFloat>("liftEndAngles2", m_solverId, AT_, &liftEndAngle2[i], i);
8519 }
8520
8532 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8533 circleStartAngle[i] =
8534 Context::getSolverProperty<MFloat>("circleStartAngles", m_solverId, AT_, &circleStartAngle[i], i);
8535 }
8536
8549 rotAngle = 0.0;
8550 rotAngle = Context::getSolverProperty<MFloat>("rotAngle", m_solverId, AT_, &rotAngle);
8551 rotAngle *= -PI / 180;
8552
8553 // 3: compute relevant values:
8554 const MFloat freq0 = Strouhal * m_referenceVelocity;
8555 const MFloat freq02 = Strouhal;
8556 for(MInt k = 0; k < noEmbeddedBodies; k++) {
8557 // when using mu : has a dimension!
8558 // when using mu2 : dimensionless!
8559 mu[k] = freqFactor[k] * freq0 * F2 * PI;
8560 mu2[k] = freqFactor[k] * freq02 * F2 * PI;
8561 }
8562
8563 if(m_levelSetLb) {
8564 MFloat MaLb = Context::getSolverProperty<MFloat>("Ma", m_solverId, AT_);
8565 const MFloat referenceLengthLb = Context::getSolverProperty<MFloat>("referenceLengthLB", m_solverId, AT_);
8566 const MFloat freq02Lb = Strouhal * MaLb * LBCS / referenceLengthLb;
8567 for(MInt k = 0; k < noEmbeddedBodies; k++) {
8568 // when using mu2 : dimensionless!
8569 mu2[k] = freqFactor[k] * freq02Lb;
8570 }
8571 }
8572
8573 // if bodyMovementFunction is 6 or 7, adjust start and end angles:
8574 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8575 if(bodyToFunction[i] == 6 || bodyToFunction[i] == 7) {
8576 liftStartAngle1[i] = liftStartAngle1[i] * PI;
8577 liftEndAngle1[i] = liftEndAngle1[i] * PI - liftStartAngle1[i];
8578 }
8579 }
8580
8581 omega = freqFactor[body] * m_referenceVelocity * PI / (F2 * amplitude[body]);
8582
8583 if(Context::propertyExists("bodyTemperature", m_solverId)) {
8584 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8585 temperature[i] = Context::getSolverProperty<MFloat>("bodyTemperature", m_solverId, AT_, &temperature[i], i);
8586 }
8587 }
8588
8589 // read cotroll-point input data sizes
8590 MInt noControllFiles = 0;
8591 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8592 if(bodyToFunction[i] == 14) {
8593 noControllFiles++;
8594 }
8595 }
8596
8597 if(noControllFiles > 0) {
8598 mAlloc(m_forcedMotionInput, noEmbeddedBodies, "m_forcedMotionInput", AT_);
8599 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8600 m_forcedMotionInput[i].clear();
8601 }
8602
8603
8604 // read cotroll-point input data file
8605 for(MInt i = 0; i < noEmbeddedBodies; i++) {
8606 if(bodyToFunction[i] == 14) {
8607 ifstream readFile;
8608 MFloat coord = NAN;
8609 MFloat time = NAN;
8610
8611 stringstream filename;
8612 filename.clear();
8613 filename.str("");
8614 filename << "forcedMotion_" << i << ".txt";
8615
8616 readFile.open(filename.str(), ios_base::in);
8617
8618 if(!readFile) {
8619 mTerm(1, AT_, "Error reading forced motion input file!");
8620 }
8621 for(;;) { // read the forced motion file
8622
8623 if((readFile.rdstate() & ifstream::eofbit) != 0) {
8624 break;
8625 }
8626
8627 readFile >> time;
8628 readFile >> coord;
8629
8630 m_forcedMotionInput[i].insert(make_pair(time, coord));
8631 }
8632 readFile.close();
8633 }
8634 }
8635 }
8636
8637
8638 first = false;
8639 }
8640
8641 if((m_levelSetMb && !m_levelSetLb) || m_levelSetFv) {
8642 if(returnMode == 4) {
8643 bodyData[0] = temperature[body];
8644 return;
8645 }
8646
8647 //--------------------------------
8648
8649 switch(bodyToFunction[body]) {
8650 case 1: // cosine function
8651 {
8652 angle = mu[body] * elapsedTime - liftStartAngle1[body];
8653 switch(returnMode) {
8654 case 1: // return body center
8655 if(angle > liftEndAngle1[body]) angle = liftEndAngle1[body];
8656 if(angle > 0) {
8657 bodyData[0] = -amplitude[body] * cos(angle);
8658 bodyData[1] = F0;
8659 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8660 } else {
8661 bodyData[0] = -amplitude[body];
8662 bodyData[1] = F0;
8663 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8664 }
8665 break;
8666 case 2: // return body velocity
8667 if((angle > 0 && angle < liftEndAngle1[body])) {
8668 bodyData[0] = mu[body] * amplitude[body] * sin(angle);
8669 bodyData[1] = F0;
8670 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8671 } else {
8672 bodyData[0] = F0;
8673 bodyData[1] = F0;
8674 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8675 }
8676 break;
8677 case 3: // return body acceleration
8678 if((angle > 0 && angle < liftEndAngle1[body])) {
8679 bodyData[0] = mu[body] * mu[body] * amplitude[body] * cos(angle);
8680 bodyData[1] = F0;
8681 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8682 } else {
8683 bodyData[0] = F0;
8684 bodyData[1] = F0;
8685 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8686 }
8687 break;
8688 default:
8689 bodyData[0] = F0;
8690 bodyData[1] = F0;
8691 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8692 break;
8693 }
8694 break;
8695 }
8696 case 2: // valve lift shifted quadratic sine
8697 {
8698 angle = mu2[body] * elapsedTime;
8699
8700 switch(returnMode) {
8701 case 1: // return body center
8702 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8703 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8704 bodyData[0] = amplitude[body] * POW2(sin(mu2[body] * elapsedTime)) * normal[body * nDim + 0];
8705 bodyData[1] = amplitude[body] * POW2(sin(mu2[body] * elapsedTime)) * normal[body * nDim + 1];
8706 IF_CONSTEXPR(nDim == 3) {
8707 bodyData[2] = amplitude[body] * POW2(sin(mu2[body] * elapsedTime)) * normal[body * nDim + 2];
8708 }
8709 } else {
8710 bodyData[0] = F0;
8711 bodyData[1] = F0;
8712 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8713 }
8714 break;
8715 case 2: // return body velocity
8716 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8717 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8718 bodyData[0] = amplitude[body] * mu2[body] * sin(2 * mu2[body] * elapsedTime) * normal[body * nDim + 0];
8719 bodyData[1] = amplitude[body] * mu2[body] * sin(2 * mu2[body] * elapsedTime) * normal[body * nDim + 1];
8720 IF_CONSTEXPR(nDim == 3) {
8721 bodyData[2] = amplitude[body] * mu2[body] * sin(2 * mu2[body] * elapsedTime) * normal[body * nDim + 2];
8722 }
8723 } else {
8724 bodyData[0] = F0;
8725 bodyData[1] = F0;
8726 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8727 }
8728 break;
8729 case 3: // return body acceleration
8730 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8731 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8732 bodyData[0] = 2 * amplitude[body] * mu2[body] * mu2[body] * cos(2 * mu2[body] * elapsedTime)
8733 * normal[body * nDim + 0];
8734 bodyData[1] = 2 * amplitude[body] * mu2[body] * mu2[body] * cos(2 * mu2[body] * elapsedTime)
8735 * normal[body * nDim + 1];
8736 IF_CONSTEXPR(nDim == 3) {
8737 bodyData[2] = 2 * amplitude[body] * mu2[body] * mu2[body] * cos(2 * mu2[body] * elapsedTime)
8738 * normal[body * nDim + 2];
8739 }
8740 } else {
8741 bodyData[0] = 2 * amplitude[body] * mu2[body] * mu2[body] * normal[body * nDim + 0];
8742 bodyData[1] = 2 * amplitude[body] * mu2[body] * mu2[body] * normal[body * nDim + 1];
8743 IF_CONSTEXPR(nDim == 3) {
8744 bodyData[2] = 2 * amplitude[body] * mu2[body] * mu2[body] * normal[body * nDim + 2];
8745 }
8746 }
8747 break;
8748 default:
8749 bodyData[0] = F0;
8750 bodyData[1] = F0;
8751 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8752 break;
8753 }
8754
8755 break;
8756 }
8757 case 3: // piston movement
8758 {
8759 angle = mu2[body] * elapsedTime;
8760
8761 switch(returnMode) {
8762 case 1: // return body center
8763 if(elapsedTime > F0) {
8764 bodyData[0] = -amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 0];
8765 bodyData[1] = -amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 1];
8766 IF_CONSTEXPR(nDim == 3) {
8767 bodyData[2] = -amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 2];
8768 }
8769 } else {
8770 bodyData[0] = -amplitude[body] * normal[body * nDim + 0];
8771 bodyData[1] = -amplitude[body] * normal[body * nDim + 1];
8772 IF_CONSTEXPR(nDim == 3) { bodyData[2] = -amplitude[body] * normal[body * nDim + 2]; }
8773 }
8774 break;
8775 case 2: // return body velocity
8776 if(elapsedTime > F0) {
8777 bodyData[0] = mu2[body] * amplitude[body] * sin(mu2[body] * elapsedTime) * normal[body * nDim + 0];
8778 bodyData[1] = mu2[body] * amplitude[body] * sin(mu2[body] * elapsedTime) * normal[body * nDim + 1];
8779 IF_CONSTEXPR(nDim == 3) {
8780 bodyData[2] = mu2[body] * amplitude[body] * sin(mu2[body] * elapsedTime) * normal[body * nDim + 2];
8781 }
8782 } else {
8783 bodyData[0] = F0;
8784 bodyData[1] = F0;
8785 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8786 }
8787 break;
8788 case 3: // return body acceleration
8789 if(elapsedTime > F0) {
8790 bodyData[0] =
8791 mu2[body] * mu2[body] * amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 0];
8792 bodyData[1] =
8793 mu2[body] * mu2[body] * amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 1];
8794 IF_CONSTEXPR(nDim == 3) {
8795 bodyData[2] =
8796 mu2[body] * mu2[body] * amplitude[body] * cos(mu2[body] * elapsedTime) * normal[body * nDim + 2];
8797 }
8798 } else {
8799 bodyData[0] = F0;
8800 bodyData[1] = F0;
8801 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8802 }
8803 break;
8804 default:
8805 bodyData[0] = F0;
8806 bodyData[1] = F0;
8807 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8808 break;
8809 }
8810
8811 break;
8812 }
8813 case 4: // cosine function with normal
8814 {
8815 angle = mu2[body] * elapsedTime;
8816
8817 switch(returnMode) {
8818 case 1: // return body center
8819 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8820 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8821 bodyData[0] = amplitude[body] * cos(angle) * normal[body * nDim + 0];
8822 bodyData[1] = amplitude[body] * cos(angle) * normal[body * nDim + 1];
8823 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * cos(angle) * normal[body * nDim + 2]; }
8824 } else {
8825 bodyData[0] = amplitude[body] * normal[body * nDim + 0];
8826 bodyData[1] = amplitude[body] * normal[body * nDim + 1];
8827 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * normal[body * nDim + 2]; }
8828 }
8829 break;
8830 case 2: // return body velocity
8831 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8832 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8833 bodyData[0] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 0];
8834 bodyData[1] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 1];
8835 IF_CONSTEXPR(nDim == 3) {
8836 bodyData[2] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 2];
8837 }
8838 } else {
8839 bodyData[0] = F0;
8840 bodyData[1] = F0;
8841 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8842 }
8843 break;
8844 case 3: // return body acceleration
8845 if((angle > liftStartAngle1[body] && angle <= liftEndAngle1[body])
8846 || (angle > liftStartAngle2[body] && angle <= liftEndAngle2[body])) {
8847 bodyData[0] = -mu2[body] * mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 0];
8848 bodyData[1] = -mu2[body] * mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 1];
8849 IF_CONSTEXPR(nDim == 3) {
8850 bodyData[2] = -mu2[body] * mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 2];
8851 }
8852 } else {
8853 bodyData[0] = F0;
8854 bodyData[1] = F0;
8855 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8856 }
8857 break;
8858 default:
8859 bodyData[0] = F0;
8860 bodyData[1] = F0;
8861 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8862 break;
8863 }
8864 break;
8865 }
8866 case 5: // circular motion:
8867 {
8868 // initialBodyCenter: center of rotation
8869 // amplitude : radius
8870 // only 2d rotation implemented until now!
8871 angle = mu2[body] * elapsedTime + circleStartAngle[body];
8872
8873 switch(returnMode) {
8874 case 1: // return body center
8875 if(elapsedTime > F0) {
8876 bodyData[0] = amplitude[body] * cos(angle);
8877 bodyData[1] = amplitude[body] * sin(angle);
8878 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8879 } else {
8880 bodyData[0] = amplitude[body] * cos(circleStartAngle[body]);
8881 bodyData[1] = amplitude[body] * sin(circleStartAngle[body]);
8882 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8883 }
8884 break;
8885 case 2: // return body velocity
8886 if(elapsedTime > F0) {
8887 bodyData[0] = -amplitude[body] * sin(angle);
8888 bodyData[1] = amplitude[body] * cos(angle);
8889 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8890 } else {
8891 bodyData[0] = F0;
8892 bodyData[1] = F0;
8893 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8894 }
8895 break;
8896 case 3: // return body acceleration
8897 if(elapsedTime > F0) {
8898 bodyData[0] = -amplitude[body] * cos(angle);
8899 bodyData[1] = -amplitude[body] * sin(angle);
8900 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8901 } else {
8902 bodyData[0] = F0;
8903 bodyData[1] = F0;
8904 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8905 }
8906 break;
8907 default:
8908 bodyData[0] = F0;
8909 bodyData[1] = F0;
8910 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8911 break;
8912 }
8913 break;
8914 }
8915 case 6: // simplified piston motion
8916 {
8917 angle = omega * elapsedTime - liftStartAngle1[body];
8918 if(angle > liftEndAngle1[body]) angle = F0;
8919
8920 switch(returnMode) {
8921 case 1: // return body center
8922 if(elapsedTime > F0) {
8923 bodyData[0] = -amplitude[body] * cos(angle) * normal[body * nDim + 0];
8924 bodyData[1] = -amplitude[body] * cos(angle) * normal[body * nDim + 1];
8925 IF_CONSTEXPR(nDim == 3) { bodyData[2] = -amplitude[body] * cos(angle) * normal[body * nDim + 2]; }
8926 } else {
8927 bodyData[0] = -amplitude[body] * normal[body * nDim + 0];
8928 bodyData[1] = -amplitude[body] * normal[body * nDim + 1];
8929 IF_CONSTEXPR(nDim == 3) { bodyData[2] = -amplitude[body] * normal[body * nDim + 2]; }
8930 }
8931 break;
8932 case 2: // return body velocity
8933 if(elapsedTime > F0) {
8934 bodyData[0] = omega * amplitude[body] * sin(angle) * normal[body * nDim + 0];
8935 bodyData[1] = omega * amplitude[body] * sin(angle) * normal[body * nDim + 1];
8936 IF_CONSTEXPR(nDim == 3) { bodyData[2] = omega * amplitude[body] * sin(angle) * normal[body * nDim + 2]; }
8937 } else {
8938 bodyData[0] = F0;
8939 bodyData[1] = F0;
8940 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8941 }
8942 break;
8943 case 3: // return body acceleration
8944 if(elapsedTime > F0) {
8945 bodyData[0] = omega * omega * amplitude[body] * cos(angle) * normal[body * nDim + 0];
8946 bodyData[1] = omega * omega * amplitude[body] * cos(angle) * normal[body * nDim + 1];
8947 IF_CONSTEXPR(nDim == 3) {
8948 bodyData[2] = omega * omega * amplitude[body] * cos(angle) * normal[body * nDim + 2];
8949 }
8950 } else {
8951 bodyData[0] = F0;
8952 bodyData[1] = F0;
8953 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8954 }
8955 break;
8956 default:
8957 bodyData[0] = F0;
8958 bodyData[1] = F0;
8959 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8960 break;
8961 }
8962
8963
8964 break;
8965 }
8966 case 7: // valve lift shifted quadratic sine matching piston motion 6
8967 {
8968 angle = omega * elapsedTime - liftStartAngle1[body];
8969 if(angle > liftEndAngle1[body]) angle = F0;
8970
8971 switch(returnMode) {
8972 case 1: // return body center
8973 if(angle > F0) {
8974 bodyData[0] = amplitude[body] * POW2(sin(angle)) * normal[body * nDim + 0];
8975 bodyData[1] = amplitude[body] * POW2(sin(angle)) * normal[body * nDim + 1];
8976 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * POW2(sin(angle)) * normal[body * nDim + 2]; }
8977 } else {
8978 bodyData[0] = 0;
8979 bodyData[1] = 0;
8980 IF_CONSTEXPR(nDim == 3) bodyData[2] = 0;
8981 }
8982 break;
8983 case 2: // return body velocity
8984 if(angle > F0) {
8985 bodyData[0] = amplitude[body] * omega * sin(2 * angle) * normal[body * nDim + 0];
8986 bodyData[1] = amplitude[body] * omega * sin(2 * angle) * normal[body * nDim + 1];
8987 IF_CONSTEXPR(nDim == 3) {
8988 bodyData[2] = amplitude[body] * omega * sin(2 * angle) * normal[body * nDim + 2];
8989 }
8990 } else {
8991 bodyData[0] = F0;
8992 bodyData[1] = F0;
8993 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
8994 }
8995 break;
8996 case 3: // return body acceleration
8997 if(angle > F0) {
8998 bodyData[0] = 2 * amplitude[body] * omega * omega * cos(2 * angle) * normal[body * nDim + 0];
8999 bodyData[1] = 2 * amplitude[body] * omega * omega * cos(2 * angle) * normal[body * nDim + 1];
9000 IF_CONSTEXPR(nDim == 3) {
9001 bodyData[2] = 2 * amplitude[body] * omega * omega * cos(2 * angle) * normal[body * nDim + 2];
9002 }
9003 } else {
9004 bodyData[0] = 2 * amplitude[body] * omega * omega * normal[body * nDim + 0];
9005 bodyData[1] = 2 * amplitude[body] * omega * omega * normal[body * nDim + 1];
9006 IF_CONSTEXPR(nDim == 3) { bodyData[2] = 2 * amplitude[body] * omega * omega * normal[body * nDim + 2]; }
9007 }
9008 break;
9009 default:
9010 bodyData[0] = F0;
9011 bodyData[1] = F0;
9012 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9013 break;
9014 }
9015
9016 break;
9017 }
9018 case 8: // translational movement in normal-direction with constant Ma-number (Ma_trans)
9019 {
9020 // Ma_trans is directly given by the amplitude-factor for each body!
9021 // The body velocity is then based on the free-stream speed of sound.
9022 switch(returnMode) {
9023 case 1: // return body center
9024 bodyData[0] = amplitude[body] * m_referenceVelocity * elapsedTime * normal[body * nDim + 0];
9025 bodyData[1] = amplitude[body] * m_referenceVelocity * elapsedTime * normal[body * nDim + 1];
9026 IF_CONSTEXPR(nDim == 3) {
9027 bodyData[2] = amplitude[body] * m_referenceVelocity * elapsedTime * normal[body * nDim + 2];
9028 }
9029 break;
9030 case 2: // return body velocity
9031 bodyData[0] = amplitude[body] * m_referenceVelocity * normal[body * nDim + 0];
9032 bodyData[1] = amplitude[body] * m_referenceVelocity * normal[body * nDim + 1];
9033 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * m_referenceVelocity * normal[body * nDim + 2]; }
9034 break;
9035 case 3: // return body acceleration
9036 bodyData[0] = F0;
9037 bodyData[1] = F0;
9038 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9039 break;
9040
9041 default:
9042 bodyData[0] = F0;
9043 bodyData[1] = F0;
9044 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9045 break;
9046 }
9047 break;
9048 }
9049 case 9: // sine function with normel (=> periodic motion around the initialBodyCenter!)
9050 {
9051 angle = mu2[body] * elapsedTime;
9052
9053 switch(returnMode) {
9054 case 1: // return body center
9055 if(angle >= liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9056 bodyData[0] = amplitude[body] * sin(angle) * normal[body * nDim + 0];
9057 bodyData[1] = amplitude[body] * sin(angle) * normal[body * nDim + 1];
9058 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * sin(angle) * normal[body * nDim + 2]; }
9059 } else if(angle < liftStartAngle1[body]) {
9060 bodyData[0] = 0;
9061 bodyData[1] = 0;
9062 IF_CONSTEXPR(nDim == 3) bodyData[2] = 0;
9063 } else if(angle > liftEndAngle1[body]) {
9064 bodyData[0] = amplitude[body] * sin(liftEndAngle1[body]) * normal[body * nDim + 0];
9065 bodyData[1] = amplitude[body] * sin(liftEndAngle1[body]) * normal[body * nDim + 1];
9066 IF_CONSTEXPR(nDim == 3) {
9067 bodyData[2] = amplitude[body] * sin(liftEndAngle1[body]) * normal[body * nDim + 2];
9068 }
9069 }
9070 break;
9071 case 2: // return body velocity
9072 if(angle > liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9073 bodyData[0] = mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 0];
9074 bodyData[1] = mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 1];
9075 IF_CONSTEXPR(nDim == 3) {
9076 bodyData[2] = mu2[body] * amplitude[body] * cos(angle) * normal[body * nDim + 2];
9077 }
9078 } else {
9079 bodyData[0] = F0;
9080 bodyData[1] = F0;
9081 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9082 }
9083 break;
9084 case 3: // return body acceleration
9085 if(angle > liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9086 bodyData[0] = -mu2[body] * mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 0];
9087 bodyData[1] = -mu2[body] * mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 1];
9088 IF_CONSTEXPR(nDim == 3) {
9089 bodyData[2] = -mu2[body] * mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 2];
9090 }
9091 } else {
9092 bodyData[0] = F0;
9093 bodyData[1] = F0;
9094 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9095 }
9096 break;
9097 default:
9098 bodyData[0] = F0;
9099 bodyData[1] = F0;
9100 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9101 break;
9102 }
9103 break;
9104 }
9105 case 10: // piston motion equation:
9106 {
9107 // reference coordincate system is the cylindeer head!
9108 // l : rod length
9109 // r : crank radius
9110 // TDC : distance at TDC from the cylinder head
9111 // normal : motion normal
9112 // phi : crank angle in radian
9113
9114 const MFloat l = liftStartAngle1[body];
9115 const MFloat TDC = liftEndAngle1[body];
9116 const MFloat r = amplitude[body];
9117
9118 const MFloat phi = crankAngle(elapsedTime, 1);
9119
9120 switch(returnMode) {
9121 case 1: // return body center
9122 bodyData[0] =
9123 normal[body * nDim + 0] * (l + r + TDC - (r * cos(phi) + sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))));
9124 bodyData[1] =
9125 normal[body * nDim + 1] * (l + r + TDC - (r * cos(phi) + sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))));
9126 IF_CONSTEXPR(nDim == 3) {
9127 bodyData[2] =
9128 normal[body * nDim + 2] * (l + r + TDC - (r * cos(phi) + sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))));
9129 }
9130
9131 if(domainId() == 0 && printPosition) {
9132 const MFloat cad = crankAngle(time(), 0);
9133 cerr << "Crank-angle-degree : " << cad << endl;
9134 if((cad / 45) > 0.989 && (cad / 45) < 1.01) {
9135 cerr << "Physical-Time : " << time() << endl;
9136 cerr << " " << time() * 0.002898783653689 << endl;
9137 }
9138 cerr << "Piston-position : "
9139 << (l + r + TDC - (r * cos(phi) + sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))) << " in m "
9140 << bodyData[1] * 0.075 << endl;
9141 cerr << "Piston-velocity : "
9142 << mu2[body]
9143 * (r * sin(phi)
9144 + (POW2(r) * sin(phi) * cos(phi) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))))
9145 << endl;
9146 }
9147
9148 break;
9149 case 2: // return body velocity
9150 bodyData[0] =
9151 normal[body * nDim + 0] * mu2[body]
9152 * (r * sin(phi) + (POW2(r) * sin(phi) * cos(phi) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9153
9154 bodyData[1] =
9155 normal[body * nDim + 1] * mu2[body]
9156 * (r * sin(phi) + (POW2(r) * sin(phi) * cos(phi) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9157 IF_CONSTEXPR(nDim == 3) {
9158 bodyData[2] =
9159 normal[body * nDim + 2] * mu2[body]
9160 * (r * sin(phi) + (POW2(r) * sin(phi) * cos(phi) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9161 }
9162 break;
9163 case 3: // return body acceleration
9164 bodyData[0] =
9165 normal[body * nDim + 0] * mu2[body] * mu2[body]
9166 * (r * cos(phi)
9167 + (POW2(r) * (POW2(cos(phi)) - POW2(sin(phi))) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))))
9168 + (POW4(r) * POW2(sin(phi)) * POW2(cos(phi))) / POW3((sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9169 bodyData[1] =
9170 normal[body * nDim + 1] * mu2[body] * mu2[body]
9171 * (r * cos(phi)
9172 + (POW2(r) * (POW2(cos(phi)) - POW2(sin(phi))) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))))
9173 + (POW4(r) * POW2(sin(phi)) * POW2(cos(phi))) / (POW3(sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9174 IF_CONSTEXPR(nDim == 3) {
9175 bodyData[2] =
9176 normal[body * nDim + 2] * mu2[body] * mu2[body]
9177 * (r * cos(phi)
9178 + (POW2(r) * (POW2(cos(phi)) - POW2(sin(phi))) / (sqrt(POW2(l) - POW2(r) * POW2(sin(phi)))))
9179 + (POW4(r) * POW2(sin(phi)) * POW2(cos(phi))) / (POW3(sqrt(POW2(l) - POW2(r) * POW2(sin(phi))))));
9180 }
9181 break;
9182 default:
9183 bodyData[0] = F0;
9184 bodyData[1] = F0;
9185 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9186 }
9187 break;
9188 }
9189 case 11: // valve motion for single-valve engine:
9190 {
9191 // reference coordincate system is the cylindeer head!
9192 // L : maximum valve lift (2*amplitude[body])
9193 // normal : motion normal
9194 // phi : crank angle in radian
9195 // cad : crank angle degree
9196 // maxNoCycles : maximum number of considered cycles
9197
9198
9199 const MFloat cad = crankAngle(elapsedTime, 0);
9200
9201 MFloat IO = liftStartAngle1[body];
9202 MFloat IC = liftEndAngle1[body];
9203 MFloat EO = liftStartAngle2[body];
9204 MFloat EC = liftEndAngle2[body];
9205
9206 // possible values are:
9207 // IO: -3 // CAD BTDC 3
9208 // IC: 180+47 // CAD ABDC 47
9209 // EO: 3*180-47; // CAD BBDC 47
9210 // EC: 720+3; // CAD ATDC 3
9211
9212 switch(returnMode) {
9213 case 1: // return body center
9214 if(cad < IO) {
9215 bodyData[0] = F0;
9216 bodyData[1] = F0;
9217 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9218 } else if(cad >= 0 && cad < IC) {
9219 MFloat phi_i = (cad - IO) * PI / 180;
9220 MFloat delta_i = (IC - IO) * PI / 180;
9221 MFloat freq_i = 1 / (delta_i / 2 / PI);
9222 MFloat phase = -PI / 2;
9223
9224 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq_i * phi_i - phase));
9225 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq_i * phi_i - phase));
9226 IF_CONSTEXPR(nDim == 3) {
9227 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq_i * phi_i - phase));
9228 }
9229
9230 } else if(cad > IC && cad < EO) {
9231 bodyData[0] = F0;
9232 bodyData[1] = F0;
9233 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9234 } else if(cad >= EO && cad < EC) {
9235 MFloat phi_e = (cad - EO) * PI / 180;
9236 MFloat delta_e = (EC - EO) * PI / 180;
9237 MFloat freq_e = 1 / (delta_e / 2 / PI);
9238 MFloat phase = -PI / 2;
9239
9240 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq_e * phi_e - phase));
9241 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq_e * phi_e - phase));
9242 IF_CONSTEXPR(nDim == 3) {
9243 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq_e * phi_e - phase));
9244 }
9245
9246 } else if(cad >= EC) {
9247 bodyData[0] = F0;
9248 bodyData[1] = F0;
9249 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9250 } else {
9251 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9252 }
9253
9254 if(domainId() == 0 && printPosition) {
9255 cerr << "Crank-angle-degree : " << cad << endl;
9256 cerr << "Valve-position : " << bodyData[0] << " in mm" << bodyData[0] * 75 << endl;
9257 }
9258
9259 break;
9260 case 2: // return body velocity
9261 if(cad < IO) {
9262 bodyData[0] = F0;
9263 bodyData[1] = F0;
9264 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9265 } else if(cad >= 0 && cad < IC) {
9266 MFloat phi_i = (cad - IO) * PI / 180;
9267 MFloat delta_i = (IC - IO) * PI / 180;
9268 MFloat freq_i = 1 / (delta_i / 2 / PI);
9269 MFloat phase = -PI / 2;
9270
9271 bodyData[0] =
9272 -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq_i * cos(freq_i * phi_i - phase);
9273 bodyData[1] =
9274 -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq_i * cos(freq_i * phi_i - phase);
9275 IF_CONSTEXPR(nDim == 3) {
9276 bodyData[2] =
9277 -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq_i * cos(freq_i * phi_i - phase);
9278 }
9279
9280 } else if(cad > IC && cad < EO) {
9281 bodyData[0] = F0;
9282 bodyData[1] = F0;
9283 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9284 } else if(cad >= EO && cad < EC) {
9285 MFloat phi_e = (cad - EO) * PI / 180;
9286 MFloat delta_e = (EC - EO) * PI / 180;
9287 MFloat freq_e = 1 / (delta_e / 2 / PI);
9288 MFloat phase = -PI / 2;
9289
9290 bodyData[0] =
9291 -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq_e * cos(freq_e * phi_e - phase);
9292 bodyData[1] =
9293 -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq_e * cos(freq_e * phi_e - phase);
9294 IF_CONSTEXPR(nDim == 3) {
9295 bodyData[2] =
9296 -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq_e * cos(freq_e * phi_e - phase);
9297 }
9298 } else if(cad >= EC) {
9299 bodyData[0] = F0;
9300 bodyData[1] = F0;
9301 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9302 } else {
9303 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9304 }
9305
9306 if(domainId() == 0 && printPosition) {
9307 cerr << "Valve-velocity : " << bodyData[0] << endl;
9308 }
9309
9310 break;
9311 case 3: // return body acceleration
9312 if(cad < IO) {
9313 bodyData[0] = F0;
9314 bodyData[1] = F0;
9315 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9316 } else if(cad >= 0 && cad < IC) {
9317 MFloat phi_i = (cad - IO) * PI / 180;
9318 MFloat delta_i = (IC - IO) * PI / 180;
9319 MFloat freq_i = 1 / (delta_i / 2 / PI);
9320 MFloat phase = -PI / 2;
9321
9322 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_i)
9323 * sin(freq_i * phi_i - phase);
9324 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_i)
9325 * sin(freq_i * phi_i - phase);
9326 IF_CONSTEXPR(nDim == 3) {
9327 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_i)
9328 * sin(freq_i * phi_i - phase);
9329 }
9330
9331 } else if(cad > IC && cad < EO) {
9332 bodyData[0] = F0;
9333 bodyData[1] = F0;
9334 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9335 } else if(cad >= EO && cad < EC) {
9336 MFloat phi_e = (cad - EO) * PI / 180;
9337 MFloat delta_e = (EC - EO) * PI / 180;
9338 MFloat freq_e = 1 / (delta_e / 2 / PI);
9339 MFloat phase = -PI / 2;
9340
9341 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_e)
9342 * sin(freq_e * phi_e - phase);
9343 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_e)
9344 * sin(freq_e * phi_e - phase);
9345 IF_CONSTEXPR(nDim == 3) {
9346 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq_e)
9347 * sin(freq_e * phi_e - phase);
9348 }
9349 } else if(cad > EC) {
9350 bodyData[0] = F0;
9351 bodyData[1] = F0;
9352 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9353 } else {
9354 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9355 }
9356 break;
9357 default:
9358 bodyData[0] = F0;
9359 bodyData[1] = F0;
9360 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9361 }
9362 break;
9363 }
9364 case 12: // valve motion for inlet valve:
9365 {
9366 // reference coordincate system is the cylindeer head!
9367 // amplitude : dimensionless maximum valve lift
9368 // normal : normalised motion normal
9369 // phi : crank angle in radian
9370 // cad : crank angle degree
9371 // maxNoCycles : maximum number of considered cycles
9372
9373 const MFloat cad = crankAngle(elapsedTime, 0);
9374
9375 MFloat scaleToMeter = 0.075;
9376
9377 // valve-timing in crank-angle-degree
9378
9379 MFloat IO = liftStartAngle1[body];
9380 MFloat IC = liftEndAngle1[body];
9381
9382 // possible values are:
9383 // IO: -24 // 24 CAD BTDC
9384 // IC: 232 // CAD ATDC
9385
9386 MFloat phi = 0;
9387 MFloat delta = -1;
9388 MFloat freq = 0;
9389 MFloat phase = -PI / 2;
9390
9391 switch(returnMode) {
9392 case 1: // return body center
9393 if(cad < IO) {
9394 bodyData[0] = F0;
9395 bodyData[1] = F0;
9396 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9397 } else if(cad >= IO && cad <= IC) {
9398 phi = (cad - IO) * PI / 180;
9399 delta = (IC - IO) * PI / 180;
9400 freq = 1 / (delta / 2 / PI);
9401 phase = -PI / 2;
9402
9403 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq * phi - phase));
9404 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq * phi - phase));
9405 IF_CONSTEXPR(nDim == 3) {
9406 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq * phi - phase));
9407 }
9408
9409 } else if(cad >= 720 + IO) {
9410 phi = (cad - (720 + IO)) * PI / 180;
9411 delta = (IC - IO) * PI / 180;
9412 freq = 1 / (delta / 2 / PI);
9413 phase = -PI / 2;
9414
9415 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq * phi - phase));
9416 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq * phi - phase));
9417 IF_CONSTEXPR(nDim == 3) {
9418 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq * phi - phase));
9419 }
9420
9421 } else if(cad >= IC && cad < 720 + IO) {
9422 bodyData[0] = F0;
9423 bodyData[1] = F0;
9424 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9425 } else {
9426 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9427 }
9428
9429 if(domainId() == 0 && printPosition) {
9430 cerr << "Crank-angle-degree : " << cad << endl;
9431 cerr << "dimensionless-Inlet-Valve-position : " << amplitude[body] * (1 - sin(freq * phi - phase))
9432 << endl;
9433 cerr << "dimensional-Inlet-Valve-position : "
9434 << amplitude[body] * (1 - sin(freq * phi - phase)) * scaleToMeter << " in m " << endl;
9435 cerr << "dimensionless-Inlet-Valve-velocity : "
9436 << -amplitude[body] * mu2[body] * freq * cos(freq * phi - phase) << endl;
9437 }
9438
9439 break;
9440 case 2: // return body velocity
9441 if(cad < IO) {
9442 bodyData[0] = F0;
9443 bodyData[1] = F0;
9444 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9445 } else if(cad >= IO && cad <= IC) {
9446 phi = (cad - IO) * PI / 180;
9447 delta = (IC - IO) * PI / 180;
9448 freq = 1 / (delta / 2 / PI);
9449 phase = -PI / 2;
9450
9451 bodyData[0] = -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9452 bodyData[1] = -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9453 IF_CONSTEXPR(nDim == 3) {
9454 bodyData[2] = -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9455 }
9456
9457 } else if(cad >= 720 + IO) {
9458 phi = (cad - (720 + IO)) * PI / 180;
9459 delta = (IC - IO) * PI / 180;
9460 freq = 1 / (delta / 2 / PI);
9461 phase = -PI / 2;
9462
9463 bodyData[0] = -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9464 bodyData[1] = -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9465 IF_CONSTEXPR(nDim == 3) {
9466 bodyData[2] = -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9467 }
9468
9469 } else if(cad >= IC && cad < 720 + IO) {
9470 bodyData[0] = F0;
9471 bodyData[1] = F0;
9472 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9473 } else {
9474 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9475 }
9476
9477 break;
9478 case 3: // return body acceleration
9479 if(cad < IO) {
9480 bodyData[0] = F0;
9481 bodyData[1] = F0;
9482 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9483 } else if(cad >= IO && cad <= IC) {
9484 phi = (cad - IO) * PI / 180;
9485 delta = (IC - IO) * PI / 180;
9486 freq = 1 / (delta / 2 / PI);
9487 phase = -PI / 2;
9488
9489 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9490 * sin(freq * phi - phase);
9491 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9492 * sin(freq * phi - phase);
9493 IF_CONSTEXPR(nDim == 3) {
9494 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9495 * sin(freq * phi - phase);
9496 }
9497
9498 } else if(cad >= 720 + IO) {
9499 phi = (cad - (720 + IO)) * PI / 180;
9500 delta = (IC - IO) * PI / 180;
9501 freq = 1 / (delta / 2 / PI);
9502 phase = -PI / 2;
9503
9504 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9505 * sin(freq * phi - phase);
9506 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9507 * sin(freq * phi - phase);
9508 IF_CONSTEXPR(nDim == 3) {
9509 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9510 * sin(freq * phi - phase);
9511 }
9512
9513 } else if(cad >= IC && cad < 720 + IO) {
9514 bodyData[0] = F0;
9515 bodyData[1] = F0;
9516 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9517 } else {
9518 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9519 }
9520 break;
9521 default:
9522 bodyData[0] = F0;
9523 bodyData[1] = F0;
9524 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9525 }
9526 break;
9527 }
9528 case 13: // valve motion for outlet valve:
9529 {
9530 // reference coordincate system is the cylindeer head!
9531 // amplitude : dimensionless maximum valve lift
9532 // normal : motion normal
9533 // phi : crank angle in radian
9534 // cad : crank angle degree
9535 // maxNoCycles : maximum number of considered cycles
9536 const MFloat cad = crankAngle(elapsedTime, 0);
9537
9538 // valve-timing in crank-angle-degree
9539
9540 MFloat EO = liftStartAngle1[body];
9541 MFloat EC = liftEndAngle1[body];
9542 MFloat scaleToMeter = 0.075;
9543
9544 // possible values are:
9545 // EO: 480; // CAD ATDC
9546 // EC: 16; // CAD ATDC
9547
9548 MFloat phi = 0;
9549 MFloat delta = -1;
9550 MFloat freq = 0;
9551 MFloat phase = -PI / 2;
9552
9553 switch(returnMode) {
9554 case 1: // return body center
9555 if(cad < EO && cad >= EC) {
9556 bodyData[0] = F0;
9557 bodyData[1] = F0;
9558 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9559 } else if(cad >= EO && cad < 720) {
9560 phi = (cad - EO) * PI / 180;
9561 delta = (720 + EC - EO) * PI / 180;
9562 freq = 1 / (delta / 2 / PI);
9563 phase = -PI / 2;
9564
9565 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq * phi - phase));
9566 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq * phi - phase));
9567 IF_CONSTEXPR(nDim == 3) {
9568 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq * phi - phase));
9569 }
9570
9571 } else if(cad < EC) {
9572 phi = -(EC - cad) * PI / 180;
9573 delta = (720 + EC - EO) * PI / 180;
9574 freq = 1 / (delta / 2 / PI);
9575 phase = -PI / 2;
9576
9577 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * (1 - sin(freq * phi - phase));
9578 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * (1 - sin(freq * phi - phase));
9579 IF_CONSTEXPR(nDim == 3) {
9580 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * (1 - sin(freq * phi - phase));
9581 }
9582
9583 } else {
9584 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9585 }
9586
9587 if(domainId() == 0 && printPosition) {
9588 cerr << "Crank-angle-degree : " << cad << endl;
9589 cerr << "dimensionless-Outlet-Valve-position : " << amplitude[body] * (1 - sin(freq * phi - phase))
9590 << endl;
9591 cerr << "dimensional-Outlet-Valve-position : "
9592 << amplitude[body] * (1 - sin(freq * phi - phase)) * scaleToMeter << " in m " << endl;
9593 cerr << "dimensionless-Outlet-Valve-velocity : "
9594 << -amplitude[body] * mu2[body] * freq * cos(freq * phi - phase) << endl;
9595 }
9596
9597 break;
9598 case 2: // return body velocity
9599 if(cad < EO && cad >= EC) {
9600 bodyData[0] = F0;
9601 bodyData[1] = F0;
9602 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9603 } else if(cad >= EO && cad < 720) {
9604 phi = (cad - EO) * PI / 180;
9605 delta = (720 + EC - EO) * PI / 180;
9606 freq = 1 / (delta / 2 / PI);
9607 phase = -PI / 2;
9608
9609 bodyData[0] = -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9610 bodyData[1] = -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9611 IF_CONSTEXPR(nDim == 3) {
9612 bodyData[2] = -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9613 }
9614
9615
9616 } else if(cad < EC) {
9617 phi = -(EC - cad) * PI / 180;
9618 delta = (720 + EC - EO) * PI / 180;
9619 freq = 1 / (delta / 2 / PI);
9620 phase = -PI / 2;
9621
9622 bodyData[0] = -normal[body * nDim + 0] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9623 bodyData[1] = -normal[body * nDim + 1] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9624 IF_CONSTEXPR(nDim == 3) {
9625 bodyData[2] = -normal[body * nDim + 2] * amplitude[body] * mu2[body] * freq * cos(freq * phi - phase);
9626 }
9627 } else {
9628 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9629 }
9630
9631 break;
9632 case 3: // return body acceleration
9633 if(cad < EO && cad >= EC) {
9634 bodyData[0] = F0;
9635 bodyData[1] = F0;
9636 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9637 } else if(cad >= EO && cad < 720) {
9638 phi = (cad - EO) * PI / 180;
9639 delta = (720 + EC - EO) * PI / 180;
9640 freq = 1 / (delta / 2 / PI);
9641 phase = -PI / 2;
9642
9643 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9644 * sin(freq * phi - phase);
9645 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9646 * sin(freq * phi - phase);
9647 IF_CONSTEXPR(nDim == 3) {
9648 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9649 * sin(freq * phi - phase);
9650 }
9651
9652 } else if(cad < EC) {
9653 phi = -(EC - cad) * PI / 180;
9654 delta = (720 + EC - EO) * PI / 180;
9655 freq = 1 / (delta / 2 / PI);
9656 phase = -PI / 2;
9657
9658 bodyData[0] = normal[body * nDim + 0] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9659 * sin(freq * phi - phase);
9660 bodyData[1] = normal[body * nDim + 1] * amplitude[body] * mu2[body] * mu2[body] * POW2(freq)
9661 * sin(freq * phi - phase);
9662 IF_CONSTEXPR(nDim == 3) {
9663 bodyData[2] = normal[body * nDim + 2] * amplitude[body] * mu2[body] * mu2[body]
9664 * (1 + POW2(freq) * sin(freq * phi - phase));
9665 }
9666 } else {
9667 mTerm(1, AT_, "Unexpected crank-angle-degree!");
9668 }
9669 break;
9670 default:
9671 bodyData[0] = F0;
9672 bodyData[1] = F0;
9673 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9674 }
9675 break;
9676 }
9677 case 14: // liniear interpolation between controll-points
9678 {
9679 // for defined motion along motion normal and position(time) input from file
9680 // using linear interpolation to get the position and
9681 // left-sided-stencil to get velocity and acceleration
9682 // note: the stencil was choosen intuitively and any other might work as well.
9683 auto upperIt = upper_bound(m_forcedMotionInput[body].begin(), m_forcedMotionInput[body].end(),
9684 make_pair(elapsedTime, -999999.9));
9685
9686 auto lowerIt = next(upperIt, -1);
9687
9688 // linear interpolation between controll-points
9689 const MFloat pos = (*lowerIt).second
9690 + (elapsedTime - (*lowerIt).first) * ((*upperIt).second - (*lowerIt).second)
9691 / ((*upperIt).first - (*lowerIt).first);
9692
9693
9694 if(domainId() == 0 && returnMode == 1 && printPosition) {
9695 cerr << globalTimeStep << " body " << body << " time " << elapsedTime << " earlier " << (*lowerIt).first
9696 << " later " << (*upperIt).first << " earlier Pos " << (*lowerIt).second << " later Pos "
9697 << (*upperIt).second << " interp. Pos " << pos << endl;
9698 }
9699
9700
9701 switch(returnMode) {
9702 case 1: // return body center
9703 {
9704 bodyData[0] = normal[body * nDim + 0] * pos;
9705 bodyData[1] = normal[body * nDim + 1] * pos;
9706 IF_CONSTEXPR(nDim == 3) { bodyData[2] = normal[body * nDim + 2] * pos; }
9707 break;
9708 }
9709 case 2: // return body velocity
9710 {
9711 // get previous position for left-sided time gradient
9712 MFloat prevTime = elapsedTime - timeStep();
9713 if(globalTimeStep <= 0) prevTime = 0;
9714 upperIt = upper_bound(m_forcedMotionInput[body].begin(), m_forcedMotionInput[body].end(),
9715 make_pair(prevTime, -999999.9));
9716 lowerIt = next(upperIt, -1);
9717
9718 const MFloat prevPos = (*lowerIt).second
9719 + (prevTime - (*lowerIt).first) * ((*upperIt).second - (*lowerIt).second)
9720 / ((*upperIt).first - (*lowerIt).first);
9721 MFloat vel = (pos - prevPos) / timeStep();
9722 if(globalTimeStep <= 0) vel = 0;
9723
9724 bodyData[0] = normal[body * nDim + 0] * vel;
9725 bodyData[1] = normal[body * nDim + 1] * vel;
9726 IF_CONSTEXPR(nDim == 3) { bodyData[2] = normal[body * nDim + 2] * vel; }
9727
9728 break;
9729 }
9730 case 3: // return body acceleration
9731 {
9732 // get previous and older position for left-sided time gradient
9733 MFloat prevTime = elapsedTime - timeStep();
9734 if(globalTimeStep <= 0) prevTime = 0;
9735
9736
9737 upperIt = upper_bound(m_forcedMotionInput[body].begin(), m_forcedMotionInput[body].end(),
9738 make_pair(prevTime, -999999.9));
9739 lowerIt = next(upperIt, -1);
9740
9741 const MFloat prevPos = (*lowerIt).second
9742 + (prevTime - (*lowerIt).first) * ((*upperIt).second - (*lowerIt).second)
9743 / ((*upperIt).first - (*lowerIt).first);
9744
9745
9746 MFloat olderTime = elapsedTime - 2 * timeStep();
9747 if(globalTimeStep <= 0) olderTime = 0;
9748 upperIt = upper_bound(m_forcedMotionInput[body].begin(), m_forcedMotionInput[body].end(),
9749 make_pair(olderTime, -999999.9));
9750 lowerIt = next(upperIt, -1);
9751
9752
9753 const MFloat olderPos = (*lowerIt).second
9754 + (olderTime - (*lowerIt).first) * ((*upperIt).second - (*lowerIt).second)
9755 / ((*upperIt).first - (*lowerIt).first);
9756 MFloat a = (pos - 2 * prevPos + olderPos) / (timeStep() * timeStep());
9757 if(globalTimeStep <= 0) a = 0;
9758
9759 bodyData[0] = normal[body * nDim + 0] * a;
9760 bodyData[1] = normal[body * nDim + 1] * a;
9761 IF_CONSTEXPR(nDim == 3) { bodyData[2] = normal[body * nDim + 2] * a; }
9762
9763 break;
9764 }
9765 default:
9766 bodyData[0] = F0;
9767 bodyData[1] = F0;
9768 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9769 break;
9770 }
9771 break;
9772 }
9773 default:
9774 mTerm(1, AT_, "function type not implemented. Please check bodyMovementFunctions property!");
9775 }
9776
9777 // add the initialBodyCenter to the bodyDato for the body-positioning:
9778 if(returnMode == 1) {
9779 for(MInt dir = 0; dir < nDim; dir++) {
9780 bodyData[dir] += initialBodyCenter[body * nDim + dir];
9781 }
9782 }
9783
9784 // rotate the final result around the z-axis
9785 if(rotAngle > 0 || rotAngle < 0) {
9786 MFloat tmp0 = bodyData[0] * cos(rotAngle) + bodyData[1] * sin(rotAngle);
9787 MFloat tmp1 = bodyData[1] * cos(rotAngle) - bodyData[0] * sin(rotAngle);
9788 bodyData[0] = tmp0;
9789 bodyData[1] = tmp1;
9790 bodyData[2] = bodyData[2];
9791 }
9792 if(m_periodicMovement) {
9793 MFloat bodyTempData = bodyData[m_periodicDirection];
9794 bodyData[m_periodicDirection] =
9795 std::fmod(bodyTempData + initialBodyCenter[body * nDim + m_periodicDirection] + 0.5 * m_periodicDistance,
9796 m_periodicDistance)
9797 - 0.5 * m_periodicDistance - initialBodyCenter[body * nDim + m_periodicDirection];
9798 }
9799 } else if(m_levelSetLb) {
9800 switch(bodyToFunction[body]) {
9801 case 1: {
9802 // translational movement in normal-direction with constant velocity
9803 angle = c_cellLengthAtLevel(maxLevel());
9804 switch(returnMode) {
9805 case 1: // return body center
9806 bodyData[0] = amplitude[body] * angle * elapsedTime * normal[body * nDim + 0];
9807 bodyData[1] = amplitude[body] * angle * elapsedTime * normal[body * nDim + 1];
9808 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * angle * elapsedTime * normal[body * nDim + 2]; }
9809 break;
9810 case 2: // return body velocity
9811 bodyData[0] = amplitude[body] * normal[body * nDim + 0];
9812 bodyData[1] = amplitude[body] * normal[body * nDim + 1];
9813 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * normal[body * nDim + 2]; }
9814 break;
9815 case 3: // return body acceleration
9816 bodyData[0] = F0;
9817 bodyData[1] = F0;
9818 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9819 break;
9820
9821 default:
9822 bodyData[0] = F0;
9823 bodyData[1] = F0;
9824 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9825 break;
9826 }
9827 break;
9828 }
9829 case 2: // sine function with normel (=> periodic motion around the initialBodyCenter!)
9830 {
9831 angle = freqFactor[body] * mu2[body] * elapsedTime + liftStartAngle1[body];
9832 switch(returnMode) {
9833 case 1: // return body center
9834 if(angle >= liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9835 bodyData[0] =
9836 amplitude[body] * c_cellLengthAtLevel(maxLevel()) / mu2[body] * sin(angle) * normal[body * nDim + 0];
9837 bodyData[1] =
9838 amplitude[body] * c_cellLengthAtLevel(maxLevel()) / mu2[body] * sin(angle) * normal[body * nDim + 1];
9839 IF_CONSTEXPR(nDim == 3) {
9840 bodyData[2] = amplitude[body] * c_cellLengthAtLevel(maxLevel()) / mu2[body] * sin(angle)
9841 * normal[body * nDim + 2];
9842 }
9843 } else if(angle < liftStartAngle1[body]) {
9844 bodyData[0] = 0;
9845 bodyData[1] = 0;
9846 IF_CONSTEXPR(nDim == 3) bodyData[2] = 0;
9847 } else if(angle > liftEndAngle1[body]) {
9848 bodyData[0] = 0;
9849 bodyData[1] = 0;
9850 IF_CONSTEXPR(nDim == 3) bodyData[2] = 0;
9851 }
9852 break;
9853 case 2: // return body velocity
9854 if(angle > liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9855 bodyData[0] = amplitude[body] * cos(angle) * normal[body * nDim + 0];
9856 bodyData[1] = amplitude[body] * cos(angle) * normal[body * nDim + 1];
9857 IF_CONSTEXPR(nDim == 3) { bodyData[2] = amplitude[body] * cos(angle) * normal[body * nDim + 2]; }
9858 } else {
9859 bodyData[0] = F0;
9860 bodyData[1] = F0;
9861 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9862 }
9863 break;
9864 case 3: // return body acceleration
9865 if(angle > liftStartAngle1[body] && angle <= liftEndAngle1[body]) {
9866 bodyData[0] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 0];
9867 bodyData[1] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 1];
9868 IF_CONSTEXPR(nDim == 3) {
9869 bodyData[2] = -mu2[body] * amplitude[body] * sin(angle) * normal[body * nDim + 2];
9870 }
9871 } else {
9872 bodyData[0] = F0;
9873 bodyData[1] = F0;
9874 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9875 }
9876 break;
9877 default:
9878 bodyData[0] = F0;
9879 bodyData[1] = F0;
9880 IF_CONSTEXPR(nDim == 3) bodyData[2] = F0;
9881 break;
9882 }
9883 break;
9884 }
9885 case 3: {
9886 if(!m_virtualSurgery) {
9887 TERMM(1, "This mode cannot be used without the m_virtualSurgery flag!");
9888 }
9889 switch(returnMode) {
9890 case 1: // return body center
9891 {
9892 // Blending between two level-sets using linear interpolation.
9893 // Only the 0th level set changes. The other sets are static.
9894 // Define the interpolation coefficients
9895 MIntScratchSpace startTime(m_noInterpolationRegions, AT_, "startTime");
9896 MIntScratchSpace noTimeSteps(m_noInterpolationRegions, AT_, "noTimeSteps");
9897 MIntScratchSpace timeStep(m_noInterpolationRegions, AT_, "timeStep");
9898 MFloatScratchSpace alpha(m_noInterpolationRegions, AT_, "alpha");
9899 for(MInt r = 0; r < m_noInterpolationRegions; r++) {
9900 if(r >= m_approxNoInterpReg) {
9901 startTime(r) = m_interpStartTime[m_approxNoInterpReg - 1];
9902 noTimeSteps(r) = m_noInterpTimeSteps[m_approxNoInterpReg - 1];
9903 } else {
9904 startTime(r) = m_interpStartTime[r];
9905 noTimeSteps(r) = m_noInterpTimeSteps[r];
9906 }
9907 timeStep(r) = mMax(0, globalTimeStep - startTime(r));
9908 }
9909
9910 for(MInt r = 0; r < m_noInterpolationRegions; r++) {
9911 timeStep(r) = mMin(timeStep(r), noTimeSteps(r));
9912 alpha(r) = (F1 * timeStep(r)) / (F1 * noTimeSteps(r));
9913 }
9914
9915 if(domainId() == 0) {
9916 cout << "GlobalTimeStep = " << globalTimeStep << ": " << endl;
9917 for(MInt r = 0; r < m_noInterpolationRegions; r++) {
9918 cout << "For region " << r << ": startTime = " << startTime(r) << ", timeStep = " << timeStep(r)
9919 << ", alpha = " << alpha(r) << endl;
9920 }
9921 }
9922
9923 // Recalculate the collected level set on the before collected cells
9924 for(MInt i = 0; i < a_noCells(); i++) {
9925 MInt cellId = i;
9926 MInt regions = mMax(0, m_cellIsInDiffRegion[cellId]);
9927 MFloat phi1 = m_correctedDistances[i][0];
9928 MFloat phi2 = m_correctedDistances[i][1];
9929 a_levelSetFunctionG(cellId, 0) = phi1 * (F1 - alpha(regions)) + phi2 * alpha(regions);
9930 }
9931 bodyData[0] = F0;
9932 bodyData[1] = F0;
9933 if(nDim == 3) {
9934 bodyData[2] = F0;
9935 }
9936 break;
9937 }
9938 case 2: // return body velocity
9939 bodyData[0] = F0;
9940 bodyData[1] = F0;
9941 if(nDim == 3) {
9942 bodyData[2] = F0;
9943 }
9944 break;
9945 case 3: // return body acceleration
9946 bodyData[0] = F0;
9947 bodyData[1] = F0;
9948 if(nDim == 3) {
9949 bodyData[2] = F0;
9950 }
9951 break;
9952 default:
9953 bodyData[0] = F0;
9954 bodyData[1] = F0;
9955 if(nDim == 3) bodyData[2] = F0;
9956 break;
9957 }
9958 break;
9959 }
9960 default:
9961 mTerm(1, AT_, "function type not implemented. Please check bodyMovementFunctions property!");
9962 }
9963
9964 // add the initialBodyCenter to the bodyDato for the body-positioning:
9965 if(returnMode == 1) {
9966 for(MInt dir = 0; dir < nDim; dir++) {
9967 bodyData[dir] += initialBodyCenter[body * nDim + dir];
9968 }
9969 }
9970
9971 // rotate the final result around the z-axis
9972 if(rotAngle > 0 || rotAngle < 0) {
9973 MFloat tmp0 = bodyData[0] * cos(rotAngle) + bodyData[1] * sin(rotAngle);
9974 MFloat tmp1 = bodyData[1] * cos(rotAngle) - bodyData[0] * sin(rotAngle);
9975 bodyData[0] = tmp0;
9976 bodyData[1] = tmp1;
9977 bodyData[2] = bodyData[2];
9978 }
9979 return;
9980 }
9981}
9982
9983
9984//----------------------------------------------------------------------------
9985
9986
9998template <MInt nDim>
10000 TRACE();
10001
10002 MBool& first = m_static_identifyBodies_first;
10003 MFloat(&initialInsidePoints)[s_maxNoEmbeddedBodies * 3] = m_static_identifyBodies_initialInsidePoints;
10004
10005 MFloat& shiftTime = m_static_identifyBodies_shiftTime;
10006
10007 // a) initialise and read initialInsidePoints-property
10008 // (used as a starting Point to identify the different bodies)
10009 if(first) {
10010 if(m_noBodyBndryCndIds > s_maxNoEmbeddedBodies) {
10011 mTerm(1, AT_, "Error in LsCartesianSolver<nDim>::identifyBodies. Too many embedded Bodies!");
10012 }
10013
10014 // set default values:
10015 for(MInt k = 0; k < s_maxNoEmbeddedBodies; k++) {
10016 for(MInt i = 0; i < nDim; i++) {
10017 initialInsidePoints[k * nDim + i] = F0;
10018 }
10019 }
10020 // read Properties
10021
10030 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
10031 for(MInt j = 0; j < nDim; j++) {
10032 initialInsidePoints[i * nDim + j] = Context::getSolverProperty<MFloat>(
10033 "initialInsidePoints", m_solverId, AT_, &initialInsidePoints[i * nDim + j], i * nDim + j);
10034 }
10035 }
10036
10037 // CAUTION: during initSolver m_phsicalTime has not yet been set in the fvSolver!
10038 // This leeds to difficulties when initialising a restart!
10039 // This an update of the levelSet-Movement to the initial-Inside-Points is done here
10040 // and reverted again at the end of the function!
10041
10042 if(m_restart) {
10043 ASSERT(globalTimeStep == m_restartTimeStep,
10044 "globalTimeStep = " + std::to_string(globalTimeStep)
10045 + "; m_restartTimeStep = " + std::to_string(m_restartTimeStep));
10046 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
10047 for(MInt j = 0; j < nDim; j++) {
10048 initialInsidePoints[i * nDim + j] =
10049 initialInsidePoints[i * nDim + j] + m_semiLagrange_xShift_ref[j * m_noEmbeddedBodies + i];
10050 }
10051 }
10052 }
10053
10054 shiftTime = 0;
10055 }
10056
10057 MFloat elapsedTime = time();
10058
10059 // b) initialise the bodyId in set 0 with -1 (if this is the collected-set)
10060 if(m_startSet > 0) {
10061 for(MInt gCellId = 0; gCellId < a_noCells(); gCellId++) {
10062 a_bodyIdG(gCellId, 0) = -1;
10063 }
10064 }
10065
10066 MIntScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
10067
10068 if(first || mode == 0 || !m_semiLagrange) {
10069 stack<MInt> bodyStack;
10070
10071
10072 // c) set the bodyId of other sets
10073 for(MInt set = m_startSet; set < m_noSets; set++) {
10074 if(!m_computeSet[set] && !m_maxLevelChange) continue;
10075 if(!m_changedSet[set] && m_levelSetMb) continue;
10076
10077 // 1) initialise with -1
10078 for(MInt gCellId = 0; gCellId < a_noCells(); gCellId++) {
10079 a_bodyIdG(gCellId, set) = -1;
10080 }
10081 // 2) go over all bodies in the set
10082 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
10083 const MInt body = m_setToBodiesTable[set][b];
10084 MFloat bodyCenter[3] = {F0, F0, F0};
10085 computeBodyPropertiesForced(1, bodyCenter, body, time());
10086 for(MInt i = 0; i < nDim; i++) {
10087 bodyCenter[i] += initialInsidePoints[body * nDim + i];
10088 }
10089 // Consider azimuthalPer
10090 if(m_LsRotate) {
10091 std::array<MFloat, nDim> rotCenter{};
10092 std::array<MFloat, nDim> bodyCenter_shift{};
10093 std::array<MFloat, nDim> rotAngle{};
10094 std::copy_n(&bodyCenter[0], nDim, &bodyCenter_shift[0]);
10095 std::copy_n(&m_semiLagrange_xRot_STL[body * nDim], nDim, &rotAngle[0]);
10096 for(MInt d = 0; d < nDim; d++) {
10097 rotAngle[d] *= -F1;
10098 }
10099 computeBodyPropertiesForced(1, rotCenter.data(), body, 0.0);
10100 rotateLevelSet(1, bodyCenter, body, bodyCenter_shift.data(), rotCenter.data(), &rotAngle[0]);
10101 if(grid().azimuthalPeriodicity()) {
10102 MFloat center = grid().azimuthalCenter();
10103 MFloat angle = grid().azimuthalAngle();
10104 grid().raw().cartesianToCylindric(bodyCenter, bodyCenter_shift.data());
10105 MInt fac = 0;
10106 if(bodyCenter_shift[1] > (center + F1B2 * angle)) {
10107 fac = (MInt)((bodyCenter_shift[1] - (center - F1B2 * angle)) / angle);
10108 } else if(bodyCenter_shift[1] < (center - F1B2 * angle)) {
10109 fac = (MInt)((bodyCenter_shift[1] - (center + F1B2 * angle)) / angle);
10110 }
10111 grid().raw().rotateCartesianCoordinates(bodyCenter, fac * angle);
10112 }
10113 }
10114
10115 const MInt startCellId = getContainingCell(bodyCenter);
10116
10117 if(startCellId > -1 && startCellId < a_noCells()) {
10118 bodyStack.push(startCellId);
10119 }
10120 MInt cellsAdded = 1;
10121
10122 while(cellsAdded) {
10123 cellsAdded = 0;
10124
10125 while(!bodyStack.empty()) {
10126 const MInt currentCell = bodyStack.top();
10127 bodyStack.pop();
10128 if(a_bodyIdG(currentCell, set) > -1) continue;
10129 if(c_noChildren(currentCell) > 0 && !a_isHalo(currentCell)) {
10130 for(MInt child = 0; child < c_noChildren(currentCell); child++) {
10131 const MInt childId = c_childId(currentCell, child);
10132 if(childId < 0) continue;
10133 if(a_isHalo(childId)) continue;
10134 if(a_level(childId) == a_maxGCellLevel(set) && !a_isGZeroCell(childId, set)
10135 && a_levelSetFunctionG(childId, set) * ((MFloat)m_levelSetSign[set]) >= 0)
10136 continue;
10137 bodyStack.push(childId);
10138 }
10139 continue;
10140 }
10141 a_bodyIdG(currentCell, set) = body;
10142 cellsAdded++;
10143 for(MInt dir = 0; dir < m_noDirs; dir++) {
10144 if(!a_hasNeighbor(currentCell, dir)) continue;
10145 const MInt nghbrId = c_neighborId(currentCell, dir);
10146 if(a_isHalo(nghbrId)) continue;
10147 if(a_bodyIdG(nghbrId, set) > -1) continue;
10148 if(!a_isGZeroCell(nghbrId, set) && a_levelSetFunctionG(nghbrId, set) * ((MFloat)m_levelSetSign[set]) >= 0)
10149 continue;
10150 bodyStack.push(nghbrId);
10151 }
10152 }
10153
10154
10155 MPI_Allreduce(MPI_IN_PLACE, &cellsAdded, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "cellsAdded");
10156
10157 // exchange halo-information
10158 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10159 for(MInt j = 0; j < noWindowCells(i); j++) {
10160 tmp_data(windowCellId(i, j)) = a_bodyIdG(windowCellId(i, j), set);
10161 }
10162 }
10163 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10164 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
10165 MInt windowId = grid().azimuthalWindowCell(i, j);
10166 tmp_data(windowId) = a_bodyIdG(windowId, set);
10167 }
10168 }
10169
10170 exchangeDataLS(&tmp_data(0), 1);
10171
10172 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10173 for(MInt j = 0; j < noHaloCells(i); j++) {
10174 const MInt haloCell = haloCellId(i, j);
10175 if(a_bodyIdG(haloCell, set) < 0) {
10176 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10177 if(a_bodyIdG(haloCell, set) > -1) {
10178 for(MInt dir = 0; dir < m_noDirs; dir++) {
10179 if(!a_hasNeighbor(haloCell, dir)) continue;
10180 MInt nghbrId = c_neighborId(haloCell, dir);
10181 if(a_isHalo(nghbrId)) continue;
10182 if(a_bodyIdG(nghbrId, set) > -1) continue;
10183 if(!a_isGZeroCell(nghbrId, set)
10184 && a_levelSetFunctionG(nghbrId, set) * ((MFloat)m_levelSetSign[set]) >= 0)
10185 continue;
10186 bodyStack.push(nghbrId);
10187 }
10188 }
10189 }
10190 }
10191 }
10192 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10193 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
10194 const MInt haloCell = grid().azimuthalHaloCell(i, j);
10195 if(a_bodyIdG(haloCell, set) < 0) {
10196 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10197 if(a_bodyIdG(haloCell, set) > -1) {
10198 for(MInt dir = 0; dir < m_noDirs; dir++) {
10199 if(!a_hasNeighbor(haloCell, dir)) {
10200 continue;
10201 }
10202 MInt nghbrId = c_neighborId(haloCell, dir);
10203 if(a_isHalo(nghbrId)) {
10204 continue;
10205 }
10206 if(a_bodyIdG(nghbrId, set) > -1) {
10207 continue;
10208 }
10209 if(!a_isGZeroCell(nghbrId, set)
10210 && a_levelSetFunctionG(nghbrId, set) * ((MFloat)m_levelSetSign[set]) >= 0) {
10211 continue;
10212 }
10213 bodyStack.push(nghbrId);
10214 }
10215 }
10216 }
10217 }
10218 }
10219 }
10220 } // loop over all bodies in the set
10221
10222 // d) extend bodyIds further for anticipated bndry cells
10223 // this is done at the same time for all bodies in the same set!
10224
10225 MInt layerCount = 1;
10226 MInt cnt = 0;
10227 MIntScratchSpace lastLayer(a_noCells(), AT_, "lastLayer");
10228
10229 // 1) extend the first layer, by going over all G0-cells in the set
10230 // and find their neighbors!
10231 // set the bodyId and add the cell to the lastLayer-list
10232 for(MInt id = 0; id < a_noG0Cells(set); id++) {
10233 const MInt cellId = a_G0CellId(id, set);
10234 for(MInt dir = 0; dir < m_noDirs; dir++) {
10235 const MInt nghbrId = c_neighborId(cellId, dir);
10236 if(nghbrId == -1) continue;
10237 if(a_isGZeroCell(nghbrId, set)) continue;
10238 if(maxLevel() > minLevel()) {
10239 ASSERT(a_bodyIdG(nghbrId, set) == -1 || a_bodyIdG(nghbrId, set) == a_bodyIdG(cellId, set),
10240 "Overlapping bodies in the same set not possible: gather bodies "
10241 + to_string(a_bodyIdG(nghbrId, set)) + " " + to_string(a_bodyIdG(cellId, set))
10242 + "in different sets! ");
10243 }
10244 lastLayer.p[cnt++] = nghbrId;
10245 a_bodyIdG(nghbrId, set) = a_bodyIdG(cellId, set);
10246 }
10247 }
10248
10249 // 2) add the halo-neighbor-cells
10250 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10251 for(MInt j = 0; j < noWindowCells(i); j++) {
10252 tmp_data(windowCellId(i, j)) = a_bodyIdG(windowCellId(i, j), set);
10253 }
10254 }
10255 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10256 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
10257 MInt windowId = grid().azimuthalWindowCell(i, j);
10258 tmp_data(windowId) = a_bodyIdG(windowId, set);
10259 }
10260 }
10261
10262 exchangeDataLS(&tmp_data(0), 1);
10263
10264 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10265 for(MInt j = 0; j < noHaloCells(i); j++) {
10266 const MInt haloCell = haloCellId(i, j);
10267 if(a_bodyIdG(haloCell, set) < 0) {
10268 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10269 if(a_bodyIdG(haloCell, set) > -1) {
10270 lastLayer.p[cnt++] = haloCell;
10271 }
10272 }
10273 }
10274 }
10275 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10276 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
10277 const MInt haloCell = grid().azimuthalHaloCell(i, j);
10278 if(a_bodyIdG(haloCell, set) < 0) {
10279 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10280 if(a_bodyIdG(haloCell, set) > -1) {
10281 lastLayer.p[cnt++] = haloCell;
10282 }
10283 }
10284 }
10285 }
10286
10287 MIntScratchSpace temp(a_noCells(), AT_, "temp");
10288
10289 // 3) extend all other layers
10290 while(layerCount < m_gBandWidth + 1) {
10291 MInt tempCnt = 0;
10292 for(MInt c = 0; c < cnt; c++) {
10293 if(a_bodyIdG(lastLayer.p[c], set) == -1) continue;
10294 for(MInt dir = 0; dir < m_noDirs; dir++) {
10295 MInt nghbrId = c_neighborId(lastLayer.p[c], dir);
10296 if(nghbrId == -1) continue;
10297 if(a_isGZeroCell(nghbrId, set)) continue;
10298 if(a_bodyIdG(nghbrId, set) > -1) continue;
10299 temp.p[tempCnt++] = nghbrId;
10300 a_bodyIdG(nghbrId, set) = a_bodyIdG(lastLayer.p[c], set);
10301 }
10302 }
10303
10304 // set bodyId for all halo-cells
10305 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10306 for(MInt j = 0; j < noWindowCells(i); j++) {
10307 tmp_data(windowCellId(i, j)) = a_bodyIdG(windowCellId(i, j), set);
10308 }
10309 }
10310 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10311 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
10312 MInt windowId = grid().azimuthalWindowCell(i, j);
10313 tmp_data(windowId) = a_bodyIdG(windowId, set);
10314 }
10315 }
10316
10317 exchangeDataLS(&tmp_data(0), 1);
10318
10319 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10320 for(MInt j = 0; j < noHaloCells(i); j++) {
10321 const MInt haloCell = haloCellId(i, j);
10322 if(a_bodyIdG(haloCell, set) < 0) {
10323 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10324 if(a_bodyIdG(haloCell, set) > -1) {
10325 temp.p[tempCnt++] = haloCell;
10326 }
10327 }
10328 }
10329 }
10330 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10331 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
10332 const MInt haloCell = grid().azimuthalHaloCell(i, j);
10333 if(a_bodyIdG(haloCell, set) < 0) {
10334 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10335 if(a_bodyIdG(haloCell, set) > -1) {
10336 temp.p[tempCnt++] = haloCell;
10337 }
10338 }
10339 }
10340 }
10341
10342 layerCount++;
10343 cnt = tempCnt;
10344 for(MInt c = 0; c < tempCnt; c++)
10345 lastLayer.p[c] = temp.p[c];
10346 }
10347 }
10348
10349 // revert body-movement-changes
10350 if(m_restart && globalTimeStep == m_restartTimeStep && first) {
10351 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
10352 for(MInt j = 0; j < nDim; j++) {
10353 initialInsidePoints[i * nDim + j] =
10354 initialInsidePoints[i * nDim + j] - m_semiLagrange_xShift_ref[j * m_noEmbeddedBodies + i];
10355 }
10356 }
10357 }
10358
10359 shiftTime = elapsedTime;
10360
10361 } else if(mode == 1) {
10362 // NOTE: faster version
10363 // however, this leads to differences towards the prevoius version,
10364 // especially for gapClosing and different bodies in the same set, that are close to each other!
10365
10366 if(domainId() == 0) cerr << "Using fast identifyBodies-Version" << endl;
10367 MBool anyShift = false;
10368
10369 // c) set the bodyId of other sets
10370 for(MInt set = m_startSet; set < m_noSets; set++) {
10371 if(!m_computeSet[set]) continue;
10372 if(!m_changedSet[set] & m_levelSetMb) continue;
10373
10374 const MFloat length = 0.5 * c_cellLengthAtLevel(a_maxGCellLevel()); // / sqrt(nDim);
10375 // 1) go over all bodies in the set
10376 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
10377 MInt body = m_setToBodiesTable[set][b];
10378 MFloat xCurrent[3] = {F0, F0, F0};
10379 MFloat xOld[3] = {F0, F0, F0};
10380 MFloat xShift[3] = {F0, F0, F0};
10381
10382 computeBodyPropertiesForced(1, xCurrent, body, time() + timeStep());
10383 computeBodyPropertiesForced(1, xOld, body, shiftTime);
10384
10385 // 2) find the body-Movement since the latest shift and check if a shift is necessary
10386 for(MInt d = 0; d < nDim; d++) {
10387 xShift[d] = xCurrent[d] - xOld[d];
10388 }
10389 MBool needShift = false;
10390 for(MInt d = 0; d < nDim; d++) {
10391 if(xShift[d] > length) {
10392 needShift = true;
10393 anyShift = true;
10394 shiftTime = elapsedTime;
10395 }
10396 }
10397
10398 // 3) shift the bodyId
10399 if(needShift) {
10400 if(domainId() == 0) {
10401 cerr << "Shifting fast identifyBodies-Version " << shiftTime << " " << xShift[0] << " " << xShift[1] << " "
10402 << xCurrent[0] << " " << xOld[0] << " " << xCurrent[1] << " " << xOld[1] << endl;
10403 }
10404 for(MInt dir = 0; dir < nDim; dir++) {
10405 if(xShift[dir] > length) {
10406 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
10407 if(!c_isLeafCell(cellId)) continue;
10408 if(a_bodyIdG(cellId, set) != body) continue;
10409
10410 if(!a_hasNeighbor(cellId, dir)) continue;
10411 MInt nghbrId = c_neighborId(cellId, dir);
10412 if(!a_bodyIdG(nghbrId, set)) {
10413 a_bodyIdG(nghbrId, set) = body;
10414 }
10415 }
10416 }
10417 }
10418 }
10419 }
10420 }
10421
10422 if(anyShift) {
10423 exchangeDataLS(&(a_bodyIdG(0, 0)), m_maxNoSets);
10424 }
10425
10426 } else {
10427 for(MInt set = m_startSet; set < m_noSets; set++) {
10428 if(!m_computeSet[set]) continue;
10429 if(!m_changedSet[set] & m_levelSetMb) continue;
10430
10431 // 1) initialise with -1 outside of the body:
10432 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
10433 if(a_levelSetFunctionG(cellId, set) * ((MFloat)m_levelSetSign[set]) > 0 && !a_isGZeroCell(cellId, set)) {
10434 a_bodyIdG(cellId, set) = -1;
10435 } else {
10436 if(a_level(cellId) == a_maxGCellLevel(set)) {
10437 ASSERT(a_bodyIdG(cellId, set) > -1, "");
10438 }
10439 }
10440 }
10441
10442 MInt tempCnt = 0;
10443 MInt layerCount = 1;
10444 MInt cnt = 0;
10445 MIntScratchSpace lastLayer(a_noCells(), AT_, "lastLayer");
10446 MIntScratchSpace temp(a_noCells(), AT_, "temp");
10447
10448 // 2) check G0-Cells and set bodyId for neighbors of the g0Cells
10449
10450 for(MInt id = 0; id < a_noG0Cells(set); id++) {
10451 const MInt cellId = a_G0CellId(id, set);
10452#if defined LS_DEBUG || !defined NDEBUG
10453 ASSERT(a_bodyIdG(cellId, set) > -1,
10454 "G0-Cell should have a valid bodyId " << to_string(c_globalId(cellId)) + " " + to_string(set));
10455 MBool bodyFound = false;
10456 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
10457 MInt body = m_setToBodiesTable[set][b];
10458 if(a_bodyIdG(cellId, set) == body) {
10459 bodyFound = true;
10460 break;
10461 }
10462 }
10463 ASSERT(bodyFound, "BodyId of the G0-Cell is not matching any of the bodies in the set!");
10464#endif
10465 temp.p[id] = cellId;
10466 tempCnt++;
10467 }
10468
10469 for(MInt c = 0; c < tempCnt; c++) {
10470 for(MInt dir = 0; dir < m_noDirs; dir++) {
10471 MInt nghbrId = c_neighborId(temp.p[c], dir);
10472 if(nghbrId == -1) continue;
10473 if(a_isGZeroCell(nghbrId, set)) continue;
10474 lastLayer.p[cnt++] = nghbrId;
10475 a_bodyIdG(nghbrId, set) = a_bodyIdG(temp.p[c], set);
10476 }
10477 }
10478
10479 // 2) add the halo-neighbor-cells
10480 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10481 for(MInt j = 0; j < noWindowCells(i); j++) {
10482 tmp_data(windowCellId(i, j)) = a_bodyIdG(windowCellId(i, j), set);
10483 }
10484 }
10485 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10486 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
10487 MInt windowId = grid().azimuthalWindowCell(i, j);
10488 tmp_data(windowId) = a_bodyIdG(windowId, set);
10489 }
10490 }
10491
10492 exchangeDataLS(&tmp_data(0), 1);
10493
10494 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10495 for(MInt j = 0; j < noHaloCells(i); j++) {
10496 const MInt haloCell = haloCellId(i, j);
10497 if(a_bodyIdG(haloCell, set) < 0) {
10498 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10499 if(a_bodyIdG(haloCell, set) > -1) {
10500 lastLayer.p[cnt++] = haloCell;
10501 }
10502 }
10503 }
10504 }
10505 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10506 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
10507 const MInt haloCell = grid().azimuthalHaloCell(i, j);
10508 if(a_bodyIdG(haloCell, set) < 0) {
10509 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10510 if(a_bodyIdG(haloCell, set) > -1) {
10511 lastLayer.p[cnt++] = haloCell;
10512 }
10513 }
10514 }
10515 }
10516
10517 // 3) extend all other layers
10518 while(layerCount < m_gBandWidth + 1) {
10519 tempCnt = 0;
10520 for(MInt c = 0; c < cnt; c++) {
10521 // if(a_bodyIdG( lastLayer.p[c] , set) == -1) continue;
10522 ASSERT(a_bodyIdG(lastLayer.p[c], set) > -1, "");
10523 for(MInt dir = 0; dir < m_noDirs; dir++) {
10524 MInt nghbrId = c_neighborId(lastLayer.p[c], dir);
10525 if(nghbrId == -1) continue;
10526 if(a_isGZeroCell(nghbrId, set)) continue;
10527 if(a_bodyIdG(nghbrId, set) > -1) continue;
10528 temp.p[tempCnt++] = nghbrId;
10529 a_bodyIdG(nghbrId, set) = a_bodyIdG(lastLayer.p[c], set);
10530 }
10531 }
10532
10533 // set bodyId for all halo-cells
10534 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10535 for(MInt j = 0; j < noWindowCells(i); j++) {
10536 tmp_data(windowCellId(i, j)) = a_bodyIdG(windowCellId(i, j), set);
10537 }
10538 }
10539 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10540 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
10541 MInt windowId = grid().azimuthalWindowCell(i, j);
10542 tmp_data(windowId) = a_bodyIdG(windowId, set);
10543 }
10544 }
10545
10546 exchangeDataLS(&tmp_data(0), 1);
10547
10548 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
10549 for(MInt j = 0; j < noHaloCells(i); j++) {
10550 const MInt haloCell = haloCellId(i, j);
10551 if(a_bodyIdG(haloCell, set) < 0) {
10552 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10553 if(a_bodyIdG(haloCell, set) > -1) {
10554 temp.p[tempCnt++] = haloCell;
10555 }
10556 }
10557 }
10558 }
10559 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
10560 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
10561 const MInt haloCell = grid().azimuthalHaloCell(i, j);
10562 if(a_bodyIdG(haloCell, set) < 0) {
10563 a_bodyIdG(haloCell, set) = tmp_data(haloCell);
10564 if(a_bodyIdG(haloCell, set) > -1) {
10565 temp.p[tempCnt++] = haloCell;
10566 }
10567 }
10568 }
10569 }
10570
10571 layerCount++;
10572 cnt = tempCnt;
10573 for(MInt c = 0; c < tempCnt; c++)
10574 lastLayer.p[c] = temp.p[c];
10575 }
10576 }
10577 }
10578
10579
10580 first = false;
10581}
10582
10583
10584//----------------------------------------------------------------------------
10585
10595template <MInt nDim>
10597 TRACE();
10598
10599 MInt startCellId = -1;
10600
10601 // find proper starting cell on lowest level
10602 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
10603 if(a_level(cellId) != minLevel()) continue;
10604 if(inCell(cellId, point)) {
10605 startCellId = cellId;
10606 while(c_noChildren(startCellId) > 0) {
10607 MInt position = 0;
10608 if(point[0] > c_coordinate(startCellId, 0)) position += 1;
10609 if(point[1] > c_coordinate(startCellId, 1)) position += 2;
10610 IF_CONSTEXPR(nDim == 3) {
10611 if(point[2] > c_coordinate(startCellId, 2)) position += 4;
10612 }
10613 // If cell has children but does not have the child inside
10614 // which the point is located, the cell itself is returned
10615 const MInt childId = c_childId(startCellId, position);
10616 if(childId > -1 && !a_isHalo(childId)) {
10617 startCellId = childId;
10618 } else {
10619 return startCellId;
10620 }
10621 }
10622 return startCellId;
10623 }
10624 }
10625
10626 ASSERT(startCellId < a_noCells(), "");
10627
10628 if(startCellId > -1) {
10629 ASSERT(!a_isHalo(startCellId), "");
10630 }
10631
10632 return startCellId;
10633}
10634
10635
10636//----------------------------------------------------------------------------
10637
10649template <MInt nDim>
10651 TRACE();
10652
10653 MInt nghbrId = -1;
10654
10655 MInt nghbrId2, nghbrId3;
10656 MInt d1, d2, d3, e, w, g;
10657 std::vector<MInt> diagCells;
10658 std::vector<MInt> diag2Cells;
10659 std::vector<MInt> signs;
10660 std::map<MInt, std::vector<MInt>> dirCode;
10661
10662 //--------
10663
10664 ASSERT(a_level(startCell) == a_maxGCellLevel(set) || a_level(startCell) == maxLevel(),
10665 "searchCell not on maxLevel! " + to_string(startCell));
10666
10667 if(startCell < 0) return -1;
10668 if(inCell(startCell, point)) return startCell;
10669 // search neighbors
10670 for(MInt nghbr = 0; nghbr < 2 * nDim; nghbr++) {
10671 nghbrId = c_neighborId(startCell, nghbr);
10672 if(nghbrId == -1) continue;
10673
10674 if(inCell(nghbrId, point)) return nghbrId;
10675 }
10676
10677 signs.resize(nDim);
10678
10679 // search diagonal neighbors
10680 MInt dir[3] = {0, 2, 4};
10681 MInt oDir[6] = {2, 4, 0, 4, 0, 2};
10682 for(MInt i = 0; i < nDim; i++) {
10683 for(MInt j = 0; j < 2; j++) {
10684 d1 = dir[i] + j;
10685 nghbrId = c_neighborId(startCell, d1);
10686 if(nghbrId == -1) continue;
10687 e = d1 / 2;
10688 signs[e] = d1 + pow(-1, j);
10689 for(MInt k = 0; k < 2; k++) {
10690 for(MInt m = 0; m < 2; m++) {
10691 d2 = oDir[2 * e + k] + m;
10692 nghbrId2 = c_neighborId(nghbrId, d2);
10693 if(nghbrId2 == -1) continue;
10694 diagCells.push_back(nghbrId2);
10695 w = d2 / 2;
10696 signs[w] = d2 + pow(-1, m);
10697 for(MInt n = 0; n < 2; n++) {
10698 d3 = dir[nDim - e - w] + n;
10699 if(a_hasNeighbor(nghbrId2, d3)) {
10700 g = d3 / 2;
10701 signs[g] = d3 + pow(-1, n);
10702 nghbrId3 = c_neighborId(nghbrId2, d3);
10703 diag2Cells.push_back(nghbrId3);
10704 if(dirCode.find(nghbrId3) == dirCode.end()) dirCode.insert(pair<MInt, vector<MInt>>(nghbrId3, signs));
10705 }
10706 }
10707 }
10708 }
10709 }
10710 }
10711
10712 std::sort(diagCells.begin(), diagCells.end());
10713 auto last1 = std::unique(diagCells.begin(), diagCells.end());
10714 diagCells.erase(last1, diagCells.end());
10715 for(std::vector<MInt>::iterator it = diagCells.begin(); it != diagCells.end(); it++) {
10716 if(inCell(*it, point)) return *it;
10717 }
10718 std::sort(diag2Cells.begin(), diag2Cells.end());
10719 auto last2 = std::unique(diag2Cells.begin(), diag2Cells.end());
10720 diag2Cells.erase(last2, diag2Cells.end());
10721 for(std::vector<MInt>::iterator it = diag2Cells.begin(); it != diag2Cells.end(); it++) {
10722 if(inCell(*it, point)) return *it;
10723 }
10724
10725 // If containing cell is not found search second layer
10726 // cerr << "D:" << domainId() << " SecondLayer " << startCell << " " << c_globalId(startCell) << " " <<
10727 // c_coordinate(startCell,0) << " " << c_coordinate(startCell,1) << " " << c_coordinate(startCell,2) << " " <<
10728 // a_level(startCell) << endl;
10729
10730 nghbrId = checkSecondLayerCells(diag2Cells, dirCode, point);
10731 if(nghbrId > -1) {
10732 if(a_level(nghbrId) != a_maxGCellLevel() || (!m_reconstructOldG && m_initialGCell[nghbrId] == 0)) {
10733 nghbrId = -1;
10734 }
10735 }
10736
10737 if(nghbrId == -1) {
10738 cerr << "D:" << domainId() << " Entire domain " << startCell << "/" << c_globalId(startCell) << " "
10739 << c_coordinate(startCell, 0) << " " << c_coordinate(startCell, 1) << " " << c_coordinate(startCell, 2) << " "
10740 << a_level(startCell) << " Point " << point[0] << " " << point[1] << " " << point[2] << endl;
10741
10742 nghbrId = getContainingCell(point);
10743
10744 if(nghbrId > -1
10745 && (a_level(nghbrId) != a_maxGCellLevel() || (!m_reconstructOldG && m_initialGCell[nghbrId] == 0))) {
10746 nghbrId = -1;
10747 }
10748 if(nghbrId > -1) {
10749 cerr << "Found " << domainId() << " " << nghbrId << "/" << c_globalId(nghbrId) << " " << c_coordinate(nghbrId, 0)
10750 << " " << c_coordinate(nghbrId, 1) << " " << c_coordinate(nghbrId, 2) << " " << a_level(nghbrId) << endl;
10751 MFloat dist = sqrt(pow(c_coordinate(nghbrId, 0) - c_coordinate(startCell, 0), 2.0)
10752 + pow(c_coordinate(nghbrId, 1) - c_coordinate(startCell, 1), 2.0)
10753 + pow(c_coordinate(nghbrId, 2) - c_coordinate(startCell, 2), 2.0))
10754 / c_cellLengthAtLevel(a_maxGCellLevel());
10755 cerr << "Point " << point[0] << " " << point[1] << " " << point[2] << " " << dist << endl;
10756 }
10757
10758 if(nghbrId == -1) {
10759 nghbrId = getContainingCellHalo(point);
10760 if(nghbrId > -1) {
10761 cerr << "D:" << domainId() << " Cell found in halo cell" << nghbrId;
10762 } else {
10763 mTerm(1, AT_, "No containing cell found... exiting!");
10764 }
10765 }
10766 }
10767
10768 return nghbrId;
10769
10770
10771 /*
10772 MInt noDiagNghbrs = 8;
10773 IF_CONSTEXPR(nDim == 3)
10774 noDiagNghbrs = 24;
10775 MInt diagNghbrs2D[9] = {0,2,0,3,1,2,1,3,0};
10776 MInt diagNghbrs3D[25] = {0,2,0,3,1,2,1,3,0,4,0,5,1,5,2,4,3,4,1,4,2,5,3,5,0};
10777 MInt* diagNghbrs = diagNghbrs2D;
10778 IF_CONSTEXPR(nDim == 3)
10779 diagNghbrs = diagNghbrs3D;
10780
10781 // check diagonal neighbors
10782 for( MInt d = 0; d < noDiagNghbrs; d++ ) {
10783 if( !a_hasNeighbor( startCell, diagNghbrs[d] ) )
10784 continue;
10785 nghbrId = c_neighborId( startCell, diagNghbrs[d] );
10786 if( !a_hasNeighbor( nghbrId, diagNghbrs[d+1] ) )
10787 continue;
10788 nghbrId = c_neighborId( nghbrId, diagNghbrs[d+1] );
10789
10790 searchCells.push_back(nghbrId);
10791 IF_CONSTEXPR(nDim == 3){
10792 if( !a_hasNeighbor( nghbrId, diagNghbrs[d+2] ) )
10793 continue;
10794 nghbrId = c_neighborId( nghbrId, diagNghbrs[d+2] );
10795 }
10796 if(inCell(nghbrId, point)) {
10797 return nghbrId;
10798 }
10799
10800 }
10801
10802
10803
10804 cerr << "D:" << domainId() << "Containing " << nghbrId;
10805 if ( nghbrId > -1 ) {
10806 cerr << " " << a_level(nghbrId) << " " << c_globalId(nghbrId);
10807
10808 for ( MInt i=0; i<nDim; i++ ) {
10809 cerr << (c_coordinate(nghbrId,i)-c_coordinate(startCell,i))/c_cellLengthAtLevel(a_level(nghbrId)) << " ";
10810 tmp += pow( (c_coordinate(nghbrId,i)-c_coordinate(startCell,i)) , 2.0 );
10811 }
10812 tmp = sqrt(tmp)/c_cellLengthAtLevel(a_level(nghbrId));
10813 cerr << tmp << endl;
10814 }
10815
10816
10817
10818 return nghbrId;
10819 */
10820}
10821
10822//----------------------------------------------------------------------------
10823
10824
10831template <MInt nDim>
10833 TRACE();
10834
10835 MFloat xmin, xmax;
10836 MFloat ymin, ymax;
10837 MFloat zmin, zmax;
10838 MFloat cellHalfLength = c_cellLengthAtLevel(a_level(cellId) + 1);
10839
10840 xmin = c_coordinate(cellId, 0) - cellHalfLength;
10841 xmax = c_coordinate(cellId, 0) + cellHalfLength;
10842 ymin = c_coordinate(cellId, 1) - cellHalfLength;
10843 ymax = c_coordinate(cellId, 1) + cellHalfLength;
10844
10845 IF_CONSTEXPR(nDim == 2) {
10846 if(point[0] <= xmax && point[0] >= xmin && point[1] <= ymax && point[1] >= ymin) {
10847 return true;
10848 } else {
10849 return false;
10850 }
10851 }
10852 else {
10853 zmin = c_coordinate(cellId, 2) - cellHalfLength;
10854 zmax = c_coordinate(cellId, 2) + cellHalfLength;
10855
10856 if(point[0] <= xmax && point[0] >= xmin && point[1] <= ymax && point[1] >= ymin && point[2] <= zmax
10857 && point[2] >= zmin) {
10858 return true;
10859 } else {
10860 return false;
10861 }
10862 }
10863}
10864
10865
10866//----------------------------------------------------------------------------
10867
10868
10877template <MInt nDim>
10879 MFloat* point) {
10880 TRACE();
10881
10882 std::function<MBool(const MInt, const MInt)> alwaysTrue = [&](const MInt cell, const MInt dim) {
10883 return static_cast<MBool>(grid().tree().hasNeighbor(cell, dim));
10884 };
10885
10886 return this->setUpInterpolationStencil(cellId, interpolationCells, point, alwaysTrue, false);
10887}
10888
10889
10890//----------------------------------------------------------------------------
10891
10902template <MInt nDim>
10903void LsCartesianSolver<nDim>::setUpLevelSetInterpolationStencil(MInt cellId, MInt* interpolationCells, MInt position) {
10904 interpolationCells[position] = cellId;
10905
10906 IF_CONSTEXPR(nDim == 2) {
10907 MInt nghbrX, nghbrY;
10908 MInt posIncrementX, posIncrementY;
10909 MInt xNghbrDir, yNghbrDir;
10910 if(position % 2 == 0) {
10911 xNghbrDir = 1;
10912 nghbrX = c_neighborId(cellId, xNghbrDir);
10913 posIncrementX = 1;
10914 } else {
10915 xNghbrDir = 0;
10916 nghbrX = c_neighborId(cellId, xNghbrDir);
10917 posIncrementX = -1;
10918 }
10919 if(((MInt)(position / 2)) % 2 == 0) {
10920 yNghbrDir = 3;
10921 nghbrY = c_neighborId(cellId, yNghbrDir);
10922 posIncrementY = 2;
10923 } else {
10924 yNghbrDir = 2;
10925 nghbrY = c_neighborId(cellId, yNghbrDir);
10926 posIncrementY = -2;
10927 }
10928 interpolationCells[position + posIncrementX] = nghbrX;
10929 interpolationCells[position + posIncrementY] = nghbrY;
10930 interpolationCells[position + posIncrementX + posIncrementY] = c_neighborId(nghbrX, yNghbrDir);
10931 }
10932 else {
10933 MInt nghbrX, nghbrY, nghbrZ;
10934 MInt posIncrementX, posIncrementY, posIncrementZ;
10935 MInt xNghbrDir, yNghbrDir, zNghbrDir;
10936 if(position % 2 == 0) {
10937 xNghbrDir = 1;
10938 nghbrX = c_neighborId(cellId, xNghbrDir);
10939 posIncrementX = 1;
10940 } else {
10941 xNghbrDir = 0;
10942 nghbrX = c_neighborId(cellId, xNghbrDir);
10943 posIncrementX = -1;
10944 }
10945 if(((MInt)(position / 2)) % 2 == 0) {
10946 yNghbrDir = 3;
10947 nghbrY = c_neighborId(cellId, yNghbrDir);
10948 posIncrementY = 2;
10949 } else {
10950 yNghbrDir = 2;
10951 nghbrY = c_neighborId(cellId, yNghbrDir);
10952 posIncrementY = -2;
10953 }
10954 if((MInt)(position / 4) == 0) {
10955 zNghbrDir = 5;
10956 nghbrZ = c_neighborId(cellId, zNghbrDir);
10957 posIncrementZ = 4;
10958 } else {
10959 zNghbrDir = 4;
10960 nghbrZ = c_neighborId(cellId, zNghbrDir);
10961 posIncrementZ = -4;
10962 }
10963 interpolationCells[position + posIncrementX] = nghbrX;
10964 interpolationCells[position + posIncrementY] = nghbrY;
10965 interpolationCells[position + posIncrementZ] = nghbrZ;
10966 interpolationCells[position + posIncrementX + posIncrementZ] = c_neighborId(nghbrX, zNghbrDir);
10967 interpolationCells[position + posIncrementX + posIncrementY] = c_neighborId(nghbrX, yNghbrDir);
10968 interpolationCells[position + posIncrementY + posIncrementZ] = c_neighborId(nghbrY, zNghbrDir);
10969 interpolationCells[position + posIncrementX + posIncrementY + posIncrementZ] =
10970 c_neighborId(c_neighborId(nghbrX, yNghbrDir), zNghbrDir);
10971 }
10972}
10973
10974
10975//----------------------------------------------------------------------------
10976
10983template <MInt nDim>
10985 TRACE();
10986
10987 const MInt otherDir[6] = {1, 0, 3, 2, 5, 4};
10988 const MInt bcId = m_bodyBndryCndIds[body];
10989
10990 MFloatScratchSpace tmp_field(a_noCells(), AT_, "tmp_field");
10991 MFloat dx[3] = {F0, F0, F0};
10992
10993 // shift STL to reference oldGField-position!
10994 if(m_GCtrlPntMethod == 2) {
10995 for(MInt i = 0; i < nDim; i++) {
10996 dx[i] = m_semiLagrange_xShift_ref[i * m_noEmbeddedBodies + body];
10997 }
10998 m_gCtrlPnt.CtrlPnt2_shiftSTL(bcId, dx);
10999 }
11000
11001 // backup of the original old levelset-field
11002 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11003 tmp_field[cellId] = a_oldLevelSetFunctionG(cellId, set);
11004 }
11005
11006 // shift the field for non-halo cells with valid neighbors
11007 // for invalid neighbor the distance is recomputed from the stl!
11008 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
11009 if(a_level(cellId) != a_maxGCellLevel(set)) continue;
11010 if(a_bodyIdG(cellId, set) != body) continue;
11011 ASSERT(!a_isHalo(cellId), "");
11012 const MInt nghbrId = c_neighborId(cellId, otherDir[dir]);
11013 if(nghbrId == -1 || nghbrId == cellId) {
11014 MFloat refPoint[3] = {F0, F0, F0};
11015 for(MInt i = 0; i < nDim; i++) {
11016 refPoint[i] = c_coordinate(cellId, i);
11017 }
11018 MInt closestElement;
11019 MFloat closestPoint[3] = {F0, F0, F0};
11020 MFloat sign = determineLevelSetSignFromSTL(refPoint, set);
11021 if(m_levelSetSign[set] < 0) sign *= -1.0;
11022 const MFloat phi = sign * computeDistanceFromSTL(refPoint, &closestElement, closestPoint, set);
11023 a_oldLevelSetFunctionG(cellId, set) = phi;
11024 } else {
11025 a_oldLevelSetFunctionG(cellId, set) = tmp_field[nghbrId];
11026 }
11027 }
11028
11029 // shift STL back to original position!
11030 if(m_GCtrlPntMethod == 2) {
11031 for(MInt i = 0; i < nDim; i++) {
11032 dx[i] = -m_semiLagrange_xShift_ref[i * m_noEmbeddedBodies + body];
11033 }
11034 m_gCtrlPnt.CtrlPnt2_shiftSTL(bcId, dx);
11035 }
11036}
11037
11038
11039//----------------------------------------------------------------------------
11040
11048template <MInt nDim>
11049MFloat LsCartesianSolver<nDim>::interpolateOldLevelSet(MInt* interpolationCells, MFloat* point, MInt referenceSet) {
11050 TRACE();
11051
11052 std::function<MFloat(const MInt, const MInt)> scalarField = [&](const MInt cellId, const MInt set) {
11053 return static_cast<MFloat>(a_oldLevelSetFunctionG(cellId, set));
11054 };
11055
11056 std::function<MFloat(const MInt, const MInt)> coordinate = [&](const MInt cellId, const MInt id) {
11057 return static_cast<MFloat>(c_coordinate(cellId, id));
11058 };
11059
11060 return this->template interpolateFieldData<true>(&interpolationCells[0], &point[0], referenceSet, scalarField,
11061 coordinate);
11062}
11063
11070template <MInt nDim>
11071MFloat LsCartesianSolver<nDim>::interpolateLevelSet(MInt* interpolationCells, MFloat* point, MInt referenceSet) {
11072 TRACE();
11073
11074 std::function<MFloat(const MInt, const MInt)> scalarField = [&](const MInt cellId, const MInt set) {
11075 return static_cast<MFloat>(a_levelSetFunctionG(cellId, set));
11076 };
11077
11078 std::function<MFloat(const MInt, const MInt)> coordinate = [&](const MInt cellId, const MInt id) {
11079 return static_cast<MFloat>(c_coordinate(cellId, id));
11080 };
11081
11082 return this->template interpolateFieldData<true>(&interpolationCells[0], &point[0], referenceSet, scalarField,
11083 coordinate);
11084}
11085
11086
11087//----------------------------------------------------------------------------
11088
11089
11108template <MInt nDim>
11110 TRACE();
11111
11112 // distance to the closest and second closest bodies of each cell
11113 MFloatScratchSpace distBody1(a_noCells(), AT_, "distBody1");
11114 MFloatScratchSpace distBody2(a_noCells(), AT_, "distBody2");
11115
11116 // sum of the distances to the closest and second closest bodies (gap width if cell is located
11117 // inside a gap)
11118 MFloatScratchSpace sumBodiesDist(a_noCells(), AT_, "sumBodiesDist");
11119
11120 if(m_noSets < 2) return;
11121
11122 const MFloat eps1 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim);
11123 const MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * m_gapDeltaMin;
11124
11125 if(mode == 1 || mode == 2) {
11126 // set a_levelSetFunctionG, a_bodyIdG
11127
11128 // move forward in time
11129 if(mode == 1 && globalTimeStep > 0 && m_closeGaps) {
11130 for(MInt region = 0; region < m_noGapRegions; region++) {
11131 m_minGapWidthDt1[region] = m_minGapWidth[region];
11132 m_minGapWidth[region] = std::numeric_limits<MFloat>::max();
11133 }
11134 }
11135
11136 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11137 MFloat currentWidth = std::numeric_limits<MFloat>::max();
11138
11139 // a) determine body0 and phi0
11140 a_levelSetFunctionG(cellId, 0) = a_levelSetFunctionG(cellId, 1);
11141 a_bodyIdG(cellId, 0) = a_bodyIdG(cellId, 1);
11142 a_secondBodyId(cellId) = -1;
11143 for(MInt set = 2; set < m_noSets; set++) {
11144 MFloat phi0 = a_levelSetFunctionG(cellId, 0);
11145 MFloat phi1 = a_levelSetFunctionG(cellId, set);
11146 MInt body0 = a_bodyIdG(cellId, 0);
11147 MInt body1 = a_bodyIdG(cellId, set);
11148 MInt body2 = a_secondBodyId(cellId);
11149 MInt body3 = a_bodyIdG(cellId, set);
11150
11151 //
11152 if(phi0 >= F0 && phi1 >= F0) {
11153 if(phi1 < phi0) {
11154 body2 = body0;
11155 body0 = body1;
11156 } else {
11157 // body0 = body0;
11158 if(body2 == -1 && body3 > -1) body2 = body3;
11159 }
11160 phi0 = mMin(phi0, phi1);
11161 } else if(phi0 <= F0 && phi1 <= F0) {
11162 if(abs(phi1) > abs(phi0)) {
11163 body2 = body0;
11164 body0 = body1;
11165 } else {
11166 if(body2 == -1 && body3 > -1) body2 = body3;
11167 }
11168 phi0 = -sqrt(phi0 * phi0 + phi1 * phi1);
11169 } else if(phi0 * phi1 <= F0) {
11170 if(phi0 < F0) {
11171 // phi0 = phi0;
11172 // body0 = body0;
11173 if(body2 == -1 && body3 > -1) body2 = body3;
11174 } else {
11175 phi0 = phi1;
11176 body2 = body0;
11177 body0 = body1;
11178 }
11179 ASSERT(phi0 <= phi1, "");
11180 } else {
11181 cerr << "WHAT THE FUCK! " << phi0 << phi1 << endl;
11182 }
11183
11184 a_levelSetFunctionG(cellId, 0) = phi0;
11185 a_bodyIdG(cellId, 0) = body0;
11186 a_secondBodyId(cellId) = body2;
11187 }
11188
11189 if(a_secondBodyId(cellId) == a_bodyIdG(cellId, 0)) {
11190 a_secondBodyId(cellId) = -1;
11191 }
11192 ASSERT(a_secondBodyId(cellId) < m_noBodyBndryCndIds, to_string(cellId) + " " + to_string(a_secondBodyId(cellId)));
11193 ASSERT(
11194 a_secondBodyId(cellId) < 0
11195 || (m_bodyToSetTable[a_secondBodyId(cellId)] > -1 && m_bodyToSetTable[a_secondBodyId(cellId)] < m_noSets),
11196 "");
11197
11198 if(m_closeGaps) {
11199 distBody1[cellId] = a_levelSetFunctionG(cellId, 0);
11200
11201 // b) set distBody2
11202 if(a_secondBodyId(cellId) > -1) {
11203 distBody2[cellId] = a_levelSetFunctionG(cellId, m_bodyToSetTable[a_secondBodyId(cellId)]);
11204 } else {
11205 distBody2[cellId] = m_outsideGValue;
11206 }
11207
11208 // c) set sumBodiesDist
11209 if(a_secondBodyId(cellId) > -1 && a_bodyIdG(cellId, 0) > -1 && fabs(distBody1[cellId]) < m_outsideGValue
11210 && fabs(distBody2[cellId]) < m_outsideGValue) {
11211 if(m_gapInitMethod == 0) {
11212 sumBodiesDist[cellId] = distBody1[cellId] + distBody2[cellId];
11213 } else {
11214 sumBodiesDist[cellId] = fabs(distBody1[cellId]) + fabs(distBody2[cellId]);
11215 }
11216
11217
11218 } else {
11219 // default-value
11220 if(m_gapInitMethod == 0) {
11221 sumBodiesDist[cellId] = -m_outsideGValue;
11222 } else {
11223 sumBodiesDist[cellId] = -2 * m_outsideGValue;
11224 }
11225 }
11226
11227 // d) set gapWidth
11228 if(m_gapInitMethod == 0) {
11229 // This unsymmetrical gap-behaviour concentrates gapCells in the gap-Area!
11230 // but is the main cause of gap-cell loos eventhough the gap is shrinking!
11231
11232 if(a_levelSetFunctionG(cellId, 0) > F0) {
11233 a_gapWidth(cellId) = sumBodiesDist[cellId];
11234 } else if(fabs(a_levelSetFunctionG(cellId, 0)) < eps1) {
11235 a_gapWidth(cellId) = sumBodiesDist[cellId];
11236 } else {
11237 a_gapWidth(cellId) = -m_outsideGValue;
11238 }
11239 } else {
11240 a_gapWidth(cellId) = sumBodiesDist[cellId];
11241 }
11242
11243 // Identifies if current cell is inside a gap
11244 const MBool isInsideGap = (fabs(a_gapWidth(cellId)) <= eps2 && a_potentialGapCell(cellId) > 0) ? true : false;
11245
11246 // e) set m_minGapWidth
11247 if(m_gapInitMethod > 0 && mode == 1) {
11248 // CAUTION: temporarily overwritting sumBodiesDist
11249 if(a_secondBodyId(cellId) > -1 && a_bodyIdG(cellId, 0) > -1 && fabs(distBody1[cellId]) < m_outsideGValue
11250 && fabs(distBody2[cellId]) < m_outsideGValue) {
11251 sumBodiesDist[cellId] = distBody1[cellId] + distBody2[cellId];
11252 } else {
11253 sumBodiesDist[cellId] = 2 * m_outsideGValue;
11254 }
11255
11256 if(a_potentialGapCell(cellId) && sumBodiesDist[cellId] <= eps2 && isInsideGap) {
11257 MInt regionId = a_potentialGapCellClose(cellId) - 2;
11258 ASSERT(regionId >= 0 && regionId < m_noGapRegions, to_string(regionId));
11259
11260 currentWidth = distBody1[cellId] + distBody2[cellId];
11261 /*
11262 if(distBody1[ cellId ] > F0 && distBody2[ cellId ] > F0 ) {
11263 currentWidth = distBody1[ cellId ] + distBody2[ cellId ];
11264 } else if (distBody1[ cellId ] * distBody2[ cellId ] < F0) {
11265 //sign change in levseSet-value, however, this doesn't mean that the bodies are overlapping!
11266
11267 currentWidth = distBody1[ cellId ] + distBody2[ cellId ];
11268 //currentWidth = mMin(distBody1[ cellId ], distBody2[ cellId ]);
11269 } else if (distBody1[ cellId ] < F0 && distBody2[ cellId ] < F0 ) {
11270 currentWidth = distBody1[ cellId ] + distBody2[ cellId ];
11271 }
11272 */
11273 if(currentWidth < m_minGapWidth[regionId]) {
11274 m_minGapWidth[regionId] = currentWidth;
11275 }
11276 }
11277 }
11278 }
11279
11280 } // loop over all cells
11281
11282 if(m_closeGaps && m_gapInitMethod > 0 && mode == 1) {
11283 MPI_Allreduce(MPI_IN_PLACE, &m_minGapWidth[0], m_noGapRegions, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_,
11284 "MPI_IN_PLACE", "m_minGapWidth[0]");
11285
11286 for(MInt region = 0; region < m_noGapRegions; region++) {
11287#if defined LS_DEBUG || !defined NDEBUG
11288 if(domainId() == 0 && m_minGapWidth[region] < 10 * m_outsideGValue) {
11289 cerr << "-->Min-Gap-Width at " << globalTimeStep << " for region " << region << " is "
11290 << m_minGapWidth[region] << " . Limit for Closure is: " << eps2 << endl;
11291 }
11292#endif
11293 if(domainId() == 0 && m_minGapWidth[region] < 0) {
11294 cerr << "Caution: overlapping levelSet-bodies in region " << region << " !" << endl;
11295 }
11296
11297 if(m_minGapWidth[region] < -eps2) {
11298 MFloat dif = -(m_minGapWidth[region] + eps2);
11299 if(domainId() == 0) cerr << "Caution: temporary increase in gapDeltaMin, from " << m_gapDeltaMin;
11300 m_gapDeltaMin = m_gapDeltaMin + 1.5 * dif;
11301 if(domainId() == 0) cerr << " to " << m_gapDeltaMin << endl;
11302 ASSERT(m_noGapRegions == 1, "ERROR: Increased gapDeltaMin not yet implemented for multiple-Gap-Regions!");
11303 // for this m_gapDeltaMin needs to be region-dependand!
11304 // However this also leads to a variable shift of the g0-field for the gap-closing!
11305 // This should best be done body-dependand!
11306 } else {
11307 m_gapDeltaMin = m_gapDeltaMinOrig;
11308 }
11309 }
11310 }
11311
11312
11313 } else if(mode == 0) { // set a_levelSetFunctionG in set 0
11314 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11315 a_levelSetFunctionG(cellId, 0) = a_levelSetFunctionG(cellId, 1);
11316 for(MInt set = 2; set < m_noSets; set++) {
11317 MFloat phi0 = a_levelSetFunctionG(cellId, 0);
11318 MFloat phi1 = a_levelSetFunctionG(cellId, set);
11319
11320 //
11321 if(phi0 >= F0 && phi1 >= F0) {
11322 phi0 = mMin(phi0, phi1);
11323 } else if(phi0 <= F0 && phi1 <= F0) {
11324 phi0 = -sqrt(phi0 * phi0 + phi1 * phi1);
11325 } else if(phi0 * phi1 <= F0) {
11326 if(phi0 < F0) {
11327 // phi0 = phi0;
11328 } else {
11329 phi0 = phi1;
11330 }
11331 }
11332
11333 a_levelSetFunctionG(cellId, 0) = phi0;
11334 }
11335 }
11336 } else {
11337 mTerm(1, AT_, "Unknown mode in buildCollectedLevelSet()");
11338 }
11339}
11340
11341template <MInt nDim>
11343 TRACE();
11344
11345 grid().findEqualLevelNeighborsParDiagonal(false);
11346
11347 //#######################################################################################################
11348 // Step 0: Initialize arrays and variables
11349 if(m_cellIsInDiffRegion != nullptr) {
11350 cout << "Deallocate m_cellIsInDiffRegion" << endl;
11351 mDeallocate(m_cellIsInDiffRegion);
11352 }
11353 if(m_correctedDistances != nullptr) {
11354 cout << "Deallocate m_correctedDistance" << endl;
11355 mDeallocate(m_correctedDistances);
11356 }
11357
11358 mAlloc(m_cellIsInDiffRegion, a_noCells(), "m_cellIsInDiffRegion", -2, AT_);
11359 mAlloc(m_correctedDistances, a_noCells(), (m_maxNoSets - m_startSet), "m_correctedDistances", F0, AT_);
11360 MFloatScratchSpace boundingBox(m_noInterpolationRegions * m_noDirs, AT_, "boundingBox");
11361 MFloatScratchSpace globalBoundingBox(2 * nDim, AT_, "globalBoundingBox");
11362 MFloatScratchSpace pointCoord(nDim, AT_, "pointCoord");
11363 MFloatScratchSpace allPointCoords(noDomains(), nDim, AT_, "allPointCoords");
11364 MFloat eps = 1e-16;
11365
11366 // How many cells are lying between the both static level sets
11367 m_geometry->getBoundingBox(globalBoundingBox.getPointer());
11368
11369 // Find cells in which the two level sets differ (only on leaf cell level).
11370 // Those areas are marked with -1. All other cells are initialize with -2.
11371 // The parent of a marked cell is also marked with the same value. If the
11372 // children of a cell have different values, i.e. -1 and -2, -1 is set for
11373 // the parent.
11374 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11375 if(!c_isLeafCell(cellId)) continue;
11376 MFloat phi1 = a_levelSetFunctionG(cellId, 1);
11377 MFloat phi2 = a_levelSetFunctionG(cellId, 2);
11378 MFloat deltaPhi = phi1 - phi2;
11379 if((fabs(deltaPhi) < eps)) {
11380 continue;
11381 } else {
11382 m_cellIsInDiffRegion[cellId] = -1;
11383 MBool reachedMinLevel = false;
11384 MInt parentId = cellId;
11385 while(!reachedMinLevel) {
11386 if(c_parentId(parentId) > -1) {
11387 parentId = c_parentId(parentId);
11388 if(m_cellIsInDiffRegion[parentId] < -1) {
11389 m_cellIsInDiffRegion[parentId] = -1;
11390 } else {
11391 reachedMinLevel = true;
11392 }
11393 } else {
11394 reachedMinLevel = true;
11395 ASSERT(a_level(parentId) == minLevel(), "This should not happen!");
11396 }
11397 }
11398 }
11399 }
11400
11401 //#######################################################################################################
11402 // Step 1: Find all regions with a level set difference automatically using the region growing method
11403 m_noInterpolationRegions = 0;
11404 MBool foundAllRegions = false;
11405 while(!foundAllRegions) {
11406 // Step 1a: Reset the point coordinates. A value outside the bounding box is used
11407 for(MInt d = 0; d < nDim; d++) {
11408 pointCoord(d) = globalBoundingBox(d + nDim) + 10.0 * c_cellLengthAtLevel(minLevel());
11409 }
11410
11411 // Step 1b: If there is still a cell lying in the "diff" region, set the
11412 // point coordinates to the coordinates of the cell
11413 // This is only done for leaf cells and non-halos
11414 for(MInt c = 0; c < grid().noLocalPartitionCells(); c++) {
11415 MInt cellId = grid().localPartitionCellLocalIds(c);
11416 if(cellId < 0) continue;
11417
11418 if(m_cellIsInDiffRegion[cellId] == -1) {
11419 for(MInt d = 0; d < nDim; d++) {
11420 pointCoord(d) = c_coordinate(cellId, d);
11421 cout << "Writing point for cell for domain " << domainId() << " and region " << m_noInterpolationRegions
11422 << ": " << pointCoord(d) << endl;
11423 }
11424 break;
11425 }
11426 }
11427
11428 // Step 1c: The point coordinates are exchanged
11429 for(MInt d = 0; d < nDim; d++) {
11430 allPointCoords(domainId(), d) = pointCoord(d);
11431 }
11432 MPI_Allgather(MPI_IN_PLACE, nDim, MPI_DOUBLE, &allPointCoords[0], nDim, MPI_DOUBLE, mpiComm(), AT_, "MPI_IN_PLACE",
11433 "allPointCoords");
11434
11435 // Step 1d: Check for all domains if there is a point which is not outside
11436 // of the bounding box (which is the initialized value)
11437 // If there is a cell on one process, this process starts the region
11438 // growing. If not there are no further regions and we can stop here
11439 foundAllRegions = true;
11440 for(MInt i = 0; i < noDomains(); i++) {
11441 MBool startPoint = true;
11442 for(MInt d = 0; d < nDim; d++) {
11443 if(allPointCoords(i, d) > globalBoundingBox(d + nDim)) startPoint = false;
11444 }
11445 if(startPoint) {
11446 for(MInt d = 0; d < nDim; d++) {
11447 pointCoord(d) = allPointCoords(i, d);
11448 }
11449 foundAllRegions = false;
11450 break;
11451 }
11452 }
11453 if(foundAllRegions) {
11454 break;
11455 }
11456
11457 // Step 1e: Find a start Cell in a not yet concidered modified region
11458 MInt startCell = -1;
11459 for(MInt i = 0; i < a_noCells(); i++) {
11460 if(a_isHalo(i)) continue;
11461 if(c_parentId(i) > -1) continue;
11462 if(m_cellIsInDiffRegion[i] != -1) continue;
11463
11464 MFloat halfLength = grid().cellLengthAtLevel(a_level(i)) * F1B2;
11465 MInt cnt = 0;
11466
11467 for(MInt d = 0; d < nDim; d++) {
11468 if(abs(c_coordinate(i, d) - pointCoord(d)) <= halfLength) cnt++;
11469 }
11470 if(cnt == nDim) {
11471 startCell = i;
11472 cout << "START Cell Found on process " << domainId() << endl;
11473 ASSERT(a_level(startCell) == minLevel(), "This should not happen!!!");
11474 break;
11475 }
11476 }
11477
11478 // Step 1f: Use the region growing to find all connected cells of the start cell
11479 // Thus all cells belonging to the region can be found
11480 if(startCell > -1) {
11481 regionGrowing(startCell, m_noInterpolationRegions);
11482 }
11483
11484 // Step 1g: In case of parallel simulations, the region growing has to be communicated
11485 if(noDomains() > 1) {
11486 // prepare communication
11487 MIntScratchSpace noSendWindowPerDomain(noNeighborDomains(), AT_, "noSendWindowPerDomain");
11488 MIntScratchSpace noReceiveHaloPerDomain(noNeighborDomains(), AT_, "noReceiveHaloPerDomain");
11489 for(MInt d = 0; d < noNeighborDomains(); d++) {
11490 noSendWindowPerDomain[d] = noWindowCells(d);
11491 ASSERT(noSendWindowPerDomain[d] >= 0, "noSendWindowPerDomain[d] < 0");
11492 }
11493 for(MInt d = 0; d < noNeighborDomains(); d++) {
11494 noReceiveHaloPerDomain[d] = noHaloCells(d);
11495 ASSERT(noReceiveHaloPerDomain[d] >= 0, "noReceiveHaloPerDomain[d] < 0");
11496 }
11497
11498 MInt allSend = 0;
11499 MInt allReceive = 0;
11500 vector<MInt> offsetsSend;
11501 vector<MInt> offsetsReceive;
11502 for(MInt dom = 0; dom < noNeighborDomains(); dom++) {
11503 offsetsSend.push_back(allSend);
11504 offsetsReceive.push_back(allReceive);
11505 allSend += noSendWindowPerDomain[dom];
11506 allReceive += noReceiveHaloPerDomain[dom];
11507 }
11508
11509 MInt noChanges = 1;
11510 MInt noIterations = 0;
11511 while(noChanges != 0) {
11512 noChanges = 0;
11513
11514 MIntScratchSpace sndBufWin(allSend, AT_, "sndBufWin");
11515 MIntScratchSpace rcvBufHalo(allReceive, AT_, "rcvBufHalo");
11516
11517 MPI_Request* mpi_request_;
11518 mAlloc(mpi_request_, noNeighborDomains(), "mpi_request_", AT_);
11519
11520 for(MInt d = 0; d < noNeighborDomains(); d++) {
11521 if(noSendWindowPerDomain[d] > 0) {
11522 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++) {
11523 sndBufWin[offsetsSend[d] + c] = m_cellIsInDiffRegion[windowCellId(d, c)];
11524 }
11525 MPI_Issend(&(sndBufWin[offsetsSend[d]]), noSendWindowPerDomain[d], MPI_INT, neighborDomain(d), 0, mpiComm(),
11526 &mpi_request_[d], AT_, "(sndBufWin[offsetsSend[d]])");
11527 }
11528 }
11529 MPI_Status status_;
11530 for(MInt d = 0; d < noNeighborDomains(); d++) {
11531 if(noReceiveHaloPerDomain[d] > 0) {
11532 MPI_Recv(&(rcvBufHalo[offsetsReceive[d]]), noReceiveHaloPerDomain[d], MPI_INT, neighborDomain(d), 0,
11533 mpiComm(), &status_, AT_, "(rcvBufHalo[offsetsReceive[d]])");
11534 }
11535 }
11536
11537 for(MInt d = 0; d < noNeighborDomains(); d++) {
11538 if(noReceiveHaloPerDomain[d] > 0 && noSendWindowPerDomain[d] > 0) {
11539 MPI_Wait(&mpi_request_[d], &status_, AT_);
11540 }
11541 }
11542
11543 for(MInt d = 0; d < noNeighborDomains(); d++) {
11544 if(noReceiveHaloPerDomain[d] > 0) {
11545 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
11546 const MInt halo = haloCellId(d, c);
11547 if(c_parentId(halo) > -1) continue;
11548 ASSERT(a_level(halo) == minLevel(), "This should not happen!!!!");
11549 if((rcvBufHalo[c + offsetsReceive[d]] == m_noInterpolationRegions)
11550 && (m_cellIsInDiffRegion[halo] == -1)) {
11551 regionGrowing(halo, m_noInterpolationRegions);
11552 noChanges++;
11553 }
11554 }
11555 }
11556 }
11557 // Are there still changes in the process, if yes, start all over again with the communication
11558 MPI_Allreduce(MPI_IN_PLACE, &noChanges, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "noChanges");
11559 mDeallocate(mpi_request_);
11560 noIterations++;
11561 }
11562 cout << "NO CHANGES " << noIterations << " " << m_noInterpolationRegions << endl;
11563 }
11564 m_noInterpolationRegions++;
11565 }
11566
11567 cout << "m_noInterpolationRegions " << m_noInterpolationRegions << endl;
11568 // Find cells in which the two level sets differ (only on leaf cell level).
11569 // Those areas are marked with -1. All other cells are initialize with -2.
11570 // The parent of a marked cell is also marked with the same value. If the
11571 // children of a cell have different values, i.e. -1 and -2, -1 is set for
11572 // the parent.
11573 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11574 if(c_parentId(cellId) > -1) continue;
11575 ASSERT(m_cellIsInDiffRegion[cellId] != -1, "It seems like some minLevel cells were skipped!");
11576 if(m_cellIsInDiffRegion[cellId] < 0) continue;
11577 for(MInt c = 0; c < c_noChildren(cellId); c++) {
11578 if(c_childId(cellId, c) < 0) continue;
11579 setChildRegions(c_childId(cellId, c), m_cellIsInDiffRegion[cellId]);
11580 }
11581 }
11582
11583 if(noDomains() > 1) {
11584 // prepare communication
11585 MIntScratchSpace noSendWindowPerDomain(noNeighborDomains(), AT_, "noSendWindowPerDomain");
11586 MIntScratchSpace noReceiveHaloPerDomain(noNeighborDomains(), AT_, "noReceiveHaloPerDomain");
11587 for(MInt d = 0; d < noNeighborDomains(); d++) {
11588 noSendWindowPerDomain[d] = noWindowCells(d);
11589 ASSERT(noSendWindowPerDomain[d] >= 0, "noSendWindowPerDomain[d] < 0");
11590 }
11591 for(MInt d = 0; d < noNeighborDomains(); d++) {
11592 noReceiveHaloPerDomain[d] = noHaloCells(d);
11593 ASSERT(noReceiveHaloPerDomain[d] >= 0, "noReceiveHaloPerDomain[d] < 0");
11594 }
11595
11596 MInt allSend = 0;
11597 MInt allReceive = 0;
11598 vector<MInt> offsetsSend;
11599 vector<MInt> offsetsReceive;
11600 for(MInt dom = 0; dom < noNeighborDomains(); dom++) {
11601 offsetsSend.push_back(allSend);
11602 offsetsReceive.push_back(allReceive);
11603 allSend += noSendWindowPerDomain[dom];
11604 allReceive += noReceiveHaloPerDomain[dom];
11605 }
11606
11607 MIntScratchSpace sndBufWin(allSend, AT_, "sndBufWin");
11608 MIntScratchSpace rcvBufHalo(allReceive, AT_, "rcvBufHalo");
11609
11610 MPI_Request* mpi_request_;
11611 mAlloc(mpi_request_, noNeighborDomains(), "mpi_request_", AT_);
11612
11613 for(MInt d = 0; d < noNeighborDomains(); d++) {
11614 if(noSendWindowPerDomain[d] > 0) {
11615 for(MInt c = 0; c < noSendWindowPerDomain[d]; c++) {
11616 sndBufWin[offsetsSend[d] + c] = m_cellIsInDiffRegion[windowCellId(d, c)];
11617 }
11618 MPI_Issend(&(sndBufWin[offsetsSend[d]]), noSendWindowPerDomain[d], MPI_INT, neighborDomain(d), 0, mpiComm(),
11619 &mpi_request_[d], AT_, "(sndBufWin[offsetsSend[d]])");
11620 }
11621 }
11622 MPI_Status status_;
11623 for(MInt d = 0; d < noNeighborDomains(); d++) {
11624 if(noReceiveHaloPerDomain[d] > 0) {
11625 MPI_Recv(&(rcvBufHalo[offsetsReceive[d]]), noReceiveHaloPerDomain[d], MPI_INT, neighborDomain(d), 0, mpiComm(),
11626 &status_, AT_, "(rcvBufHalo[offsetsReceive[d]])");
11627 }
11628 }
11629
11630 for(MInt d = 0; d < noNeighborDomains(); d++) {
11631 if(noReceiveHaloPerDomain[d] > 0 && noSendWindowPerDomain[d] > 0) {
11632 MPI_Wait(&mpi_request_[d], &status_, AT_);
11633 }
11634 }
11635
11636 for(MInt d = 0; d < noNeighborDomains(); d++) {
11637 if(noReceiveHaloPerDomain[d] > 0) {
11638 for(MInt c = 0; c < noReceiveHaloPerDomain[d]; c++) {
11639 const MInt halo = haloCellId(d, c);
11640 m_cellIsInDiffRegion[halo] = rcvBufHalo[c + offsetsReceive[d]];
11641 }
11642 }
11643 }
11644 }
11645 //#######################################################################################################
11646 // Step 2: Initialize the array containing the coorectedDistances in case the band
11647 // width is not set high enough
11648
11649 if(mode == 0) {
11650 m_refinedCells.clear();
11651 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11652 if(!c_isLeafCell(cellId)) continue;
11653 if(!a_isHalo(cellId)) {
11654 if(m_cellIsInDiffRegion[cellId] >= 0) {
11655 m_refinedCells.insert(make_pair(cellId, 0));
11656 }
11657 }
11658 }
11659 }
11660
11661 MInt noRefinedBandCells = (signed)m_refinedCells.size();
11662 MPI_Allreduce(MPI_IN_PLACE, &noRefinedBandCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
11663 "noRefinedBandCells");
11664
11665 // On the fly reconstruction of levelset band cells outside the G0 Set!
11666 cerr << "Reinitialisation of " << noRefinedBandCells << " cells " << endl;
11667 if(noRefinedBandCells > 0) {
11668 m_startSet = 1;
11669 // construct old-LevelSet data based on shifted geometry!
11670 constructGFieldFromSTL(4);
11671
11672 exchangeDataLS(&(a_oldLevelSetFunctionG(0, 0)), m_maxNoSets);
11673
11674 // copy old levelset to levelset for stationary bodies
11675 for(auto& m_refinedCell : m_refinedCells) {
11676 const MInt cellId = m_refinedCell.first;
11677 ASSERT(!a_isHalo(cellId), "");
11678 for(MInt setI = m_startSet; setI < m_noSets; setI++) {
11679 a_levelSetFunctionG(cellId, setI) = a_oldLevelSetFunctionG(cellId, setI);
11680 }
11681 }
11682
11683 for(MInt lvl = maxLevel() - 1; lvl >= minLevel(); lvl--) {
11684 for(MInt cell = 0; cell < a_noCells(); cell++) {
11685 for(MInt set = 1; set < m_maxNoSets; set++) {
11686 if(a_level(cell) != lvl) continue;
11687 MFloat levelSetCoarse = F0;
11688 if(c_noChildren(cell) > 0) {
11689 for(MInt child = 0; child < IPOW2(nDim); child++) {
11690 if(c_childId(cell, child) < 0) continue;
11691 levelSetCoarse += a_levelSetFunctionG(c_childId(cell, child), set);
11692 }
11693 a_levelSetFunctionG(cell, set) = levelSetCoarse / (MFloat)c_noChildren(cell);
11694 }
11695 }
11696 }
11697 }
11698
11699 exchangeLevelSet();
11700
11701 m_refinedCells.clear();
11702
11703 m_startSet = 0;
11704 }
11705
11706 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11707 MFloat phi1 = a_levelSetFunctionG(cellId, 1);
11708 MFloat phi2 = a_levelSetFunctionG(cellId, 2);
11709 m_correctedDistances[cellId][0] = phi1;
11710 m_correctedDistances[cellId][1] = phi2;
11711 }
11712
11713 MFloat xCurrent[3] = {F0, F0, F0};
11714 for(MInt set = m_startSet; set < m_noSets; set++) {
11715 if(!m_computeSet_backup[set]) continue;
11716 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
11717 const MInt body = m_setToBodiesTable[set][b];
11718 computeBodyPropertiesForced(1, xCurrent, body, time() + timeStep());
11719 }
11720 }
11721}
11722
11723template <MInt nDim>
11725 TRACE();
11726
11727 if(m_cellIsInDiffRegion[cellId] == -1) {
11728 m_cellIsInDiffRegion[cellId] = region;
11729
11730 for(MInt n = 0; n < IPOW3[nDim] - 1; n++) {
11731 if(grid().neighborList(cellId, n) < 0) continue;
11732 if(m_cellIsInDiffRegion[grid().neighborList(cellId, n)] != -1) continue;
11733 regionGrowing(grid().neighborList(cellId, n), region);
11734 }
11735 }
11736}
11737
11738template <MInt nDim>
11740 TRACE();
11741
11742 if(m_cellIsInDiffRegion[cellId] == -1) {
11743 m_cellIsInDiffRegion[cellId] = region;
11744
11745 for(MInt c = 0; c < c_noChildren(cellId); c++) {
11746 if(c_childId(cellId, c) < 0) continue;
11747 setChildRegions(c_childId(cellId, c), region);
11748 }
11749 }
11750}
11751
11752//----------------------------------------------------------------------------
11753
11754
11771template <MInt nDim>
11773 TRACE();
11774
11775 if(m_noSets < 2) {
11776 return;
11777 }
11778 ASSERT(m_buildCollectedLevelSetFunction, "");
11779
11780 MInt noCells = -1;
11781 if(mode)
11782 noCells = a_noCells();
11783 else
11784 noCells = a_noBandCells(0);
11785
11786 for(MInt i = 0; i < noCells; i++) {
11787 MInt cellId = -1;
11788 if(mode) {
11789 cellId = i;
11790 } else {
11791 cellId = a_bandCellId(i, 0);
11792 }
11793 if(a_nearGapG(cellId) > 0 && a_potentialGapCellClose(cellId)) continue;
11794 a_levelSetFunctionG(cellId, 0) = a_levelSetFunctionG(cellId, 1);
11795
11796 for(MInt set = 2; set < m_noSets; set++) {
11797 MFloat phi0 = a_levelSetFunctionG(cellId, 0);
11798 MFloat phi1 = a_levelSetFunctionG(cellId, set);
11799
11800 if(phi0 >= F0 && phi1 >= F0) {
11801 phi0 = mMin(phi0, phi1);
11802 } else if(phi0 <= F0 && phi1 <= F0) {
11803 phi0 = -sqrt(phi0 * phi0 + phi1 * phi1);
11804 } else if(phi0 * phi1 <= F0) {
11805 if(phi0 < F0) {
11806 // phi0 = phi0;
11807 } else {
11808 phi0 = phi1;
11809 }
11810 }
11811
11812 a_levelSetFunctionG(cellId, 0) = phi0;
11813 }
11814 }
11815}
11816
11817
11818//----------------------------------------------------------------------------
11819
11830template <MInt nDim>
11832 TRACE();
11833
11834 if(!m_closeGaps) return;
11835
11836 MIntScratchSpace gapCells(a_noCells(), AT_, "gapCells");
11837 MIntScratchSpace lastLayer(a_noCells(), AT_, "lastLayer");
11838 MBoolScratchSpace isInsideGap(a_noCells(), AT_, "isInsideGap");
11839 MBoolScratchSpace isInsideGapTmp(a_noCells(), AT_, "isInsideGapTmp");
11840 stack<MInt> gapStack;
11841
11842 // same as eps2 used in buildCollectedLevelSet()
11843 const MFloat eps = c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * m_gapDeltaMin;
11844
11845 const MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * (5.0 / 4.0 * sqrt(nDim)) * m_gapDeltaMin;
11846 const MFloat eps3 = (m_gapInitMethod < 2)
11847 ? c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * (1.5 + m_gapDeltaMin)
11848 : c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * (2.5 + m_gapDeltaMin);
11849
11850 MInt maxNoLayers = mMax(6, m_gBandWidth);
11851
11852 // MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
11853 // MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
11854
11855 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
11856
11857 //-------------------------
11858
11859 // b) reset gap-statistics
11860 m_noOldGapCells = m_noGapCells;
11861 m_noGapCells = 0;
11862 MInt gapCellCounter = 0;
11863 MInt cellsAdded = 1;
11864
11865 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
11866 isInsideGap(cellId) = false;
11867 // Identifies cells inside a gap
11868 if((fabs(a_gapWidth(cellId)) <= eps && a_potentialGapCell(cellId) > 0)
11869 && a_inBandG(cellId, 0)) { // only if cell is inside the G0-Band
11870 isInsideGap(cellId) = true;
11871 }
11872 isInsideGapTmp(cellId) = false;
11873 a_nearGapG(cellId) = false;
11874 }
11875
11876 MBoolScratchSpace forceNoGaps(m_noGapRegions, AT_, "forceNoGaps");
11877 MIntScratchSpace surpressingGaps(m_noGapRegions, AT_, "surpressingGaps");
11878
11879 for(MInt region = 0; region < m_noGapRegions; region++) {
11880 forceNoGaps[region] = false;
11881 surpressingGaps[region] = 0;
11882 if(m_forceNoGaps > 0) {
11883 // specify time or crank-angle for which gap-Cells are surpressed!
11884 // -> ensures a clean gapOpneing!
11885 const MFloat elapsedTime = time();
11886 const MFloat cad = crankAngle(elapsedTime, 0);
11887 if(((m_gapSign[region] < F0 && (cad > m_gapAngleOpen[region] || cad < m_gapAngleClose[region]))
11888 || (m_gapSign[region] > F0 && cad > m_gapAngleOpen[region] && cad < m_gapAngleClose[region]))
11889 && m_forceNoGaps == 1) {
11890 forceNoGaps[region] = true;
11891 } else if(m_forceNoGaps == 2
11892 && ((cad > m_gapAngleOpen[region] && cad < m_gapAngleClose[region])
11893 || (cad > m_gapAngleOpen[region + 1] && cad < m_gapAngleClose[region + 1]))) {
11894 forceNoGaps[region] = true;
11895 }
11896 }
11897 }
11898
11899 // c) add all isInsideGap-Cells to the gapStack and set a_nearGapG
11900 for(MInt id = 0; id < a_noBandCells(0); id++) {
11901 MInt cellId = a_bandCellId(id, 0);
11902 if(isInsideGap(cellId)) {
11903 const MInt region = a_potentialGapCellClose(cellId) - 2;
11904 if(m_forceNoGaps > 0 && forceNoGaps[region]) {
11905 surpressingGaps[region]++;
11906 continue;
11907 }
11908 gapStack.push(cellId);
11909 isInsideGapTmp(cellId) = true;
11910 m_noGapCells++;
11911 gapCells.p[gapCellCounter++] = cellId;
11912 a_nearGapG(cellId) = true;
11913 }
11914 }
11915
11916 if(m_forceNoGaps > 0) {
11917#if defined LS_DEBUG || !defined NDEBUG
11918
11919 MPI_Allreduce(MPI_IN_PLACE, &surpressingGaps, m_noGapRegions, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
11920 "surpressingGaps");
11921 if(domainId() == 0) {
11922 for(MInt region = 0; region < m_noGapRegions; region++) {
11923 if(surpressingGaps[region] > 0)
11924 cerr << "Surpressing " << surpressingGaps[region] << " gap-Cells in region " << region << endl;
11925 }
11926 }
11927#endif
11928 }
11929
11930 // d) add all neighbors of all gapStack-Cells within the gapWidth to the gapCell-List!
11931 while(cellsAdded) {
11932 cellsAdded = 0;
11933
11934 if(gapCellCounter) {
11935 while(!gapStack.empty()) {
11936 MInt gCellId = gapStack.top();
11937 gapStack.pop();
11938 for(MInt dir = 0; dir < m_noDirs; dir++) {
11939 MInt nghbrId = c_neighborId(gCellId, dir);
11940 if(nghbrId == -1) continue;
11941 if(a_isHalo(nghbrId)) continue;
11942 if(!a_potentialGapCell(nghbrId)) continue;
11943
11944 if(m_gapInitMethod == 0) {
11945 if(abs(a_gapWidth(nghbrId)) <= eps2 && a_gapWidth(nghbrId) >= F0 && !isInsideGapTmp(nghbrId)) {
11946 gapCells.p[gapCellCounter++] = nghbrId;
11947 isInsideGapTmp(nghbrId) = true;
11948 m_noGapCells++;
11949 a_nearGapG(nghbrId) = true;
11950 gapStack.push(nghbrId);
11951 cellsAdded++;
11952 }
11953
11954 } else {
11955 const MInt region = a_potentialGapCellClose(nghbrId) - 2;
11956 if(m_forceNoGaps > 0 && forceNoGaps[region]) continue;
11957
11958
11959 if(a_gapWidth(nghbrId) >= F0 && !isInsideGapTmp(nghbrId) && a_gapWidth(nghbrId) <= eps3) {
11960 // Timw: limit eps3
11961 // before: no upper-limit!
11962 gapCells.p[gapCellCounter++] = nghbrId;
11963 isInsideGapTmp(nghbrId) = true;
11964 m_noGapCells++;
11965 a_nearGapG(nghbrId) = true;
11966 gapStack.push(nghbrId);
11967 cellsAdded++;
11968 }
11969 }
11970 }
11971 }
11972 }
11973
11974 MPI_Allreduce(MPI_IN_PLACE, &cellsAdded, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "cellsAdded");
11975
11976 // add Halo-Cells to the gap-Stack and List
11977 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
11978 for(MInt j = 0; j < noWindowCells(i); j++) {
11979 tmp_data(windowCellId(i, j)) = isInsideGapTmp(windowCellId(i, j));
11980 }
11981 }
11982 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
11983 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
11984 MInt windowId = grid().azimuthalWindowCell(i, j);
11985 tmp_data(windowId) = isInsideGapTmp(windowId);
11986 }
11987 }
11988
11989 exchangeDataLS(&tmp_data(0), 1);
11990
11991 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
11992 for(MInt j = 0; j < noHaloCells(i); j++) {
11993 const MInt haloCell = haloCellId(i, j);
11994 if(!isInsideGapTmp(haloCell)) {
11995 isInsideGapTmp(haloCell) = tmp_data(haloCell);
11996 if(isInsideGapTmp(haloCell)) {
11997 m_noGapCells++;
11998 gapCells.p[gapCellCounter++] = haloCell;
11999 a_nearGapG(haloCell) = true;
12000 gapStack.push(haloCell);
12001 }
12002 }
12003 }
12004 }
12005 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
12006 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
12007 const MInt haloCell = grid().azimuthalHaloCell(i, j);
12008 if(!isInsideGapTmp(haloCell)) {
12009 isInsideGapTmp(haloCell) = tmp_data(haloCell);
12010 if(isInsideGapTmp(haloCell)) {
12011 m_noGapCells++;
12012 gapCells.p[gapCellCounter++] = haloCell;
12013 a_nearGapG(haloCell) = true;
12014 gapStack.push(haloCell);
12015 }
12016 }
12017 }
12018 }
12019 }
12020
12021
12022 if(m_gapInitMethod == 0) {
12023 MPI_Allreduce(MPI_IN_PLACE, &gapCellCounter, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "gapCellCounter");
12024
12025 // f) add additional Cells to the gap-Cell-List
12026 if(gapCellCounter) {
12027 gapCellCounter = 0;
12028 MInt layerCount = 2;
12029
12030 // first added to the local gapCells-counter
12031 for(MInt id = 0; id < a_noBandCells(0); id++) {
12032 MInt cellId = a_bandCellId(id, 0);
12033 if(a_nearGapG(cellId)) {
12034 gapCells.p[gapCellCounter++] = cellId;
12035 }
12036 }
12037
12038 while(layerCount < maxNoLayers) {
12039 MInt layerCells = 0;
12040 for(MInt gc = 0; gc < gapCellCounter; gc++) {
12041 MInt gCellId = gapCells.p[gc];
12042 for(MInt dir = 0; dir < m_noDirs; dir++) {
12043 if(!a_hasNeighbor(gCellId, dir)) continue;
12044 MInt nghbrId = c_neighborId(gCellId, dir);
12045 if(a_isHalo(nghbrId)) continue;
12046 if(!a_nearGapG(nghbrId)) {
12047 lastLayer.p[layerCells++] = nghbrId;
12048 a_nearGapG(nghbrId) = layerCount;
12049 m_noGapCells++;
12050 }
12051 }
12052 }
12053
12054 // exchange a_nearGapG-information
12055 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12056 for(MInt j = 0; j < noWindowCells(i); j++) {
12057 tmp_data(windowCellId(i, j)) = a_nearGapG(windowCellId(i, j));
12058 }
12059 }
12060 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
12061 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
12062 MInt windowId = grid().azimuthalWindowCell(i, j);
12063 tmp_data(windowId) = a_nearGapG(windowId);
12064 }
12065 }
12066
12067 exchangeDataLS(&tmp_data(0), 1);
12068
12069 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12070 for(MInt j = 0; j < noHaloCells(i); j++) {
12071 const MInt haloCell = haloCellId(i, j);
12072 if(!a_nearGapG(haloCell)) {
12073 a_nearGapG(haloCell) = tmp_data(haloCell);
12074 if(a_nearGapG(haloCell)) {
12075 lastLayer.p[layerCells++] = haloCell;
12076 m_noGapCells++;
12077 }
12078 }
12079 }
12080 }
12081 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
12082 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
12083 const MInt haloCell = grid().azimuthalHaloCell(i, j);
12084 if(!a_nearGapG(haloCell)) {
12085 a_nearGapG(haloCell) = tmp_data(haloCell);
12086 if(a_nearGapG(haloCell)) {
12087 lastLayer.p[layerCells++] = haloCell;
12088 m_noGapCells++;
12089 }
12090 }
12091 }
12092 }
12093
12094 for(MInt lc = 0; lc < layerCells; lc++) {
12095 gapCells.p[lc] = lastLayer.p[lc];
12096 }
12097 gapCellCounter = layerCells;
12098 layerCount++;
12099 }
12100 }
12101 }
12102}
12103
12104
12105//----------------------------------------------------------------------------
12106
12107
12118template <MInt nDim>
12120 TRACE();
12121
12122 // MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * (1.0 + sqrt(nDim)/2.0);
12123 // MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * (1.0 + sqrt(2.0)/2.0);
12124
12125 const MFloat eps2 = (m_gapInitMethod < 2)
12126 ? c_cellLengthAtLevel(a_maxGCellLevel(0)) * (5.0 / 4.0 * sqrt(nDim)) * m_gapDeltaMin * 0.51
12127 : c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * m_gapDeltaMin;
12128
12129 if(gapCellsExist()) {
12130 for(MInt id = 0; id < a_noBandCells(0); id++) {
12131 MInt cellId = a_bandCellId(id, 0);
12132 a_levelSetFunctionG(cellId, 0) -= eps2;
12133 }
12134 for(MInt id = 0; id < a_noBandCells(1); id++) {
12135 MInt cellId = a_bandCellId(id, 1);
12136 if(a_inBandG(cellId, 0)) continue;
12137 a_levelSetFunctionG(cellId, 0) -= eps2;
12138 }
12139 }
12140}
12141
12142
12143//----------------------------------------------------------------------------
12144
12145
12153template <MInt nDim>
12155 TRACE();
12156
12157 MInt noGapCells = m_noGapCells;
12158 MPI_Allreduce(MPI_IN_PLACE, &noGapCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "noGapCells");
12159 return noGapCells;
12160}
12161
12162
12163//----------------------------------------------------------------------------
12164
12165
12173template <MInt nDim>
12175 TRACE();
12176
12177 return m_noGapCells;
12178}
12179
12180//----------------------------------------------------------------------------
12181
12182
12193template <MInt nDim>
12195 TRACE();
12196
12197 // MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * (1.0 + sqrt(nDim)/2.0);
12198 // MFloat eps2 = c_cellLengthAtLevel(a_maxGCellLevel(0)) * (1.0 + sqrt(2.0)/2.0);
12199
12200 const MFloat eps2 = (m_gapInitMethod < 2)
12201 ? c_cellLengthAtLevel(a_maxGCellLevel(0)) * (5.0 / 4.0 * sqrt(nDim)) * m_gapDeltaMin * 0.51
12202 : c_cellLengthAtLevel(a_maxGCellLevel(0)) * sqrt(nDim) * m_gapDeltaMin;
12203
12204
12205 if(gapCellsExist()) {
12206 for(MInt id = 0; id < a_noBandCells(0); id++) {
12207 MInt cellId = a_bandCellId(id, 0);
12208 a_levelSetFunctionG(cellId, 0) += eps2;
12209 }
12210
12211 for(MInt id = 0; id < a_noBandCells(1); id++) {
12212 MInt cellId = a_bandCellId(id, 1);
12213 if(a_inBandG(cellId, 0)) continue;
12214 a_levelSetFunctionG(cellId, 0) += eps2;
12215 }
12216 }
12217}
12218
12219
12220//---------------------------------------------------------------------------
12221
12229template <MInt nDim>
12231 TRACE();
12232
12233 // set compute set identification (previously, all set to 1 for initialization, now set to real values)
12234 // Timw: now moved to a later position in prepareLevelSet
12235 // as this function is currently called in the initial-refinement-part!
12236 if(!m_levelSetMb) {
12237 for(MInt set = 0; set < m_noSets; set++)
12238 m_computeSet[set] = m_computeSet_tmp[set];
12239 }
12240
12241 if(m_buildCollectedLevelSetFunction) {
12242 setUpPotentialGapCells();
12243
12244 // during initialisation, startSet needs to be zero
12245 // only afterwards it is increased for buildCollectedLevelSet!
12246 // ASSERT(m_startSet == 0, " " );
12247 // m_startSet = 1;
12248
12249 } else {
12250 if(m_maxNoSets > 1 || m_GFieldInitFromSTL) {
12251 MInt body = -1;
12252 for(MInt set = 0; set < m_noSets; set++) {
12253 if(m_noBodiesInSet[set] > 0) body = m_setToBodiesTable[set][0];
12254 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
12255 a_bodyIdG(cellId, set) = body;
12256 }
12257 }
12258 } else {
12259 for(MInt set = 0; set < m_noSets; set++) {
12260 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
12261 a_bodyIdG(cellId, set) = 0;
12262 }
12263 }
12264 }
12265 }
12266}
12267
12268
12269//---------------------------------------------------------------------------
12270
12271
12282template <MInt nDim>
12284 TRACE();
12285
12286 if(!m_closeGaps) return;
12287
12288 // 1) Allocate potential gap cell arrays
12289 MBool& first = m_static_setUpPotentialGapCells_first;
12290 MFloat(&normal)[s_maxNoEmbeddedBodies * 3] = m_static_setUpPotentialGapCells_normal;
12291 MFloat(&center)[s_maxNoEmbeddedBodies * 3] = m_static_setUpPotentialGapCells_center;
12292 MFloat(&radius)[s_maxNoEmbeddedBodies] = m_static_setUpPotentialGapCells_radius;
12293 MFloat(&height)[s_maxNoEmbeddedBodies] = m_static_setUpPotentialGapCells_height;
12294 MFloat(&normalClose)[s_maxNoEmbeddedBodies * 3] = m_static_setUpPotentialGapCells_normalClose;
12295 MFloat(&centerClose)[s_maxNoEmbeddedBodies * 3] = m_static_setUpPotentialGapCells_centerClose;
12296 MFloat(&radiusClose)[s_maxNoEmbeddedBodies] = m_static_setUpPotentialGapCells_radiusClose;
12297 MFloat(&heightClose)[s_maxNoEmbeddedBodies] = m_static_setUpPotentialGapCells_heightClose;
12298 MInt(&bodyClose)[s_maxNoEmbeddedBodies] = m_static_setUpPotentialGapCells_bodyClose;
12299 MInt& noGapRegionsClose = m_static_setUpPotentialGapCells_noGapRegionsClose;
12300
12301 MFloat rVec[3], hVec[3];
12302 if(first) {
12303 if(m_noBodyBndryCndIds > s_maxNoEmbeddedBodies) {
12304 mTerm(1, AT_, "Error: Too many embedded Bodies!");
12305 }
12306
12307 // 2) Initialize potential gap cell arrays
12308 for(MInt body = 0; body < s_maxNoEmbeddedBodies; body++) {
12309 for(MInt dir = 0; dir < nDim; dir++) {
12310 normal[body * nDim + dir] = F0;
12311 center[body * nDim + dir] = F0;
12312 normalClose[body * nDim + dir] = F0;
12313 centerClose[body * nDim + dir] = F0;
12314 }
12315 radius[body] = 1.0;
12316 height[body] = 1.0;
12317 radiusClose[body] = 1.0;
12318 heightClose[body] = 1.0;
12319 normal[body * nDim + 0] = 1.0;
12320 normalClose[body * nDim + 0] = 1.0;
12321 bodyClose[body] = -1;
12322 }
12323
12324 // 3) Read potential gap cell properties
12325
12336 for(MInt i = 0; i < m_noGapRegions; i++) {
12337 for(MInt j = 0; j < nDim; j++) {
12338 normal[i * nDim + j] = Context::getSolverProperty<MFloat>("gapRegionNormals", m_solverId, AT_,
12339 &normal[i * nDim + j], i * nDim + j);
12340 }
12341 }
12342
12353 for(MInt i = 0; i < m_noGapRegions; i++) {
12354 for(MInt j = 0; j < nDim; j++) {
12355 center[i * nDim + j] = Context::getSolverProperty<MFloat>("gapRegionCenters", m_solverId, AT_,
12356 &center[i * nDim + j], i * nDim + j);
12357 }
12358 }
12367 for(MInt i = 0; i < m_noGapRegions; i++)
12368 radius[i] = Context::getSolverProperty<MFloat>("gapRegionRadii", m_solverId, AT_, &radius[i], i);
12369
12370
12371 for(MInt i = 0; i < m_noGapRegions; i++)
12372 height[i] = Context::getSolverProperty<MFloat>("gapRegionHeights", m_solverId, AT_, &height[i], i);
12373
12374
12386 noGapRegionsClose = 0;
12387 noGapRegionsClose = Context::getSolverProperty<MInt>("noGapRegionsClose", m_solverId, AT_, &noGapRegionsClose);
12388 ASSERT(noGapRegionsClose <= m_noEmbeddedBodies, "");
12389
12390 for(MInt i = 0; i < noGapRegionsClose; i++)
12391 for(MInt j = 0; j < nDim; j++)
12392 normalClose[i * nDim + j] = Context::getSolverProperty<MFloat>("gapRegionNormalsClose", m_solverId, AT_,
12393 &normalClose[i * nDim + j], i * nDim + j);
12394
12395 for(MInt i = 0; i < noGapRegionsClose; i++)
12396 for(MInt j = 0; j < nDim; j++)
12397 centerClose[i * nDim + j] = Context::getSolverProperty<MFloat>("gapRegionCentersClose", m_solverId, AT_,
12398 &centerClose[i * nDim + j], i * nDim + j);
12399
12400
12409 for(MInt i = 0; i < noGapRegionsClose; i++)
12410 radiusClose[i] = Context::getSolverProperty<MFloat>("gapRegionRadiiClose", m_solverId, AT_, &radiusClose[i], i);
12411
12412
12424 for(MInt i = 0; i < noGapRegionsClose; i++)
12425 heightClose[i] = Context::getSolverProperty<MFloat>("gapRegionHeightsClose", m_solverId, AT_, &heightClose[i], i);
12426
12427
12439 for(MInt i = 0; i < m_noGapRegions; i++) {
12440 bodyClose[i] = Context::getSolverProperty<MInt>("gapRegionBodyClose", m_solverId, AT_, &bodyClose[i], i);
12441 ASSERT(bodyClose[i] + 1 <= m_noEmbeddedBodies, "");
12442 }
12443
12444 first = false;
12445 }
12446
12447 ASSERT(m_closeGaps, "");
12448
12449 // 4) Loop over all cells and fill the arrays!
12450
12451 for(MInt gCellId = 0; gCellId < a_noCells(); gCellId++) {
12452 // 4.1) Initilised with zero
12453 a_potentialGapCell(gCellId) = 0;
12454 a_potentialGapCellClose(gCellId) = 0;
12455
12456 if(a_level(gCellId) == a_maxGCellLevel(0)) {
12457 for(MInt region = 0; region < m_noGapRegions; region++) {
12458 MFloat hCur = F0;
12459 MFloat rCur = F0;
12460 for(MInt dir = 0; dir < nDim; dir++) {
12461 rVec[dir] = c_coordinate(gCellId, dir) - center[region * nDim + dir];
12462 hCur += rVec[dir] * normal[region * nDim + dir];
12463 }
12464 for(MInt dir = 0; dir < nDim; dir++) {
12465 hVec[dir] = hCur * normal[region * nDim + dir];
12466 rVec[dir] -= hVec[dir];
12467 rCur += rVec[dir] * rVec[dir];
12468 }
12469 rCur = sqrt(rCur);
12470 if(rCur < radius[region] && abs(hCur) < height[region]) {
12471 // 4.2 ) If a cell is within in the GapRegion:
12472 // set a_potentialGapCell to regionId +1
12473 MInt gapRegionId = region + 1;
12474 a_potentialGapCell(gCellId) = gapRegionId;
12475 }
12476 }
12477
12478 for(MInt region = 0; region < noGapRegionsClose; region++) {
12479 MFloat hCur = F0;
12480 MFloat rCur = F0;
12481 for(MInt dir = 0; dir < nDim; dir++) {
12482 rVec[dir] = c_coordinate(gCellId, dir) - centerClose[region * nDim + dir];
12483 hCur += rVec[dir] * normalClose[region * nDim + dir];
12484 }
12485 for(MInt dir = 0; dir < nDim; dir++) {
12486 hVec[dir] = hCur * normalClose[region * nDim + dir];
12487 rVec[dir] -= hVec[dir];
12488 rCur += rVec[dir] * rVec[dir];
12489 }
12490 rCur = sqrt(rCur);
12491 if(rCur < radiusClose[region] && abs(hCur) < heightClose[region]) {
12492 if(region >= m_noGapRegions) {
12493 a_potentialGapCellClose(gCellId) = m_G0regionId;
12494 a_potentialGapCell(gCellId) = 0;
12495 } else {
12496 MInt closeRegionId = region + 1;
12497 if(bodyClose[region] > -1) {
12498 closeRegionId = bodyClose[region] + 1;
12499 }
12500 a_potentialGapCellClose(gCellId) = closeRegionId;
12501 a_potentialGapCell(gCellId) = closeRegionId + m_noGapRegions;
12502 }
12503 }
12504 }
12505 }
12506 }
12507}
12508
12509//----------------------------------------------------------------------------
12510//----------------------EXCHANGE-FUNCTIONS: ---------------------------
12511
12512template <MInt nDim>
12513void LsCartesianSolver<nDim>::exchangeIntBuffers(MInt* sendBufferSize, MInt* receiveBufferSize, MInt tag,
12514 MInt datasize) {
12515 TRACE();
12516
12517 // debugging-version:
12518 // additional check of the buffer-sizes!
12519#ifdef LS_DEBUG
12520 std::ignore = datasize;
12521
12522 MIntScratchSpace sendData(grid().noNeighborDomains(), AT_, "sendData");
12523 MIntScratchSpace receiveData(grid().noNeighborDomains(), AT_, "receiveData");
12524 MPI_Status status;
12525
12526 // send the size of the data set
12527 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12528 // cerr << "im sending to: " << grid().neighborDomain(i) << " i " << i << endl;
12529 sendData.p[i] = sendBufferSize[i];
12530 MPI_Issend(&sendData.p[i], 1, MPI_INT, grid().neighborDomain(i), tag, mpiComm(), &mpi_request[i], AT_,
12531 "sendData.p[i]");
12532 }
12533
12534 // receive the size of the data set
12535 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12536 // cerr << "im receiving from: " << grid().neighborDomain(i) << endl;
12537 MPI_Recv(&receiveData.p[i], (MInt)1, MPI_INT, grid().neighborDomain(i), tag, mpiComm(), &status, AT_,
12538 "receiveData.p[i]");
12539 receiveBufferSize[i] = receiveData.p[i];
12540 }
12541
12542 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12543 MPI_Wait(&mpi_request[i], &status, AT_);
12544 }
12545
12546 // send
12547 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12548 if(sendBufferSize[i] == 0) {
12549 continue;
12550 }
12551 MPI_Issend(m_intSendBuffers[i], sendBufferSize[i], MPI_INT, grid().neighborDomain(i), tag, mpiComm(),
12552 &mpi_request[i], AT_, "m_intSendBuffers[i]");
12553 }
12554 // receive
12555 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12556 if(receiveBufferSize[i] == 0) {
12557 continue;
12558 }
12559 MPI_Recv(m_intReceiveBuffers[i], receiveBufferSize[i], MPI_INT, grid().neighborDomain(i), tag, mpiComm(), &status,
12560 AT_, "m_intReceiveBuffers[i]");
12561 }
12562 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12563 MPI_Wait(&mpi_request[i], &status, AT_);
12564 }
12565
12566#else
12567
12568 std::ignore = sendBufferSize;
12569 std::ignore = receiveBufferSize;
12570 std::ignore = tag;
12571
12572 // 1. send
12573 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12574 const MInt bufSizeW = noWindowCells(i) * datasize;
12575 if(bufSizeW == 0) continue;
12576 MPI_Issend(m_intSendBuffers[i], bufSizeW, MPI_INT, grid().neighborDomain(i), 0, mpiComm(), &mpi_request[i], AT_,
12577 "m_intSendBuffers[i]");
12578 }
12579
12580 // 2. receive
12581 MPI_Status status;
12582 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12583 const MInt bufSizeH = noHaloCells(i) * datasize;
12584 if(bufSizeH == 0) continue;
12585 MPI_Recv(m_intReceiveBuffers[i], bufSizeH, MPI_INT, grid().neighborDomain(i), 0, mpiComm(), &status, AT_,
12586 "m_intReceiveBuffers[i]");
12587 }
12588
12589 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12590 const MInt bufSizeW = noWindowCells(i) * datasize;
12591 const MInt bufSizeH = noHaloCells(i) * datasize;
12592
12593 if(bufSizeW == 0 || bufSizeH == 0) {
12594 continue;
12595 }
12596
12597 MPI_Wait(&mpi_request[i], MPI_STATUS_IGNORE, AT_);
12598 }
12599
12600 // exchangeBuffer(noNghbrDomains, nghbrDomains, noHaloCells, noWindowCells, comm, haloBuffer, &windowBuffer[0], noDat
12601 // );
12602
12603#endif
12604}
12605
12606template <MInt nDim>
12607template <typename T>
12608void LsCartesianSolver<nDim>::exchangeBuffersGlobal(T* sendBuffer, T* receiveBuffer, MInt* sendBufferSize,
12609 MInt* receiveBufferSize, MInt* sndOffs, MInt* rcvOffs, MInt tag,
12610 MInt offset) {
12611 TRACE();
12612
12613 MInt ind;
12614 const MPI_Datatype DTYPE = maia::type_traits<T>::mpiType();
12615
12616 ScratchSpace<MPI_Request> mpiSndReqGlob(grid().noDomains(), AT_, "mpi_requestGlobal");
12617 mpiSndReqGlob.fill(MPI_REQUEST_NULL);
12618
12619#ifdef LS_DEBUG
12620 MPI_Status status;
12621 MIntScratchSpace sendData(grid().noDomains(), AT_, "sendData");
12622 MIntScratchSpace receiveData(grid().noDomains(), AT_, "receiveData");
12623
12624 // send the size of the data set
12625 for(MInt i = 0; i < grid().noDomains(); i++) {
12626 if(domainId() == i) continue;
12627 sendData.p[i] = sendBufferSize[i];
12628 MPI_Issend(&sendData.p[i], 1, MPI_INT, i, tag, mpiComm(), &mpiSndReqGlob[i], AT_, "sendData.p[i]");
12629 }
12630
12631 // receive the size of the data set
12632 for(MInt i = 0; i < grid().noDomains(); i++) {
12633 if(domainId() == i) continue;
12634 MPI_Recv(&receiveData.p[i], 1, MPI_INT, i, tag, mpiComm(), &status, AT_, "receiveData.p[i]");
12635 receiveBufferSize[i] = receiveData.p[i];
12636 }
12637 for(MInt i = 0; i < grid().noDomains(); i++) {
12638 if(domainId() == i) continue;
12639 MPI_Wait(&mpiSndReqGlob[i], &status, AT_);
12640 }
12641
12642 // send
12643 for(MInt i = 0; i < grid().noDomains(); i++) {
12644 if(domainId() == i) continue;
12645 if(sendBufferSize[i] == 0) continue;
12646 ind = sndOffs[i] * offset;
12647 MPI_Issend(&sendBuffer[ind], sendBufferSize[i], DTYPE, i, (tag + 1), mpiComm(), &mpiSndReqGlob[i], AT_,
12648 "sendBuffer[ind]");
12649 }
12650 // receive
12651 for(MInt i = 0; i < grid().noDomains(); i++) {
12652 if(domainId() == i) continue;
12653 if(receiveBufferSize[i] == 0) continue;
12654 ind = rcvOffs[i] * offset;
12655 MPI_Recv(&receiveBuffer[ind], receiveBufferSize[i], DTYPE, i, (tag + 1), mpiComm(), &status, AT_,
12656 "receiveBuffer[ind]");
12657 }
12658 for(MInt i = 0; i < grid().noDomains(); i++) {
12659 if(domainId() == i) continue;
12660 MPI_Wait(&mpiSndReqGlob[i], &status, AT_);
12661 }
12662#else
12663 ScratchSpace<MPI_Request> mpiRcvReqGlob(grid().noDomains(), AT_, "mpi_requestGlobal");
12664 mpiRcvReqGlob.fill(MPI_REQUEST_NULL);
12665
12666 for(MInt i = 0; i < grid().noDomains(); i++) {
12667 receiveBufferSize[i] = offset * (rcvOffs[i + 1] - rcvOffs[i]);
12668 }
12669
12670 // send
12671 for(MInt i = 0; i < grid().noDomains(); i++) {
12672 if(domainId() == i) continue;
12673 if(sendBufferSize[i] == 0) continue;
12674 ind = sndOffs[i] * offset;
12675
12676 // if ( offset*(sndOffs[i+1]-sndOffs[i]) != sendBufferSize[i] ) {
12677 /*if ( domainId() == 3 ) {
12678 cerr << "D:" << domainId() << " Snd:" << sendBufferSize[i] << " to " << i << " / " << offset << " " << sndOffs[i+1]
12679 << " " << sndOffs[i] << " " << m_globalSndOffsets[grid().noDomains()] << endl;
12680 }*/
12681
12682 MPI_Isend(&sendBuffer[ind], sendBufferSize[i], DTYPE, i, (tag + 1), mpiComm(), &mpiSndReqGlob[i], AT_,
12683 "sendBuffer[ind]");
12684 }
12685
12686 // receive
12687 for(MInt i = 0; i < grid().noDomains(); i++) {
12688 if(domainId() == i) continue;
12689 if(receiveBufferSize[i] == 0) continue;
12690 ind = rcvOffs[i] * offset;
12691
12692 // if ( offset*(rcvOffs[i+1]-rcvOffs[i]) != receiveBufferSize[i] ) {
12693 /*if ( domainId() == 2 ) {
12694 cerr << "D:" << domainId() << " Rcv:" << receiveBufferSize[i] << " from " << i << " / " << offset << " " <<
12695 rcvOffs[i+1] << " " << rcvOffs[i] << " " << m_globalRcvOffsets[grid().noDomains()] <<endl;
12696 }*/
12697 MPI_Irecv(&receiveBuffer[ind], receiveBufferSize[i], DTYPE, i, (tag + 1), mpiComm(), &mpiRcvReqGlob[i], AT_,
12698 "receiveBuffer[ind]");
12699 }
12700 for(MInt i = 0; i < grid().noDomains(); i++) {
12701 if(domainId() == i) continue;
12702 MPI_Wait(&mpiSndReqGlob[i], MPI_STATUS_IGNORE, AT_);
12703 MPI_Wait(&mpiRcvReqGlob[i], MPI_STATUS_IGNORE, AT_);
12704 }
12705#endif
12706}
12707
12708
12709//----------------------------------------------------------------------------
12710
12715template <MInt nDim>
12717 TRACE();
12718
12719 if(grid().noNeighborDomains() == 0 && grid().noAzimuthalNeighborDomains() == 0) return;
12720
12721 exchangeDataLS(&(a_levelSetFunctionG(0, 0)), m_maxNoSets);
12722 if(!m_combustion) {
12723 exchangeDataLS(&(a_bodyIdG(0, 0)), m_maxNoSets);
12724 }
12725
12726 if(m_semiLagrange) {
12727 exchangeDataLS(&(a_oldLevelSetFunctionG(0, 0)), m_maxNoSets);
12728 }
12729}
12730
12735template <MInt nDim>
12737 TRACE();
12738
12739 if(grid().noNeighborDomains() == 0 && grid().noAzimuthalNeighborDomains() == 0) return;
12740
12741 exchangeDataLS(&(a_levelSetFunctionG(0, 0)), m_maxNoSets);
12742}
12743
12748template <MInt nDim>
12749void LsCartesianSolver<nDim>::exchangeLs(MFloat* dataField, MInt firstset, MInt dataBlockSize) {
12750 TRACE();
12751
12752 if(grid().noNeighborDomains() == 0 && grid().noAzimuthalNeighborDomains() == 0) return;
12753
12754 MInt sendBufferCounter = 0;
12755 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12756 sendBufferCounter = 0;
12757 for(MInt j = 0; j < noWindowCells(i); j++) {
12758 memcpy((void*)&m_gSendBuffers[i][sendBufferCounter],
12759 (void*)&dataField[IDX_LSSET(windowCellId(i, j), firstset)],
12760 dataBlockSize * sizeof(MFloat));
12761 sendBufferCounter += dataBlockSize;
12762 }
12763 }
12764
12765 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12766 const MInt bufSize = noWindowCells(i) * dataBlockSize;
12767 if(bufSize == 0) continue;
12768 MPI_Issend(m_gSendBuffers[i], bufSize, MPI_DOUBLE, grid().neighborDomain(i), 0, mpiComm(), &mpi_request[i], AT_,
12769 "m_gSendBuffers[i]");
12770 }
12771
12772 MPI_Status status;
12773 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12774 const MInt bufSize = noHaloCells(i) * dataBlockSize;
12775 if(bufSize == 0) continue;
12776 MPI_Recv(m_gReceiveBuffers[i], bufSize, MPI_DOUBLE, grid().neighborDomain(i), 0, mpiComm(), &status, AT_,
12777 "m_gReceiveBuffers[i]");
12778 }
12779
12780 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12781 const MInt bufSizeW = noWindowCells(i) * dataBlockSize;
12782 const MInt bufSizeH = noHaloCells(i) * dataBlockSize;
12783 if(bufSizeH == 0 || bufSizeW == 0) {
12784 continue;
12785 }
12786 MPI_Wait(&mpi_request[i], &status, AT_);
12787 }
12788
12789 MInt receiveBufferCounter = 0;
12790 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12791 receiveBufferCounter = 0;
12792 for(MInt j = 0; j < noHaloCells(i); j++) {
12793 memcpy((void*)&dataField[IDX_LSSET(haloCellId(i, j), firstset)],
12794 (void*)&m_gReceiveBuffers[i][receiveBufferCounter],
12795 dataBlockSize * sizeof(MFloat));
12796 receiveBufferCounter += dataBlockSize;
12797 }
12798 }
12799
12800 if(grid().azimuthalPeriodicity()) {
12801 this->exchangeAzimuthalPer(&dataField[0], dataBlockSize, firstset);
12802 }
12803}
12804//----------------------------------------------------------------------------
12809template <MInt nDim>
12811 TRACE();
12812
12813 if(grid().noNeighborDomains() == 0 && grid().noAzimuthalNeighborDomains() == 0) return;
12814
12815 if(!m_closeGaps) return;
12816
12817 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
12818 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12819 for(MInt j = 0; j < noWindowCells(i); j++) {
12820 tmp_data[windowCellId(i, j)] = a_nearGapG(windowCellId(i, j));
12821 }
12822 }
12823 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
12824 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
12825 MInt windowId = grid().azimuthalWindowCell(i, j);
12826 tmp_data(windowId) = a_nearGapG(windowId);
12827 }
12828 }
12829
12830 exchangeDataLS(&tmp_data[0], 1);
12831
12832 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
12833 for(MInt j = 0; j < noHaloCells(i); j++) {
12834 a_nearGapG(haloCellId(i, j)) = tmp_data[haloCellId(i, j)];
12835 }
12836 }
12837 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
12838 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
12839 const MInt haloCell = grid().azimuthalHaloCell(i, j);
12840 a_nearGapG(haloCell) = tmp_data[haloCell];
12841 }
12842 }
12843}
12844
12845//----------------------------------------------------------------------------
12846
12847
12854template <MInt nDim>
12856 TRACE();
12857
12858 MBool tmpFalse = false;
12859 MBool tmpTrue = true;
12860
12861 m_referenceLength = F1;
12872 m_referenceLength = Context::getSolverProperty<MFloat>("referenceLength", m_solverId, AT_, &m_referenceLength);
12873
12874 m_referenceVelocity = F1;
12884 if(Context::propertyExists("referenceVelocity", m_solverId)) {
12885 m_referenceVelocity =
12886 Context::getSolverProperty<MFloat>("referenceVelocity", m_solverId, AT_, &m_referenceVelocity);
12887 } else {
12888 if(m_levelSetMb || m_levelSetFv) {
12889 // update referenceVelocity based on Ma
12890 // labels:LS,DOC NOTE: @Thomas this hack changes when a different initialCondition is used!
12891 // best to specify a referenceVelocity instead!
12892 const MFloat Ma = Context::getSolverProperty<MFloat>("Ma", m_solverId, AT_);
12893 const MFloat gammaMinusOne = 1.4 - 1.0;
12894 const MFloat TInfinity = 1.0 / (1.0 + 0.5 * gammaMinusOne * POW2(Ma));
12895 m_referenceVelocity = sqrt(TInfinity);
12896 }
12897 }
12898
12909 m_virtualSurgery = false;
12910 m_virtualSurgery = Context::getSolverProperty<MBool>("virtualSurgery", m_solverId, AT_, &m_virtualSurgery);
12911
12922 m_sphereRadiusLimit = 5.0;
12923 m_sphereRadiusLimit = Context::getSolverProperty<MFloat>("sphereRadiusLimit", m_solverId, AT_, &m_sphereRadiusLimit);
12924
12925 if(m_virtualSurgery) {
12934 m_approxNoInterpReg = Context::getSolverProperty<MInt>("approxNoInterpRegions", m_solverId, AT_);
12935
12936 if(m_approxNoInterpReg <= 0) {
12937 stringstream errorMessage;
12938 errorMessage << "ERROR: Invalid number of interpolation regions. Set approxNoInterpRegions > 0!!!";
12939 mTerm(1, AT_, errorMessage.str());
12940 }
12949 if(Context::propertyLength("interpStartTimes", m_solverId) == m_approxNoInterpReg) {
12950 mAlloc(m_interpStartTime, m_approxNoInterpReg, "m_interpStartTime", -1, AT_);
12951 for(MInt i = 0; i < m_approxNoInterpReg; i++) {
12952 m_interpStartTime[i] = Context::getSolverProperty<MInt>("interpStartTimes", m_solverId, AT_, i);
12953 }
12954 } else {
12955 stringstream errorMessage;
12956 errorMessage << "ERROR: Array length of interpStartTimes and approxNoInterpRegions do not match!!";
12957 mTerm(1, AT_, errorMessage.str());
12958 }
12959
12968 if(Context::propertyLength("noInterpTimeSteps", m_solverId) == m_approxNoInterpReg) {
12969 mAlloc(m_noInterpTimeSteps, m_approxNoInterpReg, "m_noInterpTimeSteps", -1, AT_);
12970 for(MInt i = 0; i < m_approxNoInterpReg; i++) {
12971 m_noInterpTimeSteps[i] = Context::getSolverProperty<MInt>("noInterpTimeSteps", m_solverId, AT_, i);
12972 }
12973 } else {
12974 stringstream errorMessage;
12975 errorMessage << "ERROR: Array length of noInterpTimeSteps and approxNoInterpRegions do not match!!";
12976 mTerm(1, AT_, errorMessage.str());
12977 }
12978 }
12979
12980 // property which determines whether the bodyId and old-LevelsetFuntion is relevant
12981 m_semiLagrange = (string2enum(solverMethod()) == MAIA_SEMI_LAGRANGE_LEVELSET
12983 || string2enum(solverMethod()) == MAIA_SEMI_LAGRANGE_LEVELSET_LB);
12984
12985 m_flameSpeed = 0.0;
12986 m_flameSpeed = Context::getSolverProperty<MFloat>("flameSpeed", m_solverId, AT_, &m_flameSpeed);
12987
12988 m_jetHalfWidth = 0.5;
12989 m_radiusFlameTube = 0.5;
12990 m_yOffsetFlameTube = 0.04;
12991 m_xOffsetFlameTube = 0.0;
12992 m_marksteinLength = 0.0;
12993 m_marksteinLength = Context::getSolverProperty<MFloat>("marksteinLength", m_solverId, AT_, &m_marksteinLength);
12994 m_marksteinLengthPercentage = F1;
12995 m_marksteinLengthPercentage =
12996 Context::getSolverProperty<MFloat>("marksteinLengthPercentage", m_solverId, AT_, &m_marksteinLengthPercentage);
12997 m_marksteinLength *= m_marksteinLengthPercentage;
12998
12999 m_xOffsetFlameTube = Context::getSolverProperty<MFloat>("xOffsetFlameTube", m_solverId, AT_, &m_xOffsetFlameTube);
13000 m_xOffsetFlameTube2 = Context::getSolverProperty<MFloat>("xOffsetFlameTube2", m_solverId, AT_, &m_xOffsetFlameTube);
13001 m_yOffsetFlameTube = Context::getSolverProperty<MFloat>("yOffsetFlameTube", m_solverId, AT_, &m_yOffsetFlameTube);
13002 m_yOffsetFlameTube2 = Context::getSolverProperty<MFloat>("yOffsetFlameTube2", m_solverId, AT_, &m_yOffsetFlameTube);
13003 m_radiusFlameTube = Context::getSolverProperty<MFloat>("radiusFlameTube", m_solverId, AT_, &m_radiusFlameTube);
13004 m_radiusFlameTube2 = Context::getSolverProperty<MFloat>("radiusFlameTube2", m_solverId, AT_, &m_radiusFlameTube);
13005
13006
13007 m_trackMovingBndry = true;
13008 m_trackMbStart = -1;
13009 m_trackMbEnd = numeric_limits<MInt>::max();
13010
13011 m_trackMovingBndry = Context::getSolverProperty<MBool>("trackMovingBndry", m_solverId, AT_, &m_trackMovingBndry);
13012 m_trackMbStart = Context::getSolverProperty<MInt>("trackMbStart", m_solverId, AT_, &m_trackMbStart);
13013 m_trackMbEnd = Context::getSolverProperty<MInt>("trackMbEnd", m_solverId, AT_, &m_trackMbEnd);
13014
13015 if(m_levelSetMb) {
13016 m_constructGField = true;
13017 m_constructGField = Context::getSolverProperty<MBool>("constructGField", m_solverId, AT_, &m_constructGField);
13018 }
13019
13020 m_realRadiusFlameTube = 0.5;
13021 m_realRadiusFlameTube =
13022 Context::getSolverProperty<MFloat>("realRadiusFlameTube", m_solverId, AT_, &m_realRadiusFlameTube);
13035 m_forcing = false;
13036 m_forcing = Context::getSolverProperty<MBool>("forcing", m_solverId, AT_, &m_forcing);
13037
13038 m_flameRadiusOffset = F0;
13039 m_flameRadiusOffset = Context::getSolverProperty<MFloat>("flameRadiusOffset", m_solverId, AT_, &m_flameRadiusOffset);
13040
13041 m_twoFlames = false;
13042 m_twoFlames = Context::getSolverProperty<MBool>("twoFlames", m_solverId, AT_, &tmpFalse);
13043
13044 m_initialFlameHeight = F1;
13045 m_initialFlameHeight =
13046 Context::getSolverProperty<MFloat>("initialFlameHeight", m_solverId, AT_, &m_initialFlameHeight);
13047
13048 m_initialCondition = Context::getSolverProperty<MInt>("initialCondition", m_solverId, AT_);
13049
13061 m_jetHalfLength = 4.165;
13062 m_jetHalfLength = Context::getSolverProperty<MFloat>("jetHalfLength", m_solverId, AT_, &m_jetHalfLength);
13063
13064 m_filterFlameTubeEdgesDistance = -9999.9;
13065 m_filterFlameTubeEdgesDistance = Context::getSolverProperty<MFloat>("filterFlameTubeEdgesDistance", m_solverId, AT_,
13066 &m_filterFlameTubeEdgesDistance);
13067
13068 m_filterFlameTubeEdges = Context::getSolverProperty<MBool>("filterFlameTubeEdges", m_solverId, AT_, &tmpFalse);
13069
13070 m_noReactionCells = 0.026367201;
13071 m_noReactionCells = Context::getSolverProperty<MFloat>("noReactionCells", m_solverId, AT_, &m_noReactionCells);
13072
13073
13074 m_dampingDistanceFlameBase = 0.259;
13075 m_dampingDistanceFlameBase =
13076 Context::getSolverProperty<MFloat>("dampingDistanceFlameBase", m_solverId, AT_, &m_dampingDistanceFlameBase);
13077
13078 m_dampingDistanceFlameBaseExtVel = 0.05;
13079 m_dampingDistanceFlameBaseExtVel = Context::getSolverProperty<MFloat>("dampingDistanceFlameBaseExtVel", m_solverId,
13080 AT_, &m_dampingDistanceFlameBaseExtVel);
13081
13082 m_useCorrectedBurningVelocity = 0;
13083 m_useCorrectedBurningVelocity =
13084 Context::getSolverProperty<MBool>("useCorrectedBurningVelocity", m_solverId, AT_, &m_useCorrectedBurningVelocity);
13085
13086 m_plenum = false;
13087 m_plenum = Context::getSolverProperty<MBool>("plenum", m_solverId, AT_, &tmpFalse);
13088
13089 m_timeStepMethod = Context::getSolverProperty<MInt>("timeStepMethod", m_solverId, AT_);
13090 m_cfl = Context::getSolverProperty<MFloat>("cfl", m_solverId, AT_);
13091
13092
13093 m_steadyFlameLength = -F1;
13105 m_steadyFlameLength = Context::getSolverProperty<MFloat>("steadyFlameLength", m_solverId, AT_, &m_steadyFlameLength);
13106
13107 m_maxNoCells = maxNoGridCells();
13108
13109 m_maxNoSets = 1;
13122 m_maxNoSets = Context::getSolverProperty<MInt>("maxNoLevelSets", m_solverId, AT_, &m_maxNoSets);
13123
13124
13125 m_STLReinitMode = 2;
13141 m_STLReinitMode = Context::getSolverProperty<MInt>("GFieldFromSTLReinitMode", m_solverId, AT_, &m_STLReinitMode);
13142
13143 m_noSets = m_maxNoSets;
13144 m_startSet = 0;
13145 m_buildCollectedLevelSetFunction = false;
13146 m_determineG0CellsMode = 0;
13147 m_noBodyBndryCndIds = 1;
13148 m_closeGaps = false;
13149
13150 if(m_levelSetMb) {
13151 m_noEmbeddedBodies = 1;
13152 }
13153
13154 mAlloc(m_levelSetSign, m_maxNoSets, "m_levelSetSign", 1, AT_);
13155 mAlloc(m_computeSet, m_maxNoSets, "m_computeSet", true, AT_);
13156 mAlloc(m_computeSet_tmp, m_maxNoSets, "m_computeSet_tmp", true, AT_);
13157 mAlloc(m_computeSet_backup, m_maxNoSets, "m_computeSet_backup", true, AT_);
13158 mAlloc(m_changedSet, m_maxNoSets, "m_changedSet", true, AT_);
13159
13160 if(this->m_adaptation) {
13161 if(!m_restart) {
13162 m_initialRefinement = true;
13163 }
13164 }
13165
13176 for(MInt i = 0; i < m_noSets; i++) {
13177 m_levelSetSign[i] = Context::getSolverProperty<MInt>("levelSetSign", m_solverId, AT_, &m_levelSetSign[i], i);
13178 }
13179
13189 for(MInt i = 0; i < m_noSets; i++) {
13190 m_computeSet_tmp[i] = Context::getSolverProperty<MBool>("computeSet", m_solverId, AT_, &m_computeSet_tmp[i], i);
13191 m_computeSet_backup[i] = Context::getSolverProperty<MBool>("computeSet", m_solverId, AT_, &m_computeSet_tmp[i], i);
13192 }
13193
13205 m_GFieldInitFromSTL = tmpFalse;
13206 m_GFieldInitFromSTL = Context::getSolverProperty<MBool>("GFieldInitFromSTL", m_solverId, AT_, &m_GFieldInitFromSTL);
13207
13218 m_GFieldFromSTLInitCheck = Context::getSolverProperty<MBool>("GFieldFromSTLInitCheck", m_solverId, AT_, &tmpFalse);
13219
13220 if(m_GFieldInitFromSTL) {
13232 m_GWithReConstruction = Context::getSolverProperty<MBool>("levelSetWithSTLCorrection", m_solverId, AT_, &tmpFalse);
13233
13234
13235 m_reconstructBand = Context::getSolverProperty<MInt>("reconstructBand", m_solverId, AT_, &m_reconstructBand);
13236 }
13237
13238 if(m_maxNoSets > 1) {
13251 m_buildCollectedLevelSetFunction = Context::getSolverProperty<MBool>("buildCollectedLevelSetFunction", m_solverId,
13252 AT_, &m_buildCollectedLevelSetFunction);
13253 }
13254
13255 MInt movingBndryCndId = 3006;
13268 movingBndryCndId = Context::getSolverProperty<MInt>("movingBndryCndId", m_solverId, AT_, &movingBndryCndId);
13269
13270 m_noEmbeddedBodies = 1;
13271 if(!Context::propertyExists("bodyBndryCndIds", m_solverId) && m_levelSetMb) {
13283 m_noEmbeddedBodies = Context::getSolverProperty<MInt>("noEmbeddedBodies", m_solverId, AT_, &m_noEmbeddedBodies);
13284 m_noBodyBndryCndIds = m_noEmbeddedBodies;
13285
13286 if(m_noBodyBndryCndIds > 0) {
13287 mAlloc(m_bodyBndryCndIds, m_noBodyBndryCndIds, "m_bodyBndryCndIds", movingBndryCndId, AT_);
13288 }
13289 } else {
13302 m_noBodyBndryCndIds = Context::propertyLength("bodyBndryCndIds", m_solverId);
13303 if(m_noBodyBndryCndIds > 0) {
13304 mAlloc(m_bodyBndryCndIds, m_noBodyBndryCndIds, "m_bodyBndryCndIds", 0, AT_);
13305 }
13306 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
13307 m_bodyBndryCndIds[i] = Context::getSolverProperty<MInt>("bodyBndryCndIds", m_solverId, AT_, i);
13308 }
13309 if(m_noBodyBndryCndIds > 1) {
13310 m_noEmbeddedBodies = m_noBodyBndryCndIds;
13311 }
13312 }
13313
13314 MBool useBodyToSetTable = Context::propertyExists("bodyBndryCndIds", m_solverId);
13315 if((m_GFieldInitFromSTL && useBodyToSetTable) || m_maxNoSets > 1) {
13316 setUpBodyToSetTable();
13317 }
13318
13331 m_highOrderDeltaFunction = Context::getSolverProperty<MBool>("highOrderDeltaFunction", m_solverId, AT_, &tmpFalse);
13332
13345 m_fourthOrderNormalCurvatureComputation =
13346 Context::getSolverProperty<MBool>("fourthOrderNormalCurvatureComputation", m_solverId, AT_, &tmpFalse);
13347
13348 if(m_combustion && m_fourthOrderNormalCurvatureComputation) {
13349 stringstream errorMessage;
13350 errorMessage << "ERROR: fourthOrderNormalCurvatureCompuatation should not be used, pockets are not correctly "
13351 "generated ... exiting";
13352 mTerm(1, AT_, errorMessage.str());
13353 }
13354
13367 m_curvatureDamp = Context::getSolverProperty<MBool>("curvatureDamp", m_solverId, AT_, &tmpFalse);
13368
13369 m_curvatureDampFactor = F3;
13381 m_curvatureDampFactor =
13382 Context::getSolverProperty<MFloat>("curvatureDampFactor", m_solverId, AT_, &m_curvatureDampFactor);
13383
13396 m_sharpDamp = Context::getSolverProperty<MBool>("sharpDamp", m_solverId, AT_, &tmpFalse);
13397
13398
13408 m_useLocalMarksteinLength = Context::getSolverProperty<MBool>("useLocalMarksteinLength", m_solverId, AT_, &tmpFalse);
13409
13422 m_hyperbolicCurvature = Context::getSolverProperty<MBool>("hyperbolicCurvature", m_solverId, AT_, &tmpFalse);
13423
13441 m_gRKMethod = Context::getSolverProperty<MInt>("gRKMethod", m_solverId, AT_);
13442
13462 m_levelSetDiscretizationScheme = Context::getSolverProperty<MString>("levelSetDiscretizationScheme", m_solverId, AT_);
13463
13464
13471 m_LsRotate = false;
13472 m_LsRotate = Context::getSolverProperty<MBool>("LsRotate", m_solverId, AT_, &m_LsRotate);
13473
13474 if(m_LsRotate) {
13475 m_reconstructOldG = Context::getSolverProperty<MBool>("reconstructOldG", m_solverId, AT_, &m_reconstructOldG);
13476 } else {
13477 m_reconstructOldG = false;
13478 }
13479
13491 m_gBandWidth = Context::getSolverProperty<MInt>("gBandWidth", m_solverId, AT_);
13492
13504 m_gShadowWidth = Context::getSolverProperty<MInt>("gShadowWidth", m_solverId, AT_);
13505
13516 if(m_levelSetRans) {
13517 m_gShadowWidthRans = Context::getSolverProperty<MInt>("gShadowWidthRans", m_solverId, AT_);
13518 }
13519
13531 m_gInnerBound = Context::getSolverProperty<MInt>("gInnerBound", m_solverId, AT_);
13532
13533 ASSERT(m_gInnerBound >= 2, "Should be at least 2!");
13534
13535
13547 if(Context::propertyLength("maxGCellLevel", m_solverId)) {
13548 if(Context::propertyLength("maxGCellLevel", m_solverId) == 1) {
13549 TERMM(1, "Warning: maxGCellLevel has only one set! Use maxRfnmntLvl instead!");
13550 }
13551
13552 m_gCellLevelJump = true;
13553
13554 ASSERT(m_semiLagrange && !m_LsRotate, "");
13555 // otherwise untested
13556
13557 mAlloc(m_maxGCellLevel, m_maxNoSets, "m_maxGCellLevel", 0, AT_);
13558
13559 ASSERT(Context::propertyLength("maxGCellLevel", m_solverId) == m_maxNoSets, "");
13560
13561 for(MInt set = 0; set < m_maxNoSets; set++) {
13562 m_maxGCellLevel[set] = Context::getSolverProperty<MInt>("maxGCellLevel", m_solverId, AT_, set);
13563 ASSERT(m_maxGCellLevel[set] <= maxRefinementLevel() && m_maxGCellLevel[set] >= minLevel(), "");
13564 }
13565
13566 } else {
13567 mAlloc(m_maxGCellLevel, 1, "m_maxGCellLevel", 0, AT_);
13568 m_maxGCellLevel[0] = Context::getSolverProperty<MInt>("maxRfnmntLvl", m_solverId, AT_);
13569
13570 ASSERT(m_maxGCellLevel[0] == maxRefinementLevel(),
13571 "maxGCellLevel " + to_string(m_maxGCellLevel[0]) + " maxLevel " + to_string(maxRefinementLevel()));
13572 }
13573
13574 m_maxLevelChange = false;
13575 if(globalTimeStep > 0 && m_restartFile && isActive() && maxLevel() != maxRefinementLevel()) {
13576 m_maxLevelChange = true;
13577 if(domainId() == 0) {
13578 cerr << "MaxLevel is " << maxLevel() << " and maxRefinementLevel is " << maxRefinementLevel()
13579 << " => temporarily reduction of m_maxGCellLevel to MaxLevel!" << endl;
13580 }
13581 m_maxGCellLevel[0] = maxLevel();
13582 }
13583
13584 if(this->m_noSensors > 0) {
13585 if(globalTimeStep > 0 && m_restartFile && isActive() && this->m_adaptation
13586 && maxLevel() > this->m_maxSensorRefinementLevel[0]) {
13587 m_maxLevelChange = true;
13588 if(domainId() == 0) {
13589 cerr << "MaxLevel is " << maxLevel() << " and maxSensorLevel is " << this->m_maxSensorRefinementLevel[0]
13590 << " => temporarily increase of m_maxGCellLevel to MaxLevel!" << endl;
13591 }
13592 ASSERT(m_maxGCellLevel[0] == maxLevel(), "");
13593 }
13594 }
13595
13596 m_gCellDistance = c_cellLengthAtLevel(m_maxGCellLevel[0]);
13597 m_FgCellDistance = F1 / m_gCellDistance;
13598 m_log << "smallest gCell length " << m_gCellDistance << endl;
13599
13600 m_outsideGValue = (MFloat)(2 * m_gBandWidth * m_gCellDistance);
13601 m_log << "Outside G value: " << m_outsideGValue << endl;
13602
13603 m_computeExtVel = 1;
13630 m_computeExtVel = Context::getSolverProperty<MInt>("computeExtVel", m_solverId, AT_, &m_computeExtVel);
13631
13632 m_smoothExtVel = true;
13644 m_smoothExtVel = Context::getSolverProperty<MBool>("smoothExtVel", m_solverId, AT_, &tmpTrue);
13645
13646 m_extVelIterations = 10000;
13656 m_extVelIterations = Context::getSolverProperty<MInt>("extVelIterations", m_solverId, AT_, &m_extVelIterations);
13657
13669 m_extVelConvergence = Context::getSolverProperty<MFloat>("extVelConvergence", m_solverId, AT_);
13670
13671 m_extVelCFL = 0.5;
13681 m_extVelCFL = Context::getSolverProperty<MFloat>("extVelCFL", m_solverId, AT_, &m_extVelCFL);
13682
13709 m_reinitMethod = Context::getSolverProperty<MString>("reinitMethod", m_solverId, AT_);
13710
13711 m_noGapRegions = 0;
13712 m_gapInitMethod = 2;
13713 m_forceNoGaps = 0;
13714
13715 if(m_buildCollectedLevelSetFunction) {
13728 m_gapReinitMethod = Context::getSolverProperty<MString>("gapReinitMethod", m_solverId, AT_, &m_reinitMethod);
13729
13730
13740 m_closeGaps = Context::getSolverProperty<MBool>("closeGaps", m_solverId, AT_, &m_closeGaps);
13741
13742 if(!m_closeGaps) {
13752 m_determineG0CellsMode =
13753 Context::getSolverProperty<MBool>("determineG0Mode", m_solverId, AT_, &m_determineG0CellsMode);
13754 } else { // m_closeGaps
13755
13768 m_noGapRegions = Context::getSolverProperty<MInt>("noGapRegions", m_solverId, AT_, &m_noGapRegions);
13769
13770 ASSERT(m_noGapRegions > 0, "");
13771
13786 if(Context::propertyExists("G0regionId", m_solverId)) {
13787 m_G0regionId = Context::getSolverProperty<MInt>("G0regionId", m_solverId, AT_, &m_G0regionId);
13788 }
13789
13790
13804 m_gapInitMethod = Context::getSolverProperty<MInt>("gapInitMethod", 0, AT_, &m_gapInitMethod);
13805
13818 m_forceNoGaps = Context::getSolverProperty<MInt>("forceNoGaps", m_solverId, AT_, &m_forceNoGaps);
13819
13820 if(m_forceNoGaps == 1) { // surpress gap cells for multi-valve engine
13821
13822 mAlloc(m_gapAngleClose, m_noGapRegions, "m_gapAngleClose", F0, AT_);
13823 mAlloc(m_gapAngleOpen, m_noGapRegions, "m_gapAngleOpen", F0, AT_);
13824 mAlloc(m_gapSign, m_noGapRegions, "m_gapSign", F1, AT_);
13825
13826 for(MInt i = 0; i < m_noGapRegions; i++) {
13827 m_gapAngleClose[i] =
13828 Context::getSolverProperty<MFloat>("gapAngleClose", m_solverId, AT_, &m_gapAngleClose[i], i);
13829 m_gapAngleOpen[i] =
13830 Context::getSolverProperty<MFloat>("gapAngleOpen", m_solverId, AT_, &m_gapAngleClose[i], i);
13831 if(m_gapAngleClose[i] < 0.0) {
13832 m_gapAngleClose[i] = 720 + m_gapAngleClose[i];
13833 }
13834 if(m_gapAngleOpen[i] < 0.0) {
13835 m_gapAngleOpen[i] = 720 + m_gapAngleOpen[i];
13836 }
13837 if(m_gapAngleOpen[i] > m_gapAngleClose[i]) {
13838 m_gapSign[i] = -1;
13839 }
13840 }
13841 } else if(m_forceNoGaps == 2) { // surpress gap cells for single-valve engine
13842
13843 ASSERT(m_noGapRegions == 1, "Mode only intended for 1 gap-region!");
13844
13845 mAlloc(m_gapAngleClose, m_noGapRegions + 1, "m_gapAngleClose", F0, AT_);
13846 mAlloc(m_gapAngleOpen, m_noGapRegions + 1, "m_gapAngleOpen", F0, AT_);
13847 mAlloc(m_gapSign, m_noGapRegions + 1, "m_gapSign", F1, AT_);
13848
13849 ASSERT(m_noGapRegions + 1 == Context::propertyLength("gapAngleOpen", m_solverId), "");
13850
13851 for(MInt i = 0; i < m_noGapRegions + 1; i++) {
13852 m_gapAngleClose[i] =
13853 Context::getSolverProperty<MFloat>("gapAngleClose", m_solverId, AT_, &m_gapAngleClose[i], i);
13854 m_gapAngleOpen[i] =
13855 Context::getSolverProperty<MFloat>("gapAngleOpen", m_solverId, AT_, &m_gapAngleClose[i], i);
13856 if(m_gapAngleClose[i] < 0.0) {
13857 m_gapAngleClose[i] = 720 + m_gapAngleClose[i];
13858 }
13859 if(m_gapAngleOpen[i] < 0.0) {
13860 m_gapAngleOpen[i] = 720 + m_gapAngleOpen[i];
13861 }
13862 if(m_gapAngleOpen[i] > m_gapAngleClose[i]) {
13863 m_gapSign[i] = -1;
13864 }
13865 }
13866 } else {
13867 mAlloc(m_gapAngleClose, m_noGapRegions, "m_gapAngleClose", F0, AT_);
13868 mAlloc(m_gapAngleOpen, m_noGapRegions, "m_gapAngleOpen", F0, AT_);
13869 mAlloc(m_gapSign, m_noGapRegions, "m_gapSign", F1, AT_);
13870 }
13871 }
13872
13873 m_gapDeltaMin = F1;
13874 m_gapDeltaMinOrig = F1;
13885 if(Context::propertyExists("deltaMin", m_solverId)) {
13886 m_gapDeltaMin = Context::getSolverProperty<MFloat>("deltaMin", m_solverId, AT_, &m_gapDeltaMin);
13887 }
13888 m_gapDeltaMinOrig = m_gapDeltaMin;
13889 }
13890
13900 m_gReinitIterations = Context::getSolverProperty<MInt>("gReinitIterations", m_solverId, AT_);
13901
13902 m_minReinitializationSteps = m_gReinitIterations;
13912 m_minReinitializationSteps =
13913 Context::getSolverProperty<MInt>("minReinitializationSteps", m_solverId, AT_, &m_minReinitializationSteps);
13914
13915 m_maintenanceIterations = m_gReinitIterations;
13927 m_maintenanceIterations =
13928 Context::getSolverProperty<MInt>("maintenanceIterations", m_solverId, AT_, &m_maintenanceIterations);
13929
13942 m_guaranteeReinit = Context::getSolverProperty<MBool>("guaranteeReinit", m_solverId, AT_, &tmpFalse);
13943
13944 if(!m_guaranteeReinit && m_closeGaps) {
13945 ASSERT(m_gapDeltaMin < 1.00000001, "Reinitialisation is required if deltaMin > 1 is used!");
13946 }
13947
13959 m_reinitCFL = Context::getSolverProperty<MFloat>("reinitCFL", m_solverId, AT_);
13960
13961 m_intermediateReinitIterations = 1;
13972 m_intermediateReinitIterations = Context::getSolverProperty<MInt>("intermediateReinitIterations", m_solverId, AT_,
13973 &m_intermediateReinitIterations);
13974
13985 m_reinitConvergence = Context::getSolverProperty<MFloat>("reinitConvergence", m_solverId, AT_);
13986 m_reinitConvergenceReset = m_reinitConvergence;
13987
13988 m_reinitThreshold = F0;
14003 m_reinitThreshold = Context::getSolverProperty<MFloat>("reinitThreshold", m_solverId, AT_, &m_reinitThreshold);
14004
14005 m_reinitThresholdAvg = F0;
14019 m_reinitThresholdAvg =
14020 Context::getSolverProperty<MFloat>("reinitThresholdAvg", m_solverId, AT_, &m_reinitThresholdAvg);
14021
14022 m_omegaReinit = F1;
14032 m_omegaReinit = Context::getSolverProperty<MFloat>("omegaReinit", m_solverId, AT_, &m_omegaReinit);
14033
14034 m_relaxationFactor = 0.5;
14046 m_relaxationFactor = Context::getSolverProperty<MFloat>("relaxationFactor", m_solverId, AT_, &m_relaxationFactor);
14047
14048 m_levelSetTestCase = 0;
14081 m_levelSetTestCase = Context::getSolverProperty<MInt>("levelSetTestCase", m_solverId, AT_, &m_levelSetTestCase);
14082
14083 m_levelSetBoundaryCondition = m_levelSetTestCase;
14101 m_levelSetBoundaryCondition =
14102 Context::getSolverProperty<MInt>("levelSetBoundaryCondition", m_solverId, AT_, &m_levelSetBoundaryCondition);
14103
14104 m_levelSetBC = "SYMMETRIC";
14116 m_levelSetBC = Context::getSolverProperty<MString>("levelSetBC", m_solverId, AT_, &m_levelSetBC);
14117
14118 // only relevant for m_levelSetBoundaryCondition = 1751600!
14119 m_noHaloLayers = 1;
14131 m_noHaloLayers = Context::getSolverProperty<MInt>("noHaloLayers", m_solverId, AT_, &m_noHaloLayers);
14132
14133 if(m_fourthOrderNormalCurvatureComputation) {
14134 ASSERT(m_noHaloLayers > 1, "Not enough halo layer for fourth order curvature computation");
14135 }
14136
14137 m_reinitInterval = 1;
14149 m_reinitInterval = Context::getSolverProperty<MInt>("reinitInterval", m_solverId, AT_, &m_reinitInterval);
14150
14160 m_maintainOuterBandLayers = Context::getSolverProperty<MBool>("maintainOuterBandLayers", m_solverId, AT_, &tmpFalse);
14161
14189 m_writeReinitializationStatistics =
14190 Context::getSolverProperty<MBool>("writeReinitializationStatistics", m_solverId, AT_, &tmpFalse);
14191
14203 m_interpolateFlowFieldToFlameFront =
14204 Context::getSolverProperty<MBool>("interpolateFlowFieldToFlameFront", m_solverId, AT_, &tmpFalse);
14205
14218 m_writeOutAllLevelSetFunctions =
14219 Context::getSolverProperty<MBool>("writeOutAllLevelSetFunctions", m_solverId, AT_, &tmpFalse);
14220
14232 m_writeOutAllExtensionVelocities =
14233 Context::getSolverProperty<MBool>("writeOutAllExtensionVelocities", m_solverId, AT_, &tmpFalse);
14234
14245 m_writeOutAllCurvatures = Context::getSolverProperty<MBool>("writeOutAllCurvatures", m_solverId, AT_, &tmpFalse);
14246
14258 m_writeOutAllCorrectedBurningVelocity =
14259 Context::getSolverProperty<MBool>("writeOutAllCorrectedBurningVelocity", m_solverId, AT_, &tmpFalse);
14260
14271 m_writeOutAllFlameSpeeds = Context::getSolverProperty<MBool>("writeOutAllFlameSpeeds", m_solverId, AT_, &tmpFalse);
14272
14285 m_writeOutAllNormalVectors =
14286 Context::getSolverProperty<MBool>("writeOutAllNormalVectors", m_solverId, AT_, &tmpFalse);
14287
14288 if(string2enum(m_reinitMethod) == HCR2_FULLREINIT) {
14289 // output info min iteration
14290 MInt minIteration = m_gBandWidth / m_reinitCFL;
14291 m_log << "reinitMethod: HCR2_FULLREINIT -> full reinitialization guaranteed after " << minIteration << " iterations"
14292 << endl;
14293 }
14294
14295 if(m_combustion) {
14296 // compute minimum iterations to transport the velocity to the band cells
14297 MInt minIteration = m_gBandWidth / m_extVelCFL;
14298 m_log << "number of minimum iterations necessary to extend velocity field on band " << minIteration << endl;
14299 m_log << "number of iterations set to extend velocity field on band " << m_extVelIterations << endl;
14300 }
14301
14309 m_engineSetup = Context::getSolverProperty<MBool>("engineSetup", m_solverId, AT_, &m_engineSetup);
14310
14311 if(m_LsRotate) {
14312 mAlloc(m_outerBandWidth, maxRefinementLevel() + 1, "m_outerBandWidth", 0, AT_);
14313 m_outerBandWidth[maxRefinementLevel()] = m_gShadowWidth;
14314 for(MInt lvl = maxRefinementLevel() - 1; lvl >= 0; lvl--) {
14315 MInt dif = (maxRefinementLevel() - lvl);
14316 m_outerBandWidth[lvl] = (m_outerBandWidth[lvl + 1] / 2) + 1 + dif;
14317 }
14318 } else if(m_combustion) {
14319 mAlloc(m_outerBandWidth, maxRefinementLevel() + 1, "m_outerBandWidth", 0, AT_);
14320 m_outerBandWidth[maxRefinementLevel()] = m_gShadowWidth;
14321 for(MInt lvl = maxRefinementLevel() - 1; lvl >= 0; lvl--) {
14322 MInt factor = IPOW2((maxRefinementLevel() - lvl));
14323 MInt currentWidth = m_gShadowWidth / factor;
14324 if(currentWidth * factor < m_gShadowWidth) {
14325 currentWidth++;
14326 }
14327 m_outerBandWidth[lvl] = currentWidth;
14328 }
14329 } else if(m_engineSetup) {
14330 mAlloc(m_outerBandWidth, maxRefinementLevel() + 1, "m_outerBandWidth", 0, AT_);
14331 m_outerBandWidth[maxRefinementLevel()] = m_gShadowWidth + 2;
14332 for(MInt lvl = maxRefinementLevel() - 1; lvl >= 0; lvl--) {
14333 MInt val = m_outerBandWidth[lvl + 1] / 2;
14334 if(val * 2 < m_outerBandWidth[lvl + 1]) {
14335 val++;
14336 }
14337 m_outerBandWidth[lvl] = val;
14338 }
14339 } else if(m_levelSetRans) {
14340 mAlloc(m_outerBandWidth, maxRefinementLevel(), "m_outerBandWidth", 0, AT_);
14341 m_outerBandWidth[maxRefinementLevel() - 1] = m_gShadowWidthRans;
14342 for(MInt i = maxRefinementLevel() - 2; i >= 0; i--) {
14343 m_outerBandWidth[i] = (m_outerBandWidth[i + 1] / 2) + 1;
14344 }
14345 } else {
14346 mAlloc(m_outerBandWidth, maxRefinementLevel(), "m_outerBandWidth", 0, AT_);
14347 m_outerBandWidth[maxRefinementLevel() - 1] = m_gShadowWidth;
14348 for(MInt i = maxRefinementLevel() - 2; i >= 0; i--) {
14349 m_outerBandWidth[i] = (m_outerBandWidth[i + 1] / 2) + 1;
14350 }
14351 }
14352
14353 m_refineDiagonals = true;
14364 if(m_LsRotate) m_refineDiagonals = false;
14365 m_refineDiagonals = Context::getSolverProperty<MBool>("refineDiagonals", m_solverId, AT_, &m_refineDiagonals);
14366
14367 m_bodyIdOutput = m_semiLagrange;
14377 m_bodyIdOutput = Context::getSolverProperty<MBool>("bodyIdOutput", m_solverId, AT_, &m_bodyIdOutput);
14378
14379
14380 if(m_noInitGFieldFromSTLBndCndIds + m_noBodyBndryCndIds > 0) {
14381 mAlloc(m_initGFieldFromSTLBndCndIds, m_noInitGFieldFromSTLBndCndIds + m_noBodyBndryCndIds,
14382 "m_initGFieldFromSTLBndCndIds", -1, AT_);
14383 }
14384 MInt defaultValue = -1;
14385 for(MInt i = 0; i < m_noBodyBndryCndIds; i++) {
14386 m_initGFieldFromSTLBndCndIds[i] = m_bodyBndryCndIds[i];
14387 }
14388 m_noInitGFieldFromSTLBndCndIds += m_noBodyBndryCndIds;
14389 for(MInt i = m_noBodyBndryCndIds; i < m_noInitGFieldFromSTLBndCndIds; i++) {
14390 m_initGFieldFromSTLBndCndIds[i] = Context::getSolverProperty("GFieldInitFromSTLBndCndIds", m_solverId, AT_,
14391 &defaultValue, i - m_noBodyBndryCndIds);
14392 }
14393
14394
14404 if(Context::propertyExists("LsGeometryChange", m_solverId)) {
14405 m_forceAdaptation = true;
14406
14407 mAlloc(m_geometryChange, m_noSets, "geometryChange", false, AT_);
14408
14409 MBool anychange = false;
14410 for(MInt set = 0; set < m_noSets; set++) {
14411 m_geometryChange[set] =
14412 Context::getSolverProperty<MBool>("LsGeometryChange", m_solverId, AT_, &m_geometryChange[set], set);
14413 if(m_geometryChange[set]) {
14414 anychange = true;
14415 if(domainId() == 0) {
14416 cerr << "Changing geometry of set " << set << " upon restart!" << endl;
14417 }
14418 }
14419 }
14420
14421 if(!anychange) {
14422 mDeallocate(m_geometryChange);
14423 ASSERT(m_geometryChange == nullptr, "");
14424 }
14425 }
14426
14427 m_periodicMovement = false;
14428 if(Context::propertyExists("periodicMovement", m_solverId)) {
14429 m_periodicMovement = Context::getSolverProperty<MBool>("periodicMovement", m_solverId, AT_, &m_periodicMovement);
14430 m_periodicDirection = Context::getSolverProperty<MInt>("periodicDirection", m_solverId, AT_, &m_periodicDirection);
14431 }
14440 m_weightBaseCell = 1.0;
14441 m_weightBaseCell = Context::getSolverProperty<MFloat>("weightBaseCell", solverId(), AT_, &m_weightBaseCell);
14442
14451 m_weightLeafCell = 1.0;
14452 m_weightLeafCell = Context::getSolverProperty<MFloat>("weightLeafCell", solverId(), AT_, &m_weightLeafCell);
14453
14462 m_weightBandCell = 1.0;
14463 m_weightBandCell = Context::getSolverProperty<MFloat>("weightBandCell", solverId(), AT_, &m_weightBandCell);
14464
14474 m_weightMulitSolverFactor = 1.0;
14475 m_weightMulitSolverFactor =
14476 Context::getSolverProperty<MFloat>("weightMulitSolverFactor", solverId(), AT_, &m_weightMulitSolverFactor);
14477
14486 m_limitWeights = false;
14487 m_limitWeights = Context::getSolverProperty<MBool>("limitDLBWeights", solverId(), AT_, &m_limitWeights);
14488
14498 m_weightLevelSet = true;
14499 m_weightLevelSet = Context::getSolverProperty<MBool>("weightLevelSet", solverId(), AT_, &m_weightLevelSet);
14500}
14501
14505template <MInt nDim>
14506void LsCartesianSolver<nDim>::preTimeStep() {
14507 TRACE();
14508
14509 if(m_combustion || m_freeSurface) {
14510 exchangeAllLevelSetData();
14511
14512 setGCellBndryProperty();
14513
14514 updateBndryCellList();
14515
14516 if(string2enum(m_levelSetBC) == PERIODIC) {
14517 computeNormalVectorsPeriodic();
14518
14519 computeCurvaturePeriodic();
14520 } else {
14521 computeNormalVectors();
14522
14523 computeCurvature();
14524 }
14525 // constructExtensionVelocity(); //this is now done in the coupler
14526 } else if(!m_levelSetMb) {
14527 setGCellBndryProperty();
14528
14529 if(!m_semiLagrange) {
14530 computeNormalVectors();
14531
14532 computeCurvature();
14533
14534 determinePropagationSpeed();
14535 }
14536
14537 } else if(m_levelSetMb) {
14538 if(m_constructGField != 0) return;
14539
14540 checkHaloCells();
14541
14542 static MBool firstRun = true;
14543
14544 if(firstRun) {
14545 for(MInt set = 0; set < m_noSets; set++) {
14546 m_computeSet[set] = m_computeSet_tmp[set];
14547 m_changedSet[set] = true;
14548 }
14549 firstRun = false;
14550 }
14551
14552 for(MInt set = 0; set < m_noSets; set++) {
14553 ASSERT(m_computeSet[set] == m_computeSet_backup[set], "ERROR in m_computeSet");
14554 }
14555
14556 m_time += timeStep();
14557 }
14558}
14559
14571template <MInt nDim>
14572void LsCartesianSolver<nDim>::buildMultipleLevelSet(const MInt mode) {
14573 TRACE();
14574
14575 if(!m_buildCollectedLevelSetFunction) return;
14576
14577 NEW_TIMER_GROUP_STATIC(buildMultipleLevelSet, "MultipleLevelset");
14578 NEW_TIMER_STATIC(t_multiLevelSet, "Total time - multiple-levelset", buildMultipleLevelSet);
14579 NEW_SUB_TIMER_STATIC(t_c1, "identifyBodies", t_multiLevelSet);
14580 NEW_SUB_TIMER_STATIC(t_c2, "collectedLevelSet", t_multiLevelSet);
14581 NEW_SUB_TIMER_STATIC(t_c3, "gapHandling", t_multiLevelSet);
14582 NEW_SUB_TIMER_STATIC(t_c4, "gapCells", t_multiLevelSet);
14583 NEW_SUB_TIMER_STATIC(t_c5, "gapReInit", t_multiLevelSet);
14584 NEW_SUB_TIMER_STATIC(t_c6, "Tube0", t_multiLevelSet);
14585 NEW_SUB_TIMER_STATIC(t_c7, "curv+normal", t_multiLevelSet);
14586
14587 RECORD_TIMER_START(t_multiLevelSet);
14588
14589
14590 if(mode == 2) {
14591 // initialisation version
14592 identifyBodies(0);
14593 } else {
14594 // TODO labels:LS,TIMERS update default to faster shifting version after further testing!
14595 RECORD_TIMER_START(t_c1);
14596 identifyBodies();
14597 RECORD_TIMER_STOP(t_c1);
14598 }
14599
14600 RECORD_TIMER_START(t_c2);
14601 // generares the coorect collected levelSet!
14602 // the bodies need to be identified before!
14603 buildCollectedLevelSet(mode);
14604
14605 buildLevelSetTube(0);
14606 RECORD_TIMER_STOP(t_c2);
14607
14608 RECORD_TIMER_START(t_c3);
14609 gapHandling();
14610 RECORD_TIMER_STOP(t_c3);
14611
14612 RECORD_TIMER_START(t_c4);
14613 // if gaps exist, solve this
14614 if(m_closeGaps && gapCellsExist()) {
14615 // levelSet value reduction for G0-Band cells
14616 levelSetGapCorrect();
14617
14618 RECORD_TIMER_START(t_c6);
14619 buildLevelSetTube(0);
14620 RECORD_TIMER_STOP(t_c6);
14621
14622 setBandNewArrivals(0);
14623
14624 RECORD_TIMER_START(t_c7);
14625 if(m_guaranteeReinit) {
14626 computeNormalVectors(0);
14627 computeCurvature(0);
14628 }
14629 RECORD_TIMER_STOP(t_c7);
14630
14631 RECORD_TIMER_START(t_c5);
14632 if(m_guaranteeReinit) {
14633 levelSetReinitialization(0);
14634 }
14635 RECORD_TIMER_STOP(t_c5);
14636
14637 // levelSet value increase for G0-Band cells
14638 levelSetGapRecorrect();
14639
14640 reBuildCollectedLevelSet(1);
14641
14642 RECORD_TIMER_START(t_c6);
14643 buildLevelSetTube(0);
14644 RECORD_TIMER_STOP(t_c6);
14645
14646 setBandNewArrivals(0);
14647 }
14648
14649 RECORD_TIMER_STOP(t_c4);
14650
14651 exchangeAllLevelSetData();
14652
14653 if(!m_semiLagrange) {
14654 computeNormalVectors(0);
14655 computeCurvature(0);
14656 exchangeAllLevelSetData();
14657 }
14658
14659 RECORD_TIMER_STOP(t_multiLevelSet);
14660}
14661
14662
14666template <MInt nDim>
14667MBool LsCartesianSolver<nDim>::_levelSetSolutionStep() {
14668 TRACE();
14669
14670 if(m_freeSurface) {
14671 updateBndryCellList();
14672 return levelSetSolver();
14673
14674 } else if(m_combustion) {
14675 updateBndryCellList();
14676 applyLevelSetBoundaryConditions();
14677 return levelSetSolver();
14678
14679 } else if(!m_levelSetMb && m_semiLagrange) {
14680 applyLevelSetBoundaryConditions();
14681 return semiLagrangeTimeStep();
14682
14683 } else if(!m_levelSetMb) {
14684 applyLevelSetBoundaryConditions();
14685 return levelSetSolver();
14686
14687 } else if(m_levelSetMb) {
14688 ASSERT(!m_constructGField, "");
14689 ASSERT(m_semiLagrange, "");
14690 return semiLagrangeTimeStep();
14691 }
14692
14693 return true;
14694}
14695
14696
14700
14701template <MInt nDim>
14702MBool LsCartesianSolver<nDim>::finalizeLevelSet_(const MInt t_levelSet, const MInt t_output) {
14703 TRACE();
14704
14705 // Necessary to avoid 'unused-parameter' warning when timers are disabled
14706 static_cast<void>(t_levelSet);
14707 static_cast<void>(t_output);
14708
14709 NEW_SUB_TIMER_STATIC(t_levelSetGGrid, "GGrid", t_levelSet);
14710 NEW_SUB_TIMER_STATIC(t_levelSetFastGGrid, "FastGGrid", t_levelSet);
14711 NEW_SUB_TIMER_STATIC(t_levelSetCR, "CR", t_levelSet);
14712
14713 RECORD_TIMER_START(t_levelSetGGrid);
14714 buildLevelSetTube();
14715 setBandNewArrivals();
14716 RECORD_TIMER_STOP(t_levelSetGGrid);
14717
14718 // reinitializes the level set function
14719 RECORD_TIMER_START(t_levelSetCR);
14720 levelSetReinitialization();
14721 RECORD_TIMER_STOP(t_levelSetCR);
14722
14723 RECORD_TIMER_START(t_levelSetFastGGrid);
14724 fastBuildLevelSetTubeCG();
14725 RECORD_TIMER_STOP(t_levelSetFastGGrid);
14726
14727 if(m_combustion) {
14728 determineMinMaxMeanInterfacePosition();
14729 }
14730
14731 return true;
14732}
14736template <MInt nDim>
14737MBool LsCartesianSolver<nDim>::solutionStep() {
14738 TRACE();
14739
14740 if(m_constructGField) return true;
14741
14742 if(!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep > m_trackMbEnd) {
14743 return true;
14744 }
14745
14746 RECORD_TIMER_START(m_timers[Timers::TimeInt]);
14747 m_firstSolutionExchange = true;
14748 MBool timeStepCompleted = _levelSetSolutionStep();
14749 exchangeLeafDataLS<true>();
14750 RECORD_TIMER_STOP(m_timers[Timers::TimeInt]);
14751
14752 return timeStepCompleted;
14753}
14754
14755
14759template <MInt nDim>
14760void LsCartesianSolver<nDim>::finalizeLevelSet() {
14761 TRACE();
14762
14763 RECORD_TIMER_START(m_timers[Timers::Finalize]);
14764
14765 if(m_combustion || m_freeSurface) {
14766 buildLevelSetTube();
14767 setBandNewArrivals();
14768
14769 // rebuilds the tube and reinitializes the level set function
14770 levelSetReinitialization();
14771
14772 } else if(m_semiLagrange) {
14773 if(m_constructGField) {
14774 return;
14775 }
14776
14777 testCellsCG();
14778
14779 // for the individual sets
14780 RECORD_TIMER_START(m_timers[Timers::BuildTube]);
14781 buildLevelSetTube();
14782 RECORD_TIMER_STOP(m_timers[Timers::BuildTube]);
14783
14784 RECORD_TIMER_START(m_timers[Timers::SetBand]);
14785 setBandNewArrivals();
14786 RECORD_TIMER_STOP(m_timers[Timers::SetBand]);
14787
14788 // for the collected levelset
14789 RECORD_TIMER_START(m_timers[Timers::BuildMultiple]);
14790 buildMultipleLevelSet();
14791 RECORD_TIMER_STOP(m_timers[Timers::BuildMultiple]);
14792
14793 } else {
14794 testCellsCG();
14795
14796 buildLevelSetTube();
14797
14798 setBandNewArrivals();
14799
14800 computeNormalVectors();
14801
14802 computeCurvature();
14803
14804 levelSetReinitialization();
14805
14806 buildMultipleLevelSet();
14807 }
14808
14809 RECORD_TIMER_STOP(m_timers[Timers::Finalize]);
14810}
14811
14816template <MInt nDim>
14817void LsCartesianSolver<nDim>::determinePeriodicDistance() {
14818 TRACE();
14819
14820 // Determine local minimum ans maximum
14821 MFloat minPos = std::numeric_limits<MFloat>::max();
14822 MFloat maxPos = std::numeric_limits<MFloat>::lowest();
14823 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
14824 if(a_isHalo(cellId)) continue;
14825 MInt level = a_level(cellId);
14826 MFloat cellHalfLength = 0.5 * c_cellLengthAtLevel(level);
14827 if(c_coordinate(cellId, m_periodicDirection) - cellHalfLength < minPos) {
14828 minPos = c_coordinate(cellId, m_periodicDirection) - cellHalfLength;
14829 }
14830 if(c_coordinate(cellId, m_periodicDirection) + cellHalfLength > maxPos) {
14831 maxPos = c_coordinate(cellId, m_periodicDirection) + cellHalfLength;
14832 }
14833 }
14834
14835 // Exchange global minimum and maximum
14836 MPI_Allreduce(MPI_IN_PLACE, &maxPos, 1, MPI_DOUBLE, MPI_MAX, mpiComm(), AT_, "maxPos", "1");
14837 MPI_Allreduce(MPI_IN_PLACE, &minPos, 1, MPI_DOUBLE, MPI_MIN, mpiComm(), AT_, "minPos", "1");
14838
14839 m_periodicDistance = maxPos - minPos;
14840}
14841
14846template <MInt nDim>
14847void LsCartesianSolver<nDim>::initLocalizedLevelSetCG() {
14848 TRACE();
14849 MInt noCells;
14850
14851 m_log << "Initializing local levelset CG" << endl;
14852 if(domainId() == 0) {
14853 cerr << "Initializing local levelset CG" << endl;
14854 }
14855
14856 m_time = 0.0;
14857
14858 // initialise minGapWidth and minGapWidthDt1#
14859 if(m_closeGaps) {
14860 m_minGapWidth.clear();
14861 m_minGapWidthDt1.clear();
14862 for(MInt region = 0; region < m_noGapRegions; region++) {
14863 m_minGapWidth.push_back(std::numeric_limits<MFloat>::max());
14864 m_minGapWidthDt1.push_back(std::numeric_limits<MFloat>::max());
14865 }
14866 }
14867
14868 if(m_GFieldInitFromSTL) initializeGControlPoint();
14869
14870 for(MInt set = 0; set < m_noSets; set++)
14871 std::vector<MInt>().swap(m_bandCells[set]);
14872
14873 if(m_semiLagrange) {
14874 initializeIntegrationScheme_semiLagrange();
14875 } else {
14876 initializeIntegrationScheme();
14877 }
14878
14879 if(!m_initFromRestartFile) {
14880 // Iteration 1: (on minLevel-/boundingBoxLevel-basis)
14881 //------------------------------------------------
14882 // a) create G-Base-Grid
14883 // if( domainId()==0 ) { cerr << "G grid initialization: Iteration-1" << endl; }
14884
14885 createBaseGgridCG();
14886
14887 // c) initialize the G-field on minLevel-/boundingBoxLevel-basis
14888 if(m_GFieldInitFromSTL) {
14889 constructGFieldFromSTL(1);
14890 } else {
14891 initializeGField();
14892 }
14893
14894 // d) determine G-cell-properties
14895 if(m_buildCollectedLevelSetFunction) {
14896 buildCollectedLevelSet(0);
14897 }
14898
14899 determineG0Cells();
14900
14901 // Iteration 4:
14902 //------------------------------------------------
14903 // if( domainId()==0 ) { cerr << "G grid initialization: Iteration-4" << endl; }
14904
14905
14906 // a) refine or coarsen g0 cells!
14907 m_log << "createGgridCG is starting" << endl;
14908 createGgridCG();
14909 m_log << "createGgridCG is done" << endl;
14910
14911 // b) initialize again
14912 // if( m_GFieldInitFromSTL ) constructGFieldFromSTL(1);
14913 if(m_GFieldInitFromSTL) {
14914 determineG0Cells();
14915 determineBandCells();
14916 m_log << "Initialize G Field from stl data...";
14917 constructGFieldFromSTL(3);
14918 m_log << "ok" << endl;
14919 for(MInt set = 0; set < m_noSets; set++) {
14920 std::vector<MInt>().swap(m_bandCells[set]);
14921 }
14922 } else {
14923 initializeGField();
14924 }
14925
14926 // c) determine G-cell-properties
14927 if(m_buildCollectedLevelSetFunction) {
14928 buildCollectedLevelSet(0);
14929 }
14930
14931 m_log << "Determine G cells in Gamma...";
14932 determineG0Cells();
14933 m_log << "ok" << endl;
14934
14935 m_log << "Determine the narrow computation band...";
14936 determineBandCells();
14937 m_log << "ok" << endl;
14938
14939 m_log << "Update G boundary cell list...";
14940 updateBndryCellList();
14941 m_log << "ok" << endl;
14942
14943 m_log << "smallest gCell length " << m_gCellDistance << endl;
14944
14945 m_log << "Reset outside cells...";
14946 resetOutsideCells();
14947 m_log << "ok" << endl;
14948
14949 if(domainId() == 0) {
14950 cerr << "G grid Reinitialization " << endl;
14951 }
14952
14953 // moving boundary
14954 if(m_GFieldInitFromSTL) {
14955 constructGFieldFromSTL(0);
14956 }
14957
14958 // collected level-set function
14959 if(m_buildCollectedLevelSetFunction) {
14960 buildCollectedLevelSet(0);
14961 }
14962
14963 // claudia: check if this is really necessary here...
14964 if(m_GFieldInitFromSTL) {
14965 resetOutsideCells();
14966 }
14967
14968 if(m_levelSetRans) {
14969 constructGFieldFromSTL(1);
14970 updateAllLowerGridLevels();
14971 // initialization output for checking purpose
14972 if(m_GFieldFromSTLInitCheck) {
14973 writeRestartLevelSetFileCG(1, "restartLSGridCG_init", "restartLSCG_init");
14974 }
14975 return;
14976 }
14977
14978// usefull-debug-output:
14979#ifdef LS_DEBUG
14980 MInt globalTimeStep_temp = globalTimeStep;
14981 globalTimeStep = 0;
14982 writeRestartLevelSetFileCG(1, "restartLSGridCG_debug_0", "restartLSCG_debug_0");
14983 globalTimeStep = globalTimeStep_temp;
14984#endif
14985
14986 // if(m_initialRefinement) return;
14987
14988 // initialize fields...
14989 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
14990 for(MInt set = 0; set < m_maxNoSets; set++) {
14991 if(!m_semiLagrange) {
14992 for(MInt d = 0; d < nDim; d++) {
14993 a_extensionVelocityG(cellId, d, set) = F0;
14994 }
14995 } else {
14996 a_oldLevelSetFunctionG(cellId, set) = a_levelSetFunctionG(cellId, set);
14997 }
14998 }
14999 if(m_maxNoSets > 1 && m_closeGaps) {
15000 a_potentialGapCell(cellId) = 0;
15001 a_potentialGapCellClose(cellId) = 0;
15002 }
15003 }
15004
15005
15006 // initialization output for checking purpose
15007 if(m_GFieldFromSTLInitCheck) {
15008 writeRestartLevelSetFileCG(1, "restartLSGridCG_init", "restartLSCG_init");
15009 }
15010
15011 exchangeAllLevelSetData();
15012
15013 if(m_virtualSurgery) {
15014 initializeCollectedLevelSet(0);
15015 }
15016
15017 m_log << "*** G grid initialization finished ***" << endl;
15018
15019 } else { // initFromRestartFile
15020
15021 if(domainId() == 0) {
15022 cerr << " By loading localized level-set file: ";
15023 }
15024 stringstream levelSetFileName;
15025 levelSetFileName << restartDir() << "restartLSCG_init";
15026 if(!m_useNonSpecifiedRestartFile) levelSetFileName << "_0";
15027 levelSetFileName << ParallelIo::fileExt();
15028
15029
15030 if(domainId() == 0) {
15031 cerr << (levelSetFileName.str()).c_str() << endl;
15032 }
15033
15034 noCells = loadLevelSetGridFlowVarsParCG((levelSetFileName.str()).c_str());
15035
15036 ASSERT(a_noCells() == noCells, " size of collector is not noCells: " << a_noCells() << " noCells: " << noCells);
15037
15038 generateListOfGExchangeCellsCG();
15039
15040 for(MInt set = 0; set < m_noSets; set++) {
15041 std::vector<MInt>().swap(m_bandCells[set]);
15042 }
15043
15044 determineG0Cells();
15045
15046 createGgridCG();
15047
15048 determineG0Cells();
15049
15050 // set g_properties[0,1]
15051 determineBandCells();
15052
15053 setGCellBndryProperty();
15054
15055 if(m_levelSetRans) {
15056 updateAllLowerGridLevels();
15057 }
15058
15059 updateBndryCellList();
15060
15061 m_log << "Reset outside cells...";
15062 resetOutsideCells();
15063 m_log << "ok" << endl;
15064
15065 // initialize fields...
15066 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
15067 if(m_maxNoSets > 1 && m_closeGaps) {
15068 a_potentialGapCell(cellId) = 0;
15069 a_potentialGapCellClose(cellId) = 0;
15070 }
15071 }
15072
15073 if(m_combustion) {
15074 determineMinMaxMeanInterfacePosition();
15075 computeZeroLevelSetArcLength();
15076 }
15077
15078 if(m_initialRefinement) return;
15079
15080 if(m_GFieldFromSTLInitCheck) {
15081 writeRestartLevelSetFileCG(1, "restartLSGridCG_reinit", "restartLSCG_reinit");
15082 }
15083
15084 exchangeAllLevelSetData();
15085 }
15086}
15087
15088
15093template <MInt nDim>
15094void LsCartesianSolver<nDim>::createBaseGgridCG() {
15095 TRACE();
15096
15097 MBool& firstRun = m_static_createBaseGgrid_firstRun;
15098
15099 // assure that the function is only called once,
15100 // otherwise cells are added multiple-times!
15101 if(!firstRun) return;
15102 firstRun = false;
15103
15104 m_log << "createBaseGgridCG" << endl;
15105
15106 if(minLevel() == 0) {
15107 mTerm(1, AT_, "minLevel() is 0");
15108 }
15109
15110 // establish a base g cell grid
15111 for(MInt fc = 0; fc < grid().tree().size(); fc++) {
15112 a_appendCollector();
15113 m_cells.erase(a_noCells() - 1);
15114 }
15115
15116 generateListOfGExchangeCellsCG();
15117}
15118
15119
15124// this function does some sanity assert checks
15125template <MInt nDim>
15126void LsCartesianSolver<nDim>::testCellsCG() {
15127 TRACE();
15128
15129 if(!g_multiSolverGrid) {
15130 for(MInt gridCellId = 0; gridCellId < grid().raw().treeb().size(); gridCellId++) {
15131 ASSERT(grid().tree().solver2grid(gridCellId) == gridCellId, "");
15132 ASSERT(grid().tree().grid2solver(gridCellId) == gridCellId, "");
15133 }
15134 }
15135
15136 for(MInt gc = 0; gc < a_noCells(); gc++) {
15137 ASSERT(grid().tree().grid2solver(grid().tree().solver2grid(gc)) == gc,
15138 "proxy-grid map is incorrect: gc, grid().tree().solver2grid(gc), "
15139 "grid().tree().grid2solver(grid().tree().solver2grid(gc)): "
15140 << gc << " , " << grid().tree().solver2grid(gc) << " , "
15141 << grid().tree().grid2solver(grid().tree().solver2grid(gc)));
15142 }
15143}
15144
15152template <MInt nDim>
15153void LsCartesianSolver<nDim>::createGgridCG(MBool initRegrid) {
15154 TRACE();
15155
15156 m_log << "Reset lsSolver-regrid trigger at timestep: " << globalTimeStep << " init regrid: " << initRegrid << endl;
15157
15158 vector<MInt> lastLayer;
15159 vector<MInt> tmp;
15160
15161 // MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
15162 // MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
15163
15164 MBoolScratchSpace inShadowLayer(a_noCells(), AT_, "inShadowLayer");
15165 MBoolScratchSpace tmp_data(a_noCells(), AT_, "tmp_data");
15166
15167 MBool newVersion = false;
15168 MInt startSet = 0;
15169 if(newVersion) startSet = m_startSet;
15170
15171 // 1) reset regrid property for all cells
15172 // set inShadowLayer property for all G0-cells
15173 for(MInt gc = 0; gc < a_noCells(); gc++) {
15174 MBool isGZero = false;
15175 for(MInt set = startSet; set < m_noSets; set++) {
15176 if(/*newVersion &&*/ !m_computeSet_backup[set]) continue;
15177 if(a_isGZeroCell(gc, set)) {
15178 isGZero = true;
15179 break;
15180 }
15181 }
15182 inShadowLayer[gc] = isGZero;
15183 a_regridTriggerG(gc) = false;
15184 }
15185
15186
15187 for(MInt set = startSet; set < m_noSets; set++) { // m_startSet
15188 if(newVersion && !m_computeSet_backup[set]) continue;
15189 for(MInt id = 0; id < a_noG0Cells(set); id++) {
15190 const MInt currentCellId = a_G0CellId(id, set);
15191 MBool alreadyAdded = false;
15192 // loop over prevoius sets and check if the cell was already a G0 cell there
15193 // to avaoid double entries!
15194 if(set > 0) {
15195 for(MInt s = set - 1; s >= startSet; s--) { // m_startSet
15196 if(newVersion && !m_computeSet_backup[s]) continue;
15197 if(a_isGZeroCell(currentCellId, s)) {
15198 alreadyAdded = true;
15199 break;
15200 }
15201 }
15202 }
15203 if(!alreadyAdded) {
15204 lastLayer.emplace_back(currentCellId);
15205 }
15206 }
15207 }
15208
15209 // 4. cover shadow band locally in the domain
15210 MInt itCount = 0;
15211 while(itCount < m_gShadowWidth) {
15212 // ii. build the next layer
15213 tmp.clear();
15214 for(MInt c = 0; c < (signed)lastLayer.size(); c++) {
15215 const MInt cellId = lastLayer[c];
15216 for(MInt d = 0; d < m_noDirs; d++) {
15217 if(a_hasNeighbor(cellId, d) == 0) continue;
15218 const MInt nghbrId = c_neighborId(cellId, d);
15219 if(!inShadowLayer[nghbrId]) {
15220 tmp.emplace_back(nghbrId);
15221 if(itCount > m_gShadowWidth - m_gInnerBound) {
15222 a_regridTriggerG(nghbrId) = true;
15223 }
15224 }
15225 inShadowLayer[nghbrId] = true;
15226 }
15227 }
15228
15229 // exchange next layer with neighboring domains
15230 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
15231 for(MInt j = 0; j < noWindowCells(i); j++) {
15232 tmp_data(windowCellId(i, j)) = inShadowLayer(windowCellId(i, j));
15233 }
15234 }
15235 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
15236 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
15237 MInt windowId = grid().azimuthalWindowCell(i, j);
15238 tmp_data(windowId) = inShadowLayer(windowId);
15239 }
15240 }
15241
15242 exchangeDataLS(&tmp_data(0), 1);
15243
15244 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
15245#ifdef LS_DEBUG
15246 // check, if received data size matches expected size:
15247 if(!(receiveBufferSize.p[i] == noHaloCells(i))) {
15248 stringstream errorMessage{};
15249 errorMessage << "this was not expected to happen: wrong number of halo information, buf="
15250 << receiveBufferSize.p[i] << "noGHaloCells=" << noHaloCells(i) << ", shadow layer";
15251 m_log << errorMessage.str() << endl;
15252 cerr << errorMessage.str() << endl;
15253 }
15254#endif
15255 for(MInt j = 0; j < noHaloCells(i); j++) {
15256 const MInt haloCell = haloCellId(i, j);
15257 if(!inShadowLayer[haloCell]) {
15258 inShadowLayer[haloCell] = tmp_data(haloCell);
15259 if(inShadowLayer[haloCell]) {
15260 tmp.emplace_back(haloCell);
15261 if(itCount > m_gShadowWidth - m_gInnerBound) {
15262 a_regridTriggerG(haloCell) = true;
15263 }
15264 }
15265 }
15266 }
15267 }
15268 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
15269 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
15270 const MInt haloCell = grid().azimuthalHaloCell(i, j);
15271 if(!inShadowLayer[haloCell]) {
15272 inShadowLayer[haloCell] = tmp_data(haloCell);
15273 if(inShadowLayer[haloCell]) {
15274 tmp.emplace_back(haloCell);
15275 if(itCount > m_gShadowWidth - m_gInnerBound) {
15276 a_regridTriggerG(haloCell) = true;
15277 }
15278 }
15279 }
15280 }
15281 }
15282
15283 // iii. swap data
15284 // continue to the next layer
15285 lastLayer.clear();
15286 for(MInt c = 0; c < (signed)tmp.size(); c++) {
15287 lastLayer.emplace_back(tmp[c]);
15288 }
15289 itCount++;
15290 }
15291
15292 m_log << itCount << " layers built - ";
15293
15294 if(initRegrid) return;
15295
15296 // 4. update G on all coarse grid cells
15297 // assign the value of the first child cell to the parentId that exists
15298 // TODO labels:LS delete this update of lower-gridLevels!
15299 // once updateLowerGridLevels is called in prepareRestart
15300 // otherwise this changes the testcases on lower grid levels
15301 for(MInt level = maxRefinementLevel() - 1; level > minLevel() - 1; level--) {
15302 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
15303 if(a_level(cellId) == level) {
15304 for(MInt ch = 0; ch < IPOW2(nDim); ch++) {
15305 if(c_childId(cellId, ch) < 0) continue;
15306 for(MInt set = 0; set < m_noSets; set++) {
15307 if(level >= a_maxGCellLevel(set)) continue;
15308 a_levelSetFunctionG(cellId, set) = a_levelSetFunctionG(c_childId(cellId, ch), set);
15309 if(m_semiLagrange) {
15310 a_oldLevelSetFunctionG(cellId, set) = a_oldLevelSetFunctionG(c_childId(cellId, ch), set);
15311 }
15312 }
15313 break;
15314 }
15315 }
15316 }
15317 }
15318
15319 // set bodyId for multiple sets but without collected Levelset!
15320 if(!m_buildCollectedLevelSetFunction && !m_combustion && !m_freeSurface) {
15321 if(m_maxNoSets > 1 || m_GFieldInitFromSTL) {
15322 MInt body = -1;
15323 for(MInt set = 0; set < m_noSets; set++) {
15324 if(m_noBodiesInSet[set] > 0) {
15325 body = m_setToBodiesTable[set][0];
15326 }
15327 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
15328 a_bodyIdG(cellId, set) = body;
15329 }
15330 }
15331 } else {
15332 for(MInt set = 0; set < m_noSets; set++) {
15333 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
15334 a_bodyIdG(cellId, set) = 0;
15335 }
15336 }
15337 }
15338 }
15339}
15340
15341
15346template <MInt nDim>
15347void LsCartesianSolver<nDim>::generateListOfGExchangeCellsCG() {
15348 TRACE();
15349
15350 // Initialize Halo- and Window-Cells
15351 for(MInt gCell = 0; gCell < a_noCells(); gCell++) {
15352 a_isHalo(gCell) = false;
15353 a_isWindow(gCell) = false;
15354 }
15355
15356 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
15357 for(MInt j = 0; j < noHaloCells(i); j++) {
15358 a_isHalo(haloCellId(i, j)) = true;
15359 }
15360 for(MInt j = 0; j < noWindowCells(i); j++) {
15361 a_isWindow(windowCellId(i, j)) = true;
15362 }
15363 }
15364
15365 // Mark azimuthal periodic exchange halos
15366 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
15367 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
15368 a_isHalo(grid().azimuthalHaloCell(i, j)) = true;
15369 }
15370 }
15371 for(MInt i = 0; i < grid().noAzimuthalUnmappedHaloCells(); i++) {
15372 a_isHalo(grid().azimuthalUnmappedHaloCell(i)) = true;
15373 }
15374}
15375
15385template <MInt nDim>
15386void LsCartesianSolver<nDim>::buildLevelSetTube(MInt mode) {
15387 TRACE();
15388
15389 // timer-for mode 1:
15390 NEW_TIMER_GROUP_STATIC(buildLevelSet, "Level Set - build tube");
15391 NEW_TIMER_STATIC(t_levelSetTube, "Total time - build tube", buildLevelSet);
15392 NEW_SUB_TIMER_STATIC(t_a1, "updateLowerGridLevels", t_levelSetTube);
15393 NEW_SUB_TIMER_STATIC(t_a2, "determineG0Cells", t_levelSetTube);
15394 NEW_SUB_TIMER_STATIC(t_a3, "determineBandCells", t_levelSetTube);
15395 NEW_SUB_TIMER_STATIC(t_a4, "regridCheck", t_levelSetTube);
15396 NEW_SUB_TIMER_STATIC(t_a5, "createGGrid", t_levelSetTube);
15397 NEW_SUB_TIMER_STATIC(t_a6, "group", t_levelSetTube);
15398 NEW_SUB_TIMER_STATIC(t_a7, "updateBnd", t_levelSetTube);
15399 NEW_SUB_TIMER_STATIC(t_a8, "resetOutside", t_levelSetTube);
15400
15401 // time for mode 0:
15402 NEW_TIMER_GROUP_STATIC(buildLevelSetZero, "Zero Level Set - build tube");
15403 NEW_TIMER_STATIC(t_levelSetTubeZero, "Total time - build tube zero", buildLevelSetZero);
15404 NEW_SUB_TIMER_STATIC(t_b1, "determineG0Cells", t_levelSetTubeZero);
15405 NEW_SUB_TIMER_STATIC(t_b2, "determineBandCells", t_levelSetTubeZero);
15406 NEW_SUB_TIMER_STATIC(t_b3, "resetOutside", t_levelSetTubeZero);
15407
15408 if(mode == 0) {
15409 RECORD_TIMER_START(t_levelSetTubeZero);
15410 } else {
15411 RECORD_TIMER_START(t_levelSetTube);
15412 }
15413
15414
15415 // if in the complete global domain, there are no G0 cells present, currently no LVS is computed...
15416 MInt status = 1;
15417 if(mode != 0) {
15418 status = mMin(1, a_noG0Cells(0));
15419 for(MInt set = 1; set < m_noSets; set++) {
15420 status = mMin(status, a_noG0Cells(set));
15421 }
15422 }
15423
15424 if(mode != 0) {
15425 RECORD_TIMER_START(t_a1);
15426 }
15427
15428 // TODO labels:LS uncomment the below and all lines with
15429 // avoid updateLowerGridLevels
15430 // and update testcases accordingly! The leafCell computation doesn't need the lower levels!
15431 // but testcases fail otherwise!
15432 // if(!m_levelSetMb) {
15433 updateLowerGridLevels(mode);
15434 //}
15435 if(mode != 0) {
15436 RECORD_TIMER_STOP(t_a1);
15437 }
15438
15439 if(mode == 0) {
15440 RECORD_TIMER_START(t_b1);
15441 } else {
15442 RECORD_TIMER_START(t_a2);
15443 }
15444 determineG0Cells(mode);
15445 if(mode == 0) {
15446 RECORD_TIMER_STOP(t_b1);
15447 } else {
15448 RECORD_TIMER_STOP(t_a2);
15449 }
15450
15451 if(mode == 0) {
15452 RECORD_TIMER_START(t_b2);
15453 } else {
15454 RECORD_TIMER_START(t_a3);
15455 }
15456 determineBandCells(mode);
15457 if(mode == 0) {
15458 RECORD_TIMER_STOP(t_b2);
15459 } else {
15460 RECORD_TIMER_STOP(t_a3);
15461 }
15462
15463 MInt regrid = 0;
15464 // check if the level set status changed (i,e, an interface appeared or disappeared)
15465 // only check, if not called for gap closing and other operations on the collected level-set function [mode 0]
15466 if(mode != 0) {
15467 RECORD_TIMER_START(t_a4);
15468 regrid = (MInt)regridLevelSet();
15469
15470 MInt newStatus = mMin(1, a_noG0Cells(0));
15471 for(MInt set = 1; set < m_noSets; set++) {
15472 newStatus = mMin(newStatus, a_noG0Cells(set));
15473 }
15474
15475 MPI_Allreduce(MPI_IN_PLACE, &status, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "status");
15476 MPI_Allreduce(MPI_IN_PLACE, &newStatus, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "newStatus");
15477 MPI_Allreduce(MPI_IN_PLACE, &regrid, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE", "regrid");
15478
15479 if(m_reconstructOldG) {
15480 MPI_Allreduce(MPI_IN_PLACE, &m_rotatingReinitTrigger, 1, MPI_INT, MPI_MAX, mpiComm(), AT_, "MPI_IN_PLACE",
15481 "m_rotatingReinitTrigger");
15482 if(m_rotatingReinitTrigger) {
15483 reconstructOldGField();
15484 }
15485 }
15486
15487 if(regrid != 0) m_log << "body-movement caused regridding" << endl;
15488
15489 if(newStatus != status) {
15490 regrid = 1;
15491 m_log << "changed number of G0-cells from " << status << " to " << newStatus << " caused regridding" << endl;
15492 }
15493
15494 RECORD_TIMER_STOP(t_a4);
15495 }
15496
15497 if(regrid != 0) {
15498 m_forceAdaptation = true;
15499 // This should force a global mesh-adaptation though the grid-controller at the next time-Step!
15500
15501 if(domainId() == 0) {
15502 cerr << "LS-Solver is forcing a mesh-adaptation at time step " << globalTimeStep << " ...";
15503 }
15504
15505 m_log << "LS-Solver is forcing a mesh-adaptation at time step " << globalTimeStep << endl;
15506 m_reinitConvergence = m_reinitConvergenceReset; // this prevents a double reduction of the reinit criterion which
15507 // can appearently happen in the unified run loop
15508 m_reinitConvergence = m_reinitConvergence / F3;
15509
15510 m_log << "reinitConvergence is temporarily decreased by a factor of 3 " << m_reinitConvergence << endl;
15511
15512 if(!m_levelSetMb || (!this->m_adaptation && m_levelSetMb)) {
15513 determineG0Cells();
15514
15515 // reset m_computeSet, since if cells are deleted, G0Cells etc. have to be updated for all sets!
15516 for(MInt set = 0; set < m_noSets; set++) {
15517 m_computeSet_tmp[set] = m_computeSet[set];
15518 m_computeSet[set] = true;
15519 m_changedSet[set] = true;
15520 }
15521
15522 for(MInt set = 0; set < m_noSets; set++)
15523 std::vector<MInt>().swap(m_bandCells[set]);
15524
15525 RECORD_TIMER_START(t_a5);
15526 createGgridCG();
15527 RECORD_TIMER_STOP(t_a5);
15528
15529 RECORD_TIMER_START(t_a6);
15530 determineG0Cells();
15531 determineBandCells();
15532
15533 // use updateLowerGridLevels instead of levelSetRestriction, it is more accurate!
15534 if(m_combustion) {
15535 levelSetRestriction();
15536 } else {
15537 updateLowerGridLevels(mode);
15538 }
15539 RECORD_TIMER_STOP(t_a6);
15540
15541 RECORD_TIMER_START(t_a7);
15542 setGCellBndryProperty();
15543 updateBndryCellList();
15544 RECORD_TIMER_STOP(t_a7);
15545
15546 // reset m_computeSet, since if cells are deleted, G0Cells etc. had to be updated for all sets!
15547 for(MInt set = 0; set < m_noSets; set++) {
15548 m_computeSet[set] = m_computeSet_tmp[set];
15549 }
15550
15551 if(domainId() == 0) cerr << " finished." << endl;
15552 }
15553 }
15554
15555 if(!m_levelSetMb) {
15556 // TODO labels:LS,TIMERS fix timers for different modes
15557 /* RECORD_TIMER_START(t_a7); */
15558 updateBndryCellList();
15559 /* RECORD_TIMER_STOP(t_a7); */
15560 }
15561
15562 if(mode == 0) {
15563 RECORD_TIMER_START(t_b3);
15564 } else {
15565 RECORD_TIMER_START(t_a8);
15566 }
15567 resetOutsideCells(mode);
15568 if(mode == 0) {
15569 RECORD_TIMER_STOP(t_b3);
15570 } else {
15571 RECORD_TIMER_STOP(t_a8);
15572 }
15573
15574 if(mode == 0) {
15575 RECORD_TIMER_STOP(t_levelSetTubeZero);
15576 } else {
15577 RECORD_TIMER_STOP(t_levelSetTube);
15578 }
15579}
15580
15581
15586template <MInt nDim>
15587void LsCartesianSolver<nDim>::fastBuildLevelSetTubeCG() {
15588 TRACE();
15589
15590
15591 NEW_TIMER_GROUP(fastBuildLevelSet, "Level Set - build tube");
15592 NEW_TIMER(t_levelSet, "Total time - build tube", fastBuildLevelSet);
15593 NEW_SUB_TIMER(t_updateL, "updateLowerGridLevels", t_levelSet);
15594 NEW_SUB_TIMER(t_detBand, "determineBandCells", t_levelSet);
15595 NEW_SUB_TIMER(t_detG0, "determineG0Cells", t_levelSet);
15596
15597
15598 RECORD_TIMER_START(t_levelSet);
15599
15600 RECORD_TIMER_START(t_updateL);
15601 updateLowerGridLevels();
15602 RECORD_TIMER_STOP(t_updateL);
15603
15604 RECORD_TIMER_START(t_detBand);
15605 determineG0Cells();
15606 RECORD_TIMER_STOP(t_detBand);
15607
15608 RECORD_TIMER_START(t_detG0);
15609 determineBandCells();
15610 RECORD_TIMER_STOP(t_detG0);
15611
15612 updateBndryCellList(); // Stephan
15613
15614 RECORD_TIMER_STOP(t_levelSet);
15615}
15616
15621template <MInt nDim>
15622void LsCartesianSolver<nDim>::restartLocalizedLevelSetCG() {
15623 TRACE();
15624 stringstream fileName;
15625 MInt noCells;
15626 //---
15627
15628 m_log << " Restarting localized level-set... " << endl;
15629 if(domainId() == 0) {
15630 cerr << " Restarting localized level-set... " << endl;
15631 }
15632
15633 // initialise minGapWidth and minGapWidthDt1
15634 if(m_closeGaps) {
15635 m_minGapWidth.clear();
15636 m_minGapWidthDt1.clear();
15637 for(MInt region = 0; region < m_noGapRegions; region++) {
15638 m_minGapWidth.push_back(std::numeric_limits<MFloat>::max());
15639 m_minGapWidthDt1.push_back(std::numeric_limits<MFloat>::max());
15640 }
15641 }
15642
15643 if(m_GFieldInitFromSTL) initializeGControlPoint();
15644
15645 for(MInt set = 0; set < m_noSets; set++)
15646 std::vector<MInt>().swap(m_bandCells[set]);
15647
15648 if(m_semiLagrange) {
15649 initializeIntegrationScheme_semiLagrange();
15650 } else {
15651 initializeIntegrationScheme();
15652 }
15653
15654 // TODO labels:LS,toremove run_unified remove this, globalTimeStep should not be set by the solver
15655 if(!m_levelSetMb) globalTimeStep = m_restartTimeStep;
15656
15657 stringstream levelSetFileName;
15658 if(!g_multiSolverGrid) {
15659 levelSetFileName << restartDir() << "restartLSCG";
15660 } else {
15661 levelSetFileName << restartDir() << "restartLSCG_" << m_solverId;
15662 }
15663 if(!m_useNonSpecifiedRestartFile) levelSetFileName << "_" << m_restartTimeStep;
15664 levelSetFileName << ParallelIo::fileExt();
15665 if(domainId() == 0) {
15666 cerr << " Loading " << (levelSetFileName.str()).c_str() << endl;
15667 }
15668
15669 noCells = loadLevelSetGridFlowVarsParCG((levelSetFileName.str()).c_str());
15670 ASSERT(a_noCells() == noCells && noCells == grid().tree().size(),
15671 " size of collector is not noCells: " << a_noCells() << " noCells: " << noCells);
15672
15673 generateListOfGExchangeCellsCG();
15674
15675 testCellsCG();
15676
15677 // set g0 cells on the base grid
15678 determineG0Cells();
15679
15680 for(MInt set = 0; set < m_noSets; set++) {
15681 std::vector<MInt>().swap(m_bandCells[set]);
15682 // very important trigger: determineG0Cells will reset inBand, inGamma,... for all cells
15683 }
15684
15685 determineG0Cells();
15686
15687 determineBandCells();
15688
15689 exchangeLevelSet();
15690
15691 setGCellBndryProperty();
15692
15693 updateBndryCellList();
15694
15695 resetOutsideCells();
15696
15697 exchangeAllLevelSetData();
15698
15699 if(m_virtualSurgery && isActive()) {
15700 initializeCollectedLevelSet(2);
15701 }
15702
15703 if(m_levelSetRans) {
15704 updateAllLowerGridLevels();
15705 }
15706
15707 // initialize fields...
15708 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
15709 if(m_maxNoSets > 1 && m_closeGaps) {
15710 a_potentialGapCell(cellId) = 0;
15711 a_potentialGapCellClose(cellId) = 0;
15712 }
15713 }
15714
15715 if(m_combustion) {
15716 determineMinMaxMeanInterfacePosition();
15717 computeZeroLevelSetArcLength();
15718 }
15719}
15720
15721
15726template <MInt nDim>
15727MInt LsCartesianSolver<nDim>::loadLevelSetGridFlowVarsParCG(const MChar* fileName) {
15728 TRACE();
15729
15730
15731 IF_CONSTEXPR(nDim != 2 && nDim != 3) {
15732 cerr << " In global function loadGridFlowVarsPar: wrong number of dimensions !" << endl;
15733 mTerm(1, AT_);
15734 return 0;
15735 }
15736
15737 using namespace maia::parallel_io;
15738 ParallelIo data(fileName, PIO_READ, mpiComm());
15739
15740 if(m_LSSolver) {
15741 // set level set time
15742 data.getAttribute(&m_time, "levelSetTime");
15743 }
15744
15745 MInt noCells = 0;
15746 MInt noGridCell = grid().tree().size();
15747 MInt noInternalGCells = 0;
15748
15749 for(MInt i = 0; i < noGridCell; i++) {
15750 noCells++;
15751 if(grid().tree().hasProperty(i, Cell::IsHalo)) {
15752 continue;
15753 }
15754 ++noInternalGCells;
15755 }
15756
15757 MFloatScratchSpace tmpFloat(noCells, AT_, "tmpFloat");
15758 MLongScratchSpace tmpInt(noCells, AT_, "tmpInt");
15759 tmpFloat.fill(-2.0);
15760 tmpInt.fill(-2);
15761
15762 vector<MString> variableNames = data.getDatasetNames(1);
15763 MString dataVarName;
15764 MInt dataVarId;
15765
15766 // This should be the same for all the variables
15767 ParallelIo::size_type dimLen = noInternalGCells;
15768 ParallelIo::size_type start = grid().domainOffset(domainId()) - grid().raw().m_32BitOffset;
15769 // set offset for all read operations
15770 data.setOffset(dimLen, start);
15771
15772 data.getAttribute(&dataVarName, "name", variableNames[0]);
15773 ASSERT(dataVarName == "G" || dataVarName == "G_0", "ERROR retsart-file, wrong Variable-name ordering");
15774 data.readArray(&tmpFloat[0], variableNames[0]);
15775
15776 dataVarName.clear();
15777 dataVarId = -1;
15778 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15779 data.getAttribute(&dataVarName, "name", variableNames[i]);
15780 if("regrid" == dataVarName) {
15781 dataVarId = i;
15782 break;
15783 }
15784 }
15785
15786 data.readArray(&tmpInt[0], variableNames[dataVarId]);
15787
15788 // exchange G0-values to get correct values on halo cells!
15789 // otherwise halo cells will not be detected as g cells
15790 exchangeDataLS(&tmpFloat[0], 1);
15791 exchangeDataLS(&tmpInt[0], 1);
15792
15793 for(MInt i = 0; i < noGridCell; ++i) {
15794 a_appendCollector();
15795
15796 a_regridTriggerG(i) = tmpInt[i];
15797 a_levelSetFunctionG(i, 0) = tmpFloat[i];
15798 }
15799
15800 if(m_maxNoSets > 1) {
15801 for(MInt set = 1; set < m_noSets; set++) {
15802 dataVarName.clear();
15803 dataVarId = -1;
15804 string tmps = "G_" + to_string(set);
15805 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15806 data.getAttribute(&dataVarName, "name", variableNames[i]);
15807 if(tmps == dataVarName) {
15808 dataVarId = i;
15809 break;
15810 }
15811 }
15812 if(dataVarId == -1)
15813 mTerm(1, AT_, "ERROR: More levelsets specified in the properties file than existing in the restart-file!");
15814
15815 data.readArray(&tmpFloat[0], variableNames[dataVarId]);
15816 for(MInt i = 0; i < noGridCell; ++i) {
15817 a_levelSetFunctionG(i, set) = tmpFloat[i];
15818 }
15819 }
15820 }
15821
15822 if(m_semiLagrange && m_maxNoSets == 1) {
15823 dataVarName.clear();
15824 dataVarId = -1;
15825 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15826 data.getAttribute(&dataVarName, "name", variableNames[i]);
15827 if("oldG" == dataVarName) {
15828 dataVarId = i;
15829 break;
15830 }
15831 }
15832 data.readArray(&tmpFloat[0], variableNames[dataVarId]);
15833 for(MInt i = 0; i < noGridCell; ++i) {
15834 a_oldLevelSetFunctionG(i, 0) = tmpFloat[i];
15835 }
15836 } else if(m_semiLagrange && m_maxNoSets > 1) {
15837 for(MInt set = 0; set < m_noSets; set++) {
15838 string tmps = "oldG_" + to_string(set);
15839 dataVarName.clear();
15840 dataVarId = -1;
15841 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15842 data.getAttribute(&dataVarName, "name", variableNames[i]);
15843 if(tmps == dataVarName) {
15844 dataVarId = i;
15845 break;
15846 }
15847 }
15848 data.readArray(&tmpFloat[0], variableNames[dataVarId]);
15849 for(MInt i = 0; i < noGridCell; ++i) {
15850 a_oldLevelSetFunctionG(i, set) = tmpFloat[i];
15851 }
15852 }
15853 }
15854
15855
15856 if(m_semiLagrange) {
15857 if(m_LsRotate) {
15858 if(!m_reconstructOldG) {
15859 MInt body;
15860 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
15861 body = m_bodiesToCompute[b];
15862
15863 string tmps = "containingCell_" + to_string(body);
15864 dataVarName.clear();
15865 dataVarId = -1;
15866 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15867 data.getAttribute(&dataVarName, "name", variableNames[i]);
15868 if(tmps == dataVarName) {
15869 dataVarId = i;
15870 break;
15871 }
15872 }
15873 data.readArray(&tmpInt[0], variableNames[dataVarId]);
15874
15875 for(MInt i = 0; i < noGridCell; ++i) {
15876 a_containingCell(i, b) = tmpInt[i];
15877 }
15878 globalToLocalIdsContainingCells();
15879 }
15880
15881 dataVarName.clear();
15882 dataVarId = -1;
15883 for(MInt i = 0; i < (signed)variableNames.size(); ++i) {
15884 data.getAttribute(&dataVarName, "name", variableNames[i]);
15885 if("initialGCell" == dataVarName) {
15886 dataVarId = i;
15887 break;
15888 }
15889 }
15890 data.readArray(&tmpInt[0], variableNames[dataVarId]);
15891 for(MInt i = 0; i < noGridCell; ++i) {
15892 m_initialGCell[i] = tmpInt[i];
15893 }
15894 }
15895
15896 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
15897 for(MInt j = 0; j < nDim; j++) {
15898 MInt id = i * nDim + j;
15899 string tmps = "SL_xRot_" + to_string(id);
15900 data.readScalar(&m_semiLagrange_xRot_ref[id], tmps.c_str());
15901 }
15902 }
15903
15904 if(m_reconstructOldG) {
15905 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
15906 for(MInt j = 0; j < nDim; j++) {
15907 MInt id = i * nDim + j;
15908 string tmps = "SL_xRot_STL" + to_string(id);
15909 data.readScalar(&m_semiLagrange_xRot_STL[id], tmps.c_str());
15910 }
15911 }
15912 } else {
15913 std::copy_n(&m_semiLagrange_xRot_ref[0], nDim * m_noEmbeddedBodies, &m_semiLagrange_xRot_STL[0]);
15914 }
15915 }
15916
15917 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
15918 for(MInt j = 0; j < nDim; j++) {
15919 MInt id = i * nDim + j;
15920 string tmps = "SL_xShift_" + to_string(id);
15921 data.readScalar(&m_semiLagrange_xShift_ref[id], tmps.c_str());
15922 }
15923 }
15924 }
15925
15926 if(m_noGapRegions > 0) {
15927 for(MInt i = 0; i < m_noGapRegions; i++) {
15928 string tmps = "deltaMin_" + to_string(i);
15929 data.readScalar(&m_minGapWidth[i], tmps.c_str());
15930 }
15931 }
15932
15933
15934 // generate the window and halo cells of the level set
15935 generateListOfGExchangeCellsCG();
15936 // exchange to get correct values for halo cells
15937
15938 exchangeAllLevelSetData();
15939
15940 return a_noCells();
15941}
15942
15948template <MInt nDim>
15949void LsCartesianSolver<nDim>::writeRestartLevelSetFileCG(MBool writeRestart,
15950 const MString& levelSetFileNameGGrid,
15951 const MString& levelSetFileNameGSol) {
15952 if(m_restartInterval == -1) return;
15953 if(((globalTimeStep % m_restartInterval) == 0 && globalTimeStep > m_restartTimeStep) || writeRestart) {
15954 if(domainId() == 0) {
15955 cerr << endl;
15956 cerr << "Writing levelset CG restart file at time step " << globalTimeStep << " ..." << endl;
15957 }
15958 writeRestart = true;
15959 }
15960 if(!writeRestart) return;
15961
15962 std::ignore = levelSetFileNameGGrid;
15963 stringstream gridFile;
15964 stringstream gridFilePath;
15965 gridFile << "grid_" << globalTimeStep << ".Netcdf";
15966 gridFilePath << outputDir() << "grid_" << globalTimeStep << ".Netcdf";
15967 MIntScratchSpace recalcIds(grid().raw().treeb().size(), AT_, "recalcIds");
15968
15969 grid().raw().saveGrid((gridFilePath.str()).c_str(), recalcIds.begin());
15970
15971 ASSERT(m_currentFileName.empty(), "");
15972 m_currentFileName = levelSetFileNameGSol;
15973
15974 writeRestartFile(true, false, (gridFile.str()).c_str(), recalcIds.begin());
15975
15976 m_currentFileName.clear();
15977}
15978
15983template <MInt nDim>
15984MBool LsCartesianSolver<nDim>::levelSetAdaptationTrigger() {
15985 TRACE();
15986 MInt mode = -1;
15987
15988 MIntScratchSpace globalRegrid(1, AT_, "globalRegrid");
15989 MIntScratchSpace regrid(1, AT_, "regrid");
15990 MIntScratchSpace globalStatus(1, AT_, "globalStatus");
15991 MIntScratchSpace status(1, AT_, "status");
15992 MIntScratchSpace newStatus(1, AT_, "newStatus");
15993
15994 // if in the complete global domain, there are no G0 cells present, currently no LVS is computed...
15995 status.p[0] = mMin(1, a_noG0Cells(0));
15996 for(MInt set = 1; set < m_noSets; set++) {
15997 status.p[0] = mMin(status.p[0], a_noG0Cells(set));
15998 }
15999 MPI_Allreduce(status.getPointer(), globalStatus.getPointer(), 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
16000 "status.getPointer()", "globalStatus.getPointer()");
16001 status.p[0] = globalStatus.p[0];
16002
16003 // required here, since determineG0Cells may rely on lower grid levels...
16004 updateLowerGridLevels(mode);
16005 determineG0Cells(mode);
16006 determineBandCells(mode);
16007 updateBndryCellList();
16008 regrid.p[0] = 0;
16009 // check if the level set status changed (i,e, an interface appeared or disappeared)
16010 // only check, if not called for gap closing and other operations on the collected level-set function [mode 0]
16011 regrid.p[0] = (MInt)regridLevelSet();
16012 newStatus.p[0] = mMin(1, a_noG0Cells(0));
16013 for(MInt set = 1; set < m_noSets; set++) {
16014 newStatus.p[0] = mMin(newStatus.p[0], a_noG0Cells(set));
16015 }
16016
16017 MPI_Allreduce(newStatus.getPointer(), globalStatus.getPointer(), 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
16018 "newStatus.getPointer()", "globalStatus.getPointer()");
16019 newStatus.p[0] = globalStatus.p[0];
16020
16021 MPI_Allreduce(regrid.getPointer(), globalRegrid.getPointer(), 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
16022 "regrid.getPointer()", "globalRegrid.getPointer()");
16023 regrid.p[0] = globalRegrid.p[0];
16024
16025 if(newStatus.p[0] != status.p[0]) regrid.p[0] = true;
16026
16027
16028 return regrid.p[0];
16029}
16030
16035template <MInt nDim>
16036void LsCartesianSolver<nDim>::refineCell(const MInt gridCellId) {
16037 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
16038
16039 for(MInt child = 0; child < grid().m_maxNoChilds; child++) {
16040 const MInt childId = grid().raw().treeb().child(gridCellId, child);
16041
16042 if(childId == -1) continue;
16043
16044 // @ansgar_pls_adapt2 test this for ls solver!
16045 // --> this sort of skip at least causes one assert in compactCells to fail (see testcase
16046 // LS/2D_twoLsBlock_slottedDisk_different_rotations_single with partitionCellMaxNoOffspring=1
16047 // Skip if cell is a partition level ancestor and its child was not newly created
16048 if(!grid().raw().a_hasProperty(childId, Cell::WasNewlyCreated)
16049 && grid().raw().a_hasProperty(gridCellId, Cell::IsPartLvlAncestor)) {
16050 continue;
16051 }
16052
16053 if(!g_multiSolverGrid) ASSERT(grid().raw().a_hasProperty(childId, Cell::WasNewlyCreated), "");
16054
16055 // If solver is inactive all cells musst be halo cells!
16056 if(!isActive()) ASSERT(grid().raw().a_isHalo(childId), "");
16057
16058 if(grid().azimuthalPeriodicity()) {
16059 // Solver flag will be set in proxy
16060 // The cartesianGrid does not know the geometry, therefore it needs to be checked
16061 // that the child actually is inside the geometry
16062 if(grid().checkOutsideGeometry(childId) == 1) {
16063 grid().raw().setSolver(childId, solverId(), false);
16064 continue;
16065 }
16066 }
16067
16068 // If child exists in grid but is not located inside solver geometry
16069 if(!grid().solverFlag(childId, solverId())) continue;
16070
16071 const MInt solverChildId = this->createCellId(childId);
16072
16073 if(!g_multiSolverGrid) ASSERT(solverChildId == childId, "");
16074
16075 // avoid faulty initialisation of childs
16076 for(MInt set = m_startSet; set < m_noSets; set++) {
16077 a_inBandG(solverChildId, set) = a_inBandG(solverCellId, set);
16078 }
16079
16080 for(MInt set = 0; set < m_noSets; set++) {
16081 a_levelSetFunctionG(solverChildId, set) = a_levelSetFunctionG(solverCellId, set);
16082 if(m_semiLagrange) {
16083 a_oldLevelSetFunctionG(solverChildId, set) = a_oldLevelSetFunctionG(solverCellId, set);
16084 }
16085 if(m_levelSetMb) a_bodyIdG(solverChildId, set) = a_bodyIdG(solverCellId, set);
16086 }
16087
16088 if(!a_isHalo(solverCellId) && globalTimeStep > 0) {
16089 if(m_virtualSurgery) {
16090 if((a_levelSetFunctionG(solverCellId, 1) * a_levelSetFunctionG(solverCellId, 2)) < 0) {
16091 m_refinedCells.insert(make_pair(solverCellId, 0));
16092 }
16093 } else {
16094 MInt cellAdded = 0;
16095 for(MInt set = m_startSet; set < m_noSets; set++) {
16096 if(a_inBandG(solverCellId, set)) {
16097 if(!m_computeSet_backup[set] || m_maxLevelChange) {
16098 cellAdded++;
16099 if(cellAdded > 1) {
16100 auto it0 = m_refinedCells.find(solverChildId);
16101 ASSERT(it0 != m_refinedCells.end(), "");
16102 m_refinedCells.erase(it0);
16103 m_refinedCells.insert(make_pair(solverChildId, 0));
16104 } else {
16105 m_refinedCells.insert(make_pair(solverChildId, set));
16106 }
16107 }
16108
16109 if(m_computeSet_backup[set]) {
16110 // tested only for m_maxLevelChange, in this case the levelSet is interpolated
16111 // and the old-levelSet is reconstructed to maintain mass-conservation!
16112 MInt interpolationCells[8] = {0, 0, 0, 0, 0, 0, 0, 0};
16113 MFloat cellPos[3] = {c_coordinate(solverChildId, 0), c_coordinate(solverChildId, 1),
16114 c_coordinate(solverChildId, nDim - 1)};
16115 const MInt position = setUpLevelSetInterpolationStencil(solverCellId, interpolationCells, cellPos);
16116 if(position > -1) {
16117 if(!m_maxLevelChange) {
16118 a_oldLevelSetFunctionG(solverChildId, set) = interpolateOldLevelSet(interpolationCells, cellPos, set);
16119 }
16120 a_levelSetFunctionG(solverChildId, set) = interpolateLevelSet(interpolationCells, cellPos, set);
16121 }
16122 }
16123 }
16124 }
16125 }
16126 }
16127
16128 if(m_LsRotate) {
16129 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16130 a_containingCell(solverChildId, b) = -1;
16131 if(!m_reconstructOldG) {
16132 a_containingDomain(solverChildId, b) = -1;
16133 m_initialGCell[solverChildId] = 0;
16134 }
16135 }
16136 }
16137 }
16138}
16139
16144template <MInt nDim>
16145void LsCartesianSolver<nDim>::removeChilds(const MInt gridCellId) {
16146 // If solver is inactive cell musst never be a internal cell
16147 if(!isActive()) {
16148 ASSERT(grid().raw().a_isHalo(gridCellId), "");
16149 }
16150
16151 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
16152
16153 for(MInt set = 0; set < m_noSets; set++) {
16154 a_inBandG(solverCellId, set) = false;
16155 }
16156
16157
16158 ASSERT(solverCellId > -1 && solverCellId < m_cells.size(), "solverCellId is: " << solverCellId);
16159 if(!g_multiSolverGrid) ASSERT(solverCellId == gridCellId, "");
16160
16161 for(MInt set = 0; set < m_noSets; set++) {
16162 a_levelSetFunctionG(solverCellId, set) = F0;
16163 if(m_semiLagrange) {
16164 a_oldLevelSetFunctionG(solverCellId, set) = F0;
16165 }
16166 }
16167 MInt noChildren = 0;
16168
16169 for(MInt c = 0; c < grid().m_maxNoChilds; c++) {
16170 MInt childId = c_childId(solverCellId, c);
16171 if(childId < 0) continue;
16172 noChildren++;
16173 for(MInt set = 0; set < m_noSets; set++) {
16174 a_levelSetFunctionG(solverCellId, set) += a_levelSetFunctionG(childId, set);
16175 if(m_semiLagrange) {
16176 a_oldLevelSetFunctionG(solverCellId, set) += a_oldLevelSetFunctionG(childId, set);
16177 }
16178 }
16179
16180 if(m_LsRotate) {
16181 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16182 a_containingCell(childId, b) = -1;
16183 if(!m_reconstructOldG) {
16184 a_containingDomain(childId, b) = -1;
16185 if(!a_isHalo(childId) && m_initialGCell[childId] == 1) {
16186 MInt parentId = c_parentId(childId);
16187 cerr << c_globalId(childId) << "," << c_globalId(parentId) << "," << a_level(childId) << ","
16188 << a_isHalo(childId) << "," << a_isHalo(parentId) << endl;
16189 mTerm(1, AT_, "Initial G cell is deleted!");
16190 }
16191 }
16192 }
16193 }
16194 for(MInt set = m_startSet; set < m_noSets; set++) {
16195 a_inBandG(solverCellId, set) = a_inBandG(solverCellId, set) || a_inBandG(childId, set);
16196 }
16197
16198 this->removeCellId(childId);
16199 }
16200 for(MInt set = 0; set < m_noSets; set++) {
16201 a_levelSetFunctionG(solverCellId, set) /= noChildren;
16202 if(m_semiLagrange) {
16203 a_oldLevelSetFunctionG(solverCellId, set) /= noChildren;
16204 }
16205 }
16206
16207 if(m_maxLevelChange && globalTimeStep > 0 && !a_isHalo(solverCellId)) {
16208 MInt cellAdded = 0;
16209 for(MInt set = m_startSet; set < m_noSets; set++) {
16210 if(a_inBandG(solverCellId, set)) {
16211 cellAdded++;
16212 if(cellAdded > 1) {
16213 auto it0 = m_refinedCells.find(solverCellId);
16214 ASSERT(it0 != m_refinedCells.end(), "");
16215 m_refinedCells.erase(it0);
16216 m_refinedCells.insert(make_pair(solverCellId, 0));
16217 } else {
16218 m_refinedCells.insert(make_pair(solverCellId, set));
16219 }
16220 }
16221 }
16222 }
16223
16224 if(!g_multiSolverGrid) {
16225 ASSERT((grid().raw().treeb().size() - m_cells.size()) <= grid().m_maxNoChilds, "");
16226 }
16227}
16228
16232template <MInt nDim>
16233void LsCartesianSolver<nDim>::removeCell(const MInt gridCellId) {
16234 // If solver is inactive cell musst never be a internal cell
16235 if(!isActive()) {
16236 ASSERT(grid().raw().a_isHalo(gridCellId), "");
16237 }
16238
16239 const MInt solverCellId = grid().tree().grid2solver(gridCellId);
16240
16241 ASSERT(gridCellId > -1 && gridCellId < grid().raw().treeb().size() && solverCellId > -1
16242 && solverCellId < m_cells.size() && grid().tree().solver2grid(solverCellId) == gridCellId,
16243 "");
16244
16245 this->removeCellId(solverCellId);
16246}
16247
16248// this function should be moved to Solver as soon as cartesiansolver.h has been removed!!!
16249// this function should be moved to Solver as soon as cartesiansolver.h has been removed!!!
16250// this function should be moved to Solver as soon as cartesiansolver.h has been removed!!!
16251template <MInt nDim>
16252void LsCartesianSolver<nDim>::resizeGridMap() {
16253 grid().resizeGridMap(m_cells.size());
16254}
16255
16260template <MInt nDim>
16261void LsCartesianSolver<nDim>::swapCells(const MInt cellId0, const MInt cellId1) {
16262 const MInt size = m_cells.size();
16263 m_cells.append();
16264 m_cells.erase(size);
16265 m_cells.copy(cellId0, size);
16266 m_cells.copy(cellId1, cellId0);
16267 m_cells.copy(size, cellId1);
16268 m_cells.erase(size);
16269 m_cells.size(size);
16270
16271 if(m_LsRotate) {
16272 // cellId1 is moved ahead
16273 if(m_reconstructOldG) {
16274 // Property is already been swapped
16275 if(m_swapIds.find(cellId1) == m_swapIds.end()) m_swapIds[cellId1] = cellId0;
16276 } else {
16277 if(m_initialGCell[cellId1] == 1) m_swapIds[cellId1] = cellId0;
16278 std::swap(m_initialGCell[cellId0], m_initialGCell[cellId1]);
16279 m_initialGCell[cellId1] = 0;
16280 }
16281 }
16282
16283 if(!m_refinedCells.empty()) {
16284 auto it0 = m_refinedCells.find(cellId0);
16285 auto it1 = m_refinedCells.find(cellId1);
16286 if(it0 != m_refinedCells.end() && it1 != m_refinedCells.end()) {
16287 std::swap(it0->second, it1->second);
16288 } else if(it0 != m_refinedCells.end()) {
16289 MInt set = it0->second;
16290 m_refinedCells.erase(it0);
16291 m_refinedCells.insert(make_pair(cellId1, set));
16292 } else if(it1 != m_refinedCells.end()) {
16293 MInt set = it1->second;
16294 m_refinedCells.erase(it1);
16295 m_refinedCells.insert(make_pair(cellId0, set));
16296 }
16297 }
16298
16299
16300 if(!m_oldG0Cells.empty()) {
16301 auto it0 = m_oldG0Cells.find(cellId0);
16302 auto it1 = m_oldG0Cells.find(cellId1);
16303 if(it0 != m_oldG0Cells.end() && it1 != m_oldG0Cells.end()) {
16304 std::swap(it0->second, it1->second);
16305 } else if(it0 != m_oldG0Cells.end()) {
16306 const MInt set = it0->second;
16307 m_oldG0Cells.erase(it0);
16308 m_oldG0Cells.insert(make_pair(cellId1, set));
16309 } else if(it1 != m_oldG0Cells.end()) {
16310 const MInt set = it1->second;
16311 m_oldG0Cells.erase(it1);
16312 m_oldG0Cells.insert(make_pair(cellId0, set));
16313 }
16314 }
16315}
16316
16317
16322template <MInt nDim>
16323void LsCartesianSolver<nDim>::swapProxy(const MInt cellId0, const MInt cellId1) {
16324 grid().swapGridIds(cellId0, cellId1);
16325}
16326
16327
16332template <MInt nDim>
16333void LsCartesianSolver<nDim>::setCellWeights(MFloat* solverCellWeight) {
16334 TRACE();
16335 const MInt noCellsGrid = grid().raw().treeb().size();
16336 const MInt offset = noCellsGrid * solverId();
16337
16338 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
16339 const MInt gridCellId = grid().tree().solver2grid(cellId);
16340 const MInt id = gridCellId + offset;
16341 solverCellWeight[id] = 0.0;
16342 if(a_isHalo(cellId)) continue;
16343 solverCellWeight[id] = m_weightBaseCell * m_weightMulitSolverFactor;
16344 if(c_noChildren(cellId) > 0) continue;
16345 solverCellWeight[id] = m_weightLeafCell * m_weightMulitSolverFactor;
16346 for(MInt set = m_startSet; set < m_noSets; set++) {
16347 if(!m_computeSet[set]) continue;
16348 if(a_inBandG(cellId, set)) {
16349 solverCellWeight[id] = m_weightBandCell * m_weightMulitSolverFactor;
16350 }
16351 }
16352 }
16353}
16354
16355// ---------------------------------------------------------------------------------------------
16356
16362template <MInt nDim>
16363MBool LsCartesianSolver<nDim>::prepareRestart(MBool writeRestart, MBool& writeGridRestart) {
16364 TRACE();
16365
16366 writeGridRestart = false;
16367
16368 if(((globalTimeStep % m_restartInterval) == 0) || writeRestart) {
16369 writeRestart = true;
16370
16371 if(m_adaptationSinceLastRestart) {
16372 writeGridRestart = true;
16373 }
16374
16375 // update updateLowerGridLevels before a restart!
16376 // avoid updateLowerGridLevels
16377 // if(m_levelSetMb && isActive()) {
16378 // updateLowerGridLevels();
16379 //}
16380 }
16381
16382 return writeRestart;
16383}
16384
16390template <MInt nDim>
16391void LsCartesianSolver<nDim>::reIntAfterRestart(MBool doneRestart) {
16392 TRACE();
16393
16394 if(doneRestart) {
16395 m_adaptationSinceLastRestart = false;
16396 }
16397}
16398
16403template <MInt nDim>
16404void LsCartesianSolver<nDim>::writeRestartFile(const MBool writeRestart, const MBool writeBackup,
16405 const MString gridFileName, MInt* recalcIdTree) {
16406 TRACE();
16407
16408 m_currentGridFileName = gridFileName;
16409
16410 if(writeRestart) {
16411 saveRestartFile(writeBackup, &recalcIdTree[0]);
16412 }
16413}
16414
16419template <MInt nDim>
16420void LsCartesianSolver<nDim>::saveRestartFile(const MBool writeBackup, MInt* recalcIds) {
16421 TRACE();
16422
16423 if(domainId() == 0) {
16424 cerr << "Writing levelset restart file for solver " << m_solverId << " at time step " << globalTimeStep << " ...";
16425 }
16426
16427 MBool debugOutput = false;
16428#ifdef LS_DEBUG
16429 debugOutput = true;
16430#endif
16431
16432
16433#if defined LS_DEBUG
16434 for(MInt body = 0; body < m_noEmbeddedBodies; body++) {
16435 const MInt bcId = m_bodyBndryCndIds[body];
16436 stringstream controlfile;
16437 controlfile << "Ctrl_Body_" << body << "_" << globalTimeStep << ".stl";
16438 m_gCtrlPnt.CtrlPnt2_CtrlPntToSTL((controlfile.str()).c_str(), bcId);
16439 }
16440#endif
16441
16442 MInt noCells;
16443 MInt noInternalCellIds;
16444 std::vector<MInt> recalcIdsSolver(0);
16445 std::vector<MInt> reOrderedCells(0);
16446 this->calcRecalcCellIdsSolver(recalcIds, noCells, noInternalCellIds, recalcIdsSolver, reOrderedCells);
16447
16448 MInt noIdVars = 1;
16449 if(m_LsRotate && !m_reconstructOldG) noIdVars += 1;
16450 MInt noDbVars = m_maxNoSets;
16451 if(m_semiLagrange) noDbVars += m_maxNoSets;
16452 if(m_semiLagrange && m_bodyIdOutput) noDbVars += m_maxNoSets;
16453 if(m_LsRotate && !m_reconstructOldG) noDbVars += m_noBodiesToCompute;
16454 if(debugOutput) {
16455 noDbVars = noDbVars + 4;
16456 }
16457 const MInt noIdParams = 0;
16458 MInt noDbParams = m_semiLagrange ? nDim * m_noEmbeddedBodies : 0;
16459 noDbParams = noDbParams + (MInt)m_noGapRegions;
16460 if(m_LsRotate) noDbParams += (2 * nDim * m_noBodiesToCompute);
16461 MIntScratchSpace idVariables(noCells * noIdVars, AT_, "idVariables");
16462 MFloatScratchSpace dbVariables(noCells * noDbVars, AT_, "dbVariables");
16463 MIntScratchSpace idParameters(noIdParams, AT_, "idParameters");
16464 MFloatScratchSpace dbParameters(noDbParams, AT_, "dbParameters");
16465 vector<MString> dbVariablesName;
16466 vector<MString> idVariablesName;
16467 vector<MString> dbParametersName;
16468 vector<MString> idParametersName;
16469 vector<MString> name;
16470
16471 MFloatScratchSpace levelSet(noCells, AT_, "levelSet");
16472 MIntScratchSpace regridL(noCells, AT_, "regridL");
16473 MInt tmpSize = debugOutput ? 1 : 0;
16474 MFloatScratchSpace tmpW(noCells * tmpSize, AT_, "tmpw");
16475 regridL.fill(3);
16476
16477 if(m_levelSetRans) {
16478 updateLowerGridLevels();
16479 }
16480
16481 if(m_maxNoSets == 1) {
16482 name.clear();
16483 name.push_back("G");
16484 if(grid().newMinLevel() < 0) {
16485 for(MInt cell = 0; cell < noCells; cell++) {
16486 levelSet[cell] = a_levelSetFunctionG(cell, 0);
16487 }
16488 } else {
16489 for(MInt cell = 0; cell < noCells; cell++) {
16490 levelSet[cell] = a_levelSetFunctionG(reOrderedCells[cell], 0);
16491 }
16492 }
16493 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16494 } else {
16495 for(MInt set = 0; set < m_noSets; set++) {
16496 string tmps = "G_" + to_string(set);
16497 name.clear();
16498 name.push_back(tmps);
16499 if(grid().newMinLevel() < 0) {
16500 for(MInt cell = 0; cell < noCells; cell++) {
16501 levelSet[cell] = a_levelSetFunctionG(cell, set);
16502 }
16503 } else {
16504 for(MInt cell = 0; cell < noCells; cell++) {
16505 levelSet[cell] = a_levelSetFunctionG(reOrderedCells[cell], set);
16506 }
16507 }
16508 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16509 }
16510 }
16511
16512 if(m_semiLagrange) {
16513 if(m_maxNoSets == 1) {
16514 name.clear();
16515 name.push_back("oldG");
16516 if(grid().newMinLevel() < 0) {
16517 for(MInt cell = 0; cell < noCells; cell++) {
16518 levelSet[cell] = a_oldLevelSetFunctionG(cell, 0);
16519 }
16520 } else {
16521 for(MInt cell = 0; cell < noCells; cell++) {
16522 levelSet[cell] = a_oldLevelSetFunctionG(reOrderedCells[cell], 0);
16523 }
16524 }
16525 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16526 } else {
16527 for(MInt set = 0; set < m_noSets; set++) {
16528 string tmps = "oldG_" + to_string(set);
16529 name.clear();
16530 name.push_back(tmps);
16531 if(grid().newMinLevel() < 0) {
16532 for(MInt cell = 0; cell < noCells; cell++) {
16533 levelSet[cell] = a_oldLevelSetFunctionG(cell, set);
16534 }
16535 } else {
16536 for(MInt cell = 0; cell < noCells; cell++) {
16537 levelSet[cell] = a_oldLevelSetFunctionG(reOrderedCells[cell], set);
16538 }
16539 }
16540 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16541 }
16542 }
16543 if(m_bodyIdOutput) {
16544 for(MInt i = 0; i < m_noSets; i++) {
16545 string tmps = "bodyId_" + to_string(i);
16546 name.clear();
16547 name.push_back(tmps);
16548 if(grid().newMinLevel() < 0) {
16549 for(MInt cell = 0; cell < noCells; cell++) {
16550 levelSet[cell] = a_bodyIdG(cell, i);
16551 }
16552 } else {
16553 for(MInt cell = 0; cell < noCells; cell++) {
16554 levelSet[cell] = a_bodyIdG(reOrderedCells[cell], i);
16555 }
16556 }
16557 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16558 }
16559 }
16560 if(m_LsRotate) {
16561 if(!m_reconstructOldG) {
16562 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16563 MInt body = m_bodiesToCompute[b];
16564
16565 string tmps = "containingCell_" + to_string(body);
16566 name.clear();
16567 name.push_back(tmps);
16568
16569 localToGlobalIdsContainingCells();
16570 for(MInt cell = 0; cell < noCells; cell++) {
16571 levelSet[cell] = a_containingCell(cell, b);
16572 }
16573 globalToLocalIdsContainingCells();
16574
16575 this->collectVariables(levelSet.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16576 }
16577
16578 name.clear();
16579 name.push_back("initialGCell");
16580 for(MInt cell = 0; cell < noCells; cell++) {
16581 regridL[cell] = m_initialGCell[cell];
16582 }
16583 this->collectVariables(regridL.begin(), idVariables, name, idVariablesName, 1, noCells);
16584 }
16585
16586 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
16587 for(MInt j = 0; j < nDim; j++) {
16588 MInt id = i * nDim + j;
16589 string tmps = "SL_xRot_" + to_string(id);
16590 this->collectParameters(m_semiLagrange_xRot_ref[id], dbParameters, tmps.c_str(), dbParametersName);
16591 }
16592 }
16593
16594 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
16595 for(MInt j = 0; j < nDim; j++) {
16596 MInt id = i * nDim + j;
16597 string tmps = "SL_xRot_STL" + to_string(id);
16598 this->collectParameters(m_semiLagrange_xRot_STL[id], dbParameters, tmps.c_str(), dbParametersName);
16599 }
16600 }
16601 }
16602
16603
16604 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
16605 for(MInt j = 0; j < nDim; j++) {
16606 const MInt id = i * nDim + j;
16607 const string tmps = "SL_xShift_" + to_string(id);
16608 this->collectParameters(m_semiLagrange_xShift_ref[id], dbParameters, tmps.c_str(), dbParametersName);
16609 }
16610 }
16611 }
16612
16613
16614 if(m_noGapRegions > 0) {
16615 for(MInt i = 0; i < m_noGapRegions; i++) {
16616 string tmps = "deltaMin_" + to_string(i);
16617 this->collectParameters(m_minGapWidthDt1[i], dbParameters, tmps.c_str(), dbParametersName);
16618 }
16619 }
16620 name.clear();
16621 name.push_back("regrid");
16622 if(grid().newMinLevel() < 0) {
16623 for(MInt cell = 0; cell < noCells; cell++) {
16624 regridL[cell] = a_regridTriggerG(cell);
16625 }
16626 } else {
16627 for(MInt cell = 0; cell < noCells; cell++) {
16628 regridL[cell] = a_regridTriggerG(reOrderedCells[cell]);
16629 }
16630 }
16631 this->collectVariables(regridL.begin(), idVariables, name, idVariablesName, 1, noCells);
16632
16633 if(debugOutput) {
16634 if(grid().newMinLevel() > 0) mTerm(1, AT_, "Not implemented yet!");
16635 name.clear();
16636 name.push_back("Window");
16637 for(MInt i = 0; i < noCells; i++) {
16638 if(a_isWindow(i)) {
16639 tmpW[i] = -1;
16640 } else {
16641 tmpW[i] = domainId();
16642 }
16643 }
16644 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16645
16646 name.clear();
16647 name.push_back("globalId");
16648 for(MInt i = 0; i < noCells; i++) {
16649 tmpW[i] = c_globalId(i);
16650 }
16651 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16652 name.clear();
16653 name.push_back("BandCells");
16654 for(MInt i = 0; i < noCells; i++) {
16655 tmpW[i] = -2;
16656 for(MInt set = 0; set < m_noSets; set++) {
16657 if(a_isGBoundaryCellG(i, set)) tmpW[i] = -1;
16658 if(a_inBandG(i, set)) tmpW[i] = set;
16659 }
16660 }
16661 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16662 name.clear();
16663 name.emplace_back("G0-Cells");
16664 for(MInt i = 0; i < noCells; i++) {
16665 tmpW[i] = -1;
16666 for(MInt set = 0; set < m_noSets; set++) {
16667 for(MInt id = 0; id < a_noG0Cells(set); id++) {
16668 MInt cellId = a_G0CellId(id, set);
16669 tmpW[cellId] = set;
16670 }
16671 }
16672 }
16673 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1, noCells);
16674
16675 /* name.clear();
16676 name.push_back("gapWidth");
16677 for (MInt i = 0; i < noCells; i++){
16678 tmpW[i] = a_gapWidth(i);
16679 }
16680 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1,noCells);
16681 name.clear();
16682 name.push_back("secondBodyId");
16683 for (MInt i = 0; i < noCells; i++){
16684 tmpW[i] = a_secondBodyId( i );
16685 }
16686 this->collectVariables(tmpW.begin(), dbVariables, name, dbVariablesName, 1,noCells);
16687 */
16688 }
16689
16690 stringstream levelSetFileName;
16691 levelSetFileName.clear();
16692 levelSetFileName.str("");
16693 if(m_currentFileName.empty()) {
16694 if(!g_multiSolverGrid) {
16695 levelSetFileName << outputDir() << "restartLSCG";
16696 } else {
16697 levelSetFileName << outputDir() << "restartLSCG_" << m_solverId;
16698 }
16699
16700 if(!m_useNonSpecifiedRestartFile) {
16701 levelSetFileName << "_" << globalTimeStep;
16702 }
16703
16704 levelSetFileName << ParallelIo::fileExt();
16705
16706 } else {
16707 levelSetFileName << outputDir() << m_currentFileName;
16708 if(!m_useNonSpecifiedRestartFile) levelSetFileName << "_" << globalTimeStep;
16709 levelSetFileName << ParallelIo::fileExt();
16710 }
16711
16712 MFloat time = -1;
16713 if(m_LSSolver) time = m_time;
16714
16715 MInt* pointerRecalcIds = (recalcIds == nullptr) ? nullptr : recalcIdsSolver.data();
16716 if(writeBackup) {
16717 stringstream levelSetBackupFileName;
16718 levelSetBackupFileName.clear();
16719 levelSetBackupFileName.str("");
16720 levelSetBackupFileName << outputDir() << "restartLSCGBackup_" << globalTimeStep;
16721 levelSetBackupFileName << ParallelIo::fileExt();
16722 if(domainId() == 0) cerr << "Writing level set (backup) for the ls-solver... ";
16723
16724 this->saveGridFlowVars((levelSetBackupFileName.str()).c_str(), m_currentGridFileName.c_str(), noCells,
16725 noInternalCellIds, dbVariables, dbVariablesName, 0, idVariables, idVariablesName, 0,
16726 dbParameters, dbParametersName, idParameters, idParametersName, pointerRecalcIds, time);
16727 }
16728
16729 this->saveGridFlowVars((levelSetFileName.str()).c_str(), m_currentGridFileName.c_str(), noCells, noInternalCellIds,
16730 dbVariables, dbVariablesName, 0, idVariables, idVariablesName, 0, dbParameters,
16731 dbParametersName, idParameters, idParametersName, pointerRecalcIds, time);
16732
16733 if(domainId() == 0) cerr << "ok" << endl;
16734}
16735
16736// --------------------------------------------------------------------------------------
16737
16738
16739/*
16740 * \brief finalize levelSet solver for rotating levelSet
16741 * \author Thomas Hoesgen
16742 */
16743template <MInt nDim>
16744void LsCartesianSolver<nDim>::finalizeInitSolver() {
16745 TRACE();
16746 if(m_combustion && globalTimeStep < 1) {
16747 initSolver();
16748 }
16749
16750 // Nothing to be done if solver is not active
16751 if(!isActive()) return;
16752
16753 if(m_levelSetMb) {
16754 if(m_constructGField) return;
16755
16756 checkHaloCells();
16757
16758 for(MInt set = 0; set < m_noSets; set++) {
16759 m_computeSet[set] = m_computeSet_tmp[set];
16760 m_changedSet[set] = true;
16761 }
16762
16763 for(MInt set = 0; set < m_noSets; set++) {
16764 ASSERT(m_computeSet[set] == m_computeSet_backup[set], "ERROR in m_computeSet");
16765 }
16766
16767 if(m_trackMovingBndry != 0 && globalTimeStep >= m_trackMbStart && globalTimeStep < m_trackMbEnd) {
16768 // set a_wasGZeroCell to a_isGZeroCell before the timeStep!
16769 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
16770 for(MInt set = 0; set < m_noSets; set++) {
16771 a_wasGZeroCell(cellId, set) = a_isGZeroCell(cellId, set);
16772 }
16773 }
16774
16775 if(!m_semiLagrange) {
16776 setGCellBndryProperty();
16777
16778 computeNormalVectors();
16779
16780 computeCurvature();
16781
16782 determinePropagationSpeed();
16783 }
16784
16785
16786 testCellsCG();
16787
16788 // if buildCollectedLevelSet, this should only be working on the individual-sets!
16789 buildLevelSetTube();
16790 setBandNewArrivals();
16791
16792 if(!m_semiLagrange) {
16793 computeNormalVectors();
16794 computeCurvature();
16795 levelSetReinitialization();
16796 }
16797
16798 // wokring on the collected levelSet!
16799 buildMultipleLevelSet();
16800 }
16801
16802 if(m_LsRotate) {
16803 MInt ind;
16804 for(MInt i = 0; i < m_noEmbeddedBodies; i++) {
16805 for(MInt j = 0; j < nDim; j++) {
16806 ind = i * nDim + j;
16807 m_bodyAngularAcceleration[ind] = F0;
16808 }
16809 rotateLevelSet(5, &m_bodyAngularVelocity[i * nDim], i, nullptr, nullptr, &m_semiLagrange_xRot_STL[i * nDim]);
16810 }
16811 updateContainingGCells(1);
16812 copyWindowToHaloIds();
16813 }
16814 }
16815}
16816
16817/*
16818 * \brief: Initialize lists for rotating levelset
16819 * \author Thomas Hoesgen
16820 */
16821template <MInt nDim>
16822void LsCartesianSolver<nDim>::initRotatingLS() {
16823 TRACE();
16824
16825 if(!m_LsRotate) return;
16826
16827 MFloat maRot;
16828 MInt ind;
16829 for(MInt b = 0; b < m_noEmbeddedBodies; b++) {
16830 for(MInt i = 0; i < nDim; i++) {
16831 ind = b * nDim + i;
16832 maRot = Context::getSolverProperty<MFloat>("MaRot", solverId(), AT_, ind);
16833 m_omega[b * nDim + i] = m_referenceLength / m_bodyRadius[b] * m_referenceVelocity * maRot;
16834 }
16835 }
16836 if(m_restart) {
16837 if(m_reconstructOldG) {
16838 m_rotatingReinitTrigger = 1;
16839 resetContainingGCells();
16840 }
16841 return;
16842 }
16843 if(m_initialRefinement) return;
16844
16845 resetContainingGCells();
16846}
16847
16848/*
16849 * \brief: resets list for rotating levelset
16850 * \author Thomas Hoesgen
16851 */
16852template <MInt nDim>
16853void LsCartesianSolver<nDim>::resetContainingGCells() {
16854 TRACE();
16855
16856 for(MInt cellId = 0; cellId < m_maxNoCells; cellId++) {
16857 if(a_isHalo(cellId)) continue;
16858
16859 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16860 a_containingCell(cellId, b) = cellId;
16861 }
16862 }
16863
16864 if(m_reconstructOldG) return;
16865
16866 for(MInt cellId = 0; cellId < m_maxNoCells; cellId++) {
16867 if(a_isHalo(cellId)) continue;
16868 m_initialGCell[cellId] = 0;
16869 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16870 a_containingCell(cellId, b) = cellId;
16871 a_containingDomain(cellId, b) = domainId();
16872 }
16873 }
16874
16875
16876 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
16877 if(a_isHalo(cellId)) continue;
16878 if(a_level(cellId) == a_maxGCellLevel()) {
16879 m_initialGCell[cellId] = 1;
16880 MInt parentId = cellId;
16881 for(MInt level = a_level(cellId); level > minLevel(); level--) {
16882 parentId = c_parentId(parentId);
16883 m_initialGCell[parentId] = 1;
16884 }
16885 }
16886 }
16887}
16888
16889/*
16890 * \brief: update list for rotating levelset
16891 * \author Thomas Hoesgen
16892 */
16893template <MInt nDim>
16894void LsCartesianSolver<nDim>::updateContainingGCells(MInt mode) {
16895 TRACE();
16896
16897 MInt body;
16898 MInt set;
16899
16900 if(mode == 1) {
16901 for(MInt cellId = 0; cellId < m_maxNoCells; cellId++) {
16902 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16903 body = m_bodiesToCompute[b];
16904 set = m_bodyToSetTable[body];
16905 if(!a_inBandG(cellId, set)) {
16906 a_containingCell(cellId, b) = -1;
16907 if(!m_reconstructOldG) {
16908 a_containingDomain(cellId, b) = -1;
16909 }
16910 }
16911 }
16912 }
16913 } else if(mode == 0) {
16914 if(m_reconstructOldG) {
16915 for(MInt cellId = 0; cellId < m_maxNoCells; cellId++) {
16916 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16917 body = m_bodiesToCompute[b];
16918 set = m_bodyToSetTable[body];
16919 if(a_inBandG(cellId, set)) {
16920 MInt contCell = a_containingCell(cellId, b);
16921 if(contCell > -1) {
16922 for(MInt level = grid().maxUniformRefinementLevel(); level < grid().maxRefinementLevel(); level++) {
16923 if(m_swapIds.find(contCell) != m_swapIds.end()) {
16924 contCell = m_swapIds[contCell];
16925 }
16926 }
16927 a_containingCell(cellId, b) = contCell;
16928 }
16929 } else {
16930 a_containingCell(cellId, b) = -1;
16931 }
16932 }
16933 }
16934 } else {
16935 MInt domId;
16936
16937 // send the size of the data set
16938
16939 MIntScratchSpace noBandCells(grid().noDomains(), AT_, "noBandCells");
16940 noBandCells.fill(0);
16941 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
16942 body = m_bodiesToCompute[b];
16943 set = m_bodyToSetTable[body];
16944 noBandCells[domainId()] += a_noBandCells(set);
16945 }
16946 MPI_Allreduce(MPI_IN_PLACE, &noBandCells[0], grid().noDomains(), MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
16947 "noBandCells[0]");
16948
16949 MInt noCellsComm = m_swapIds.size();
16950 MIntScratchSpace noCellsToDom(grid().noDomains(), AT_, "noCellsToDom");
16951 noCellsToDom.fill(0);
16952
16953 for(MInt i = 0; i < grid().noDomains(); i++) {
16954 if(noBandCells[i] > 0) {
16955 noCellsToDom[i] = noCellsComm;
16956 }
16957 }
16958
16959 prepareGlobalComm(&noCellsToDom[0]);
16960
16961 noCellsComm = mMax(m_globalSndOffsets[grid().noDomains()], m_globalRcvOffsets[grid().noDomains()]);
16962
16963
16964 MIntScratchSpace sndData(2 * noCellsComm, AT_, "sndData");
16965 MIntScratchSpace sndDataSize(grid().noDomains(), AT_, "sndDataSize");
16966 sndData.fill(-1);
16967 sndDataSize.fill(0);
16968 MIntScratchSpace rcvData(2 * noCellsComm, AT_, "rcvData");
16969 MIntScratchSpace rcvDataSize(grid().noDomains(), AT_, "rcvDataSize");
16970 rcvData.fill(-1);
16971 rcvDataSize.fill(0);
16972
16973 std::vector<std::map<MInt, MInt>> swapIdsGlobal;
16974 swapIdsGlobal.resize(grid().noDomains());
16975
16976 // send data
16977 for(std::map<MInt, MInt>::iterator it = m_swapIds.begin(); it != m_swapIds.end(); it++) {
16978 for(MInt d = 0; d < grid().noDomains(); d++) {
16979 if(domainId() == d) continue;
16980 if(noBandCells[d] <= 0) continue;
16981 sndData[2 * m_globalSndOffsets[d] + sndDataSize.p[d]] = it->first;
16982 sndDataSize.p[d]++;
16983 sndData[2 * m_globalSndOffsets[d] + sndDataSize.p[d]] = it->second;
16984 sndDataSize.p[d]++;
16985 }
16986 }
16987
16988 exchangeBuffersGlobal(sndData.getPointer(), rcvData.getPointer(), sndDataSize.getPointer(),
16989 rcvDataSize.getPointer(), &m_globalSndOffsets[0], &m_globalRcvOffsets[0], 9, 2);
16990 for(MInt i = 0; i < grid().noDomains(); i++) {
16991 MInt ind = 2 * m_globalRcvOffsets[i];
16992 for(MInt j = 0; j < rcvDataSize(i); j += 2) {
16993 swapIdsGlobal[i].insert(make_pair(rcvData[ind + j], rcvData[ind + j + 1]));
16994 }
16995 }
16996
16997 for(std::map<MInt, MInt>::iterator it = m_swapIds.begin(); it != m_swapIds.end(); it++) {
16998 swapIdsGlobal[domainId()].insert(make_pair(it->first, it->second));
16999 }
17000
17001 for(MInt cellId = 0; cellId < m_maxNoCells; cellId++) {
17002 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
17003 body = m_bodiesToCompute[b];
17004 set = m_bodyToSetTable[body];
17005 if(a_inBandG(cellId, set)) {
17006 MInt contCell = a_containingCell(cellId, b);
17007 if(contCell > -1) {
17008 domId = a_containingDomain(cellId, b);
17009 if(swapIdsGlobal[domId].find(contCell) != swapIdsGlobal[domId].end()) {
17010 a_containingCell(cellId, b) = swapIdsGlobal[domId][contCell];
17011 }
17012 }
17013 } else {
17014 a_containingCell(cellId, b) = -1;
17015 a_containingDomain(cellId, b) = -1;
17016 }
17017 }
17018 }
17019 }
17020 }
17021
17022 m_swapIds.clear();
17023}
17024
17025/*
17026 * \brief: Updates a list which contains the respective windowCellId of each haloCell
17027 * \author Thomas Hoesgen
17028 */
17029template <MInt nDim>
17030void LsCartesianSolver<nDim>::copyWindowToHaloIds() {
17031 TRACE();
17032
17033 MInt haloId, windowId;
17034
17035 if(m_reconstructOldG) return;
17036
17037 for(MInt i = 0; i < 2 * m_maxNoCells; i++) {
17038 m_cellDomIds[i] = -1;
17039 }
17040
17041 MIntScratchSpace tmp_data(a_noCells() * 3, AT_, "tmp_data");
17042 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
17043 for(MInt j = 0; j < noWindowCells(i); j++) {
17044 windowId = windowCellId(i, j);
17045 tmp_data[windowId * 3] = windowId;
17046 tmp_data[windowId * 3 + 1] = domainId();
17047 tmp_data[windowId * 3 + 2] = m_initialGCell[windowId];
17048 }
17049 }
17050 if(grid().azimuthalPeriodicity()) {
17051 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
17052 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
17053 windowId = grid().azimuthalWindowCell(i, j);
17054 tmp_data[windowId * 3] = windowId;
17055 tmp_data[windowId * 3 + 1] = domainId();
17056 tmp_data[windowId * 3 + 2] = m_initialGCell[windowId];
17057 }
17058 }
17059 }
17060
17061 // exchange data -> send, receive
17062 exchangeDataLS(&tmp_data[0], 3);
17063
17064 // scatter:
17065 // update the halo and window cell lists
17066 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
17067 for(MInt j = 0; j < noHaloCells(i); j++) {
17068 haloId = haloCellId(i, j);
17069 m_cellDomIds[haloId * 2 + 0] = tmp_data[haloId * 3];
17070 m_cellDomIds[haloId * 2 + 1] = tmp_data[haloId * 3 + 1];
17071 m_initialGCell[haloId] = tmp_data[haloId * 3 + 2];
17072 }
17073 }
17074 if(grid().azimuthalPeriodicity()) {
17075 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
17076 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
17077 haloId = grid().azimuthalHaloCell(i, j);
17078 m_cellDomIds[haloId * 2 + 0] = tmp_data[haloId * 3];
17079 m_cellDomIds[haloId * 2 + 1] = tmp_data[haloId * 3 + 1];
17080 m_initialGCell[haloId] = tmp_data[haloId * 3 + 2];
17081 }
17082 }
17083 }
17084}
17085
17086
17091template <MInt nDim>
17092void LsCartesianSolver<nDim>::checkHaloCells() {
17093 TRACE();
17094
17095#if defined LS_DEBUG || !defined NDEBUG
17096
17097 const MFloat eps0 = 1e-8;
17098
17099 MInt noChecks = 3 * m_noSets;
17100 if(m_closeGaps) noChecks += 2;
17101
17102 MFloatScratchSpace cellCheck(a_noCells(), noChecks, AT_, "cellCheck");
17103 cellCheck.fill(std::numeric_limits<MFloat>::max());
17104
17105 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
17106 for(MInt set = 0; set < m_noSets; set++) {
17107 cellCheck(cellId, set * 3) = (MFloat)a_inBandG(cellId, set);
17108 cellCheck(cellId, set * 3 + 1) = a_levelSetFunctionG(cellId, set);
17109 if(!m_combustion) {
17110 cellCheck(cellId, set * 3 + 2) = (MFloat)a_bodyIdG(cellId, set);
17111 }
17112 }
17113 if(m_closeGaps) {
17114 cellCheck(cellId, 3 * m_noSets) = (MFloat)a_secondBodyId(cellId);
17115 cellCheck(cellId, 3 * m_noSets + 1) = (MFloat)a_nearGapG(cellId);
17116 }
17117 }
17118
17119 exchangeData(&cellCheck(0), noChecks);
17120
17121 for(MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
17122 // changes to avoid updateLowerGridLevels each TS
17123 if(!c_isLeafCell(cellId)) continue;
17124
17125 // Since azimuthal periodic halos are not exact cartesian matches, these
17126 // checks are not valid for them
17127 if(grid().azimuthalPeriodicity() && grid().isPeriodic(cellId)) continue;
17128
17129 for(MInt set = 0; set < m_noSets; set++) {
17130 ASSERT((MInt)cellCheck(cellId, set * 3) == a_inBandG(cellId, set), " " + to_string(set));
17131 ASSERT(fabs(cellCheck(cellId, set * 3 + 1) - a_levelSetFunctionG(cellId, set)) < eps0,
17132 to_string(a_levelSetFunctionG(cellId, set)) + " " + to_string(cellCheck(cellId, set * 3 + 1)));
17133 if(!m_combustion) {
17134 ASSERT((MInt)cellCheck(cellId, set * 3 + 2) == a_bodyIdG(cellId, set),
17135 to_string(cellCheck(cellId, set * 3 + 2)) + " " + to_string(a_bodyIdG(cellId, set)));
17136 }
17137 }
17138 if(m_closeGaps) {
17139 // ASSERT((MInt)cellCheck(cellId,3 * m_noSets) == a_secondBodyId( cellId ), to_string(cellCheck(cellId,3 *
17140 // m_noSets)) + " " + to_string(a_secondBodyId( cellId )));
17141 ASSERT((MInt)cellCheck(cellId, 3 * m_noSets + 1) == a_nearGapG(cellId),
17142 to_string(cellCheck(cellId, 3 * m_noSets + 1)) + " " + to_string(a_nearGapG(cellId)));
17143 }
17144 }
17145
17146#endif
17147}
17148
17149
17154template <MInt nDim>
17155MFloat LsCartesianSolver<nDim>::reduceData(const MInt cellId, MFloat* data, const MInt dataBlockSize) {
17156 MFloat vol = cellVolumeAtCell(cellId);
17157 if(c_noChildren(cellId) > 0) {
17158 vol = F0;
17159 for(MInt d = 0; d < dataBlockSize; d++) {
17160 data[dataBlockSize * cellId + d] = F0;
17161 }
17162 for(MInt child = 0; child < IPOW2(nDim); child++) {
17163 MInt childId = c_childId(cellId, child);
17164 if(childId < 0) continue;
17165 if(c_noChildren(childId) == 0) continue;
17166 MFloat volc = reduceData(childId, data, dataBlockSize);
17167 for(MInt d = 0; d < dataBlockSize; d++) {
17168 data[dataBlockSize * cellId + d] += volc * data[dataBlockSize * childId + d];
17169 }
17170 vol += volc;
17171 }
17172 for(MInt d = 0; d < dataBlockSize; d++) {
17173 data[dataBlockSize * cellId + d] /= mMax(1e-14, vol);
17174 }
17175 }
17176 return vol;
17177}
17178
17179// --------------------------------------------------------------------------------------
17180
17181
17186template <MInt nDim>
17187void LsCartesianSolver<nDim>::setInterfaceList(MIntScratchSpace& inList) {
17188 TRACE();
17189
17190 inList.fill(0);
17191
17192 const MInt startSet = m_reconstructBand > 0 ? 0 : m_startSet;
17193 const MInt endSet = m_noSets;
17194
17195
17196 // based on the levelset-values
17197 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
17198 if(inList[cellId] != 0) continue;
17199
17200 for(MInt set = startSet; set < endSet; set++) {
17201 if(m_reconstructBand > 0 && !m_computeSet_backup[set]) {
17202 continue;
17203 }
17204
17205 MBool addParents = false;
17206 if(approx(a_levelSetFunctionG(cellId, set), F0, MFloatEps)) {
17207 // TOBETESTED:
17208 // if(m_adaptationLevel < a_maxGCellLevel(set)) {
17209 if(a_level(cellId) < a_maxGCellLevel(set) && a_level(cellId) < this->m_maxSensorRefinementLevel[0]) {
17210 inList[cellId] = 1;
17211 }
17212 addParents = true;
17213 } else {
17214 for(MInt dir = 0; dir < m_noDirs; dir++) {
17215 if(a_hasNeighbor(cellId, dir) > 0) {
17216 const MInt nghbrId = c_neighborId(cellId, dir);
17217 if((a_levelSetFunctionG(nghbrId, set) * a_levelSetFunctionG(cellId, set) < F0)) {
17218 // if(m_adaptationLevel < a_maxGCellLevel(set)) {
17219 if(a_level(cellId) < a_maxGCellLevel(set) && a_level(cellId) < this->m_maxSensorRefinementLevel[0]) {
17220 inList[cellId] = 1;
17221 }
17222 addParents = true;
17223 break;
17224 }
17225 }
17226 }
17227 }
17228
17229 if(addParents) {
17230 MInt parentId = c_parentId(cellId);
17231 while(parentId > -1 && parentId < a_noCells()) {
17232 if(a_level(parentId) < this->m_maxSensorRefinementLevel[0]) {
17233 inList[parentId] = 1;
17234 }
17235 parentId = c_parentId(parentId);
17236 }
17237 }
17238 }
17239 }
17240
17241 // Exchange the listCount on all Domains
17242#if defined LS_DEBUG || !defined NDEBUG
17243 if(m_reconstructBand > 0) {
17244 ASSERT(m_buildCollectedLevelSetFunction, "");
17245 }
17246
17247 MInt listCount = 0;
17248 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
17249 if(inList[cellId] > 0) {
17250 ++listCount;
17251 }
17252 }
17253 MPI_Allreduce(MPI_IN_PLACE, &listCount, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE", "listCount");
17254
17255 if(listCount == 0 && !m_maxLevelChange && this->m_maxSensorRefinementLevel[0] > minLevel()) {
17256 mTerm(1, AT_, "No Cells found for refinement!");
17257 }
17258#endif
17259
17260 // the levelset-solver has only one layer of haloCells, the exchange is necessary!
17261 exchangeDataLS(&inList[0]);
17262}
17263
17268template <MInt nDim>
17269void LsCartesianSolver<nDim>::resetSolver() {
17270 /* Do something */
17271}
17272
17277template <MInt nDim>
17278void LsCartesianSolver<nDim>::resetSolverFull() {
17279 for(MInt set = 0; set < m_noSets; set++)
17280 std::vector<MInt>().swap(m_bandCells[set]);
17281}
17282
17288template <MInt nDim>
17289MInt LsCartesianSolver<nDim>::cellDataSizeDlb(const MInt dataId, const MInt gridCellId) {
17290 // Inactive ranks do not have any data to communicate
17291 if(!isActive()) {
17292 return 0;
17293 }
17294
17295 // Convert to solver cell id and check
17296 const MInt cellId = grid().tree().grid2solver(gridCellId);
17297 if(cellId < 0 || cellId >= noInternalCells()) {
17298 return 0;
17299 }
17300
17301 MInt dataSize = 0;
17302
17303 switch(dataId) {
17304 case 0: {
17305 dataSize = m_noSets;
17306 break;
17307 }
17308 case 1: {
17309 dataSize = 1;
17310 break;
17311 }
17312 case 2: {
17313 dataSize = (m_semiLagrange) ? m_noSets : 1;
17314 break;
17315 }
17316 case 3: {
17317 if(m_semiLagrange) {
17318 if(!m_reconstructOldG && m_LsRotate) {
17319 dataSize = 1;
17320 } else
17321 TERMM(1, "Unknown data id for !m_reconstructOldG && m_LsRotate.");
17322 } else {
17323 dataSize = nDim;
17324 }
17325 break;
17326 }
17327 case 4: {
17328 if(m_semiLagrange) {
17329 if(!m_reconstructOldG && m_LsRotate) {
17330 dataSize = 1;
17331 } else
17332 TERMM(1, "Unknown data id for !m_reconstructOldG && m_LsRotate.");
17333 } else {
17334 dataSize = nDim;
17335 }
17336 break;
17337 }
17338 default: {
17339 TERMM(1, "Unknown data id.");
17340 break;
17341 }
17342 }
17343 return dataSize;
17344}
17345
17351template <MInt nDim>
17352void LsCartesianSolver<nDim>::getCellDataDlb(const MInt dataId, const MInt oldNoCells,
17353 const MInt* const bufferIdToCellId, MFloat* const data) {
17354 TRACE();
17355
17356 MInt localBufferId = 0;
17357 for(MInt i = 0; i < oldNoCells; i++) {
17358 const MInt gridCellId = bufferIdToCellId[i];
17359
17360 if(gridCellId < 0) continue;
17361
17362 const MInt cellId = grid().tree().grid2solver(gridCellId);
17363 if(cellId < 0 || cellId >= noInternalCells()) {
17364 continue;
17365 }
17366
17367 MInt dataSize = cellDataSizeDlb(dataId, gridCellId);
17368
17369 switch(dataId) {
17370 case 0: {
17371 std::copy_n(&a_levelSetFunctionG(cellId, 0), dataSize, &data[localBufferId * dataSize]);
17372 break;
17373 }
17374 case 2: {
17375 if(m_semiLagrange) {
17376 std::copy_n(&a_oldLevelSetFunctionG(cellId, 0), dataSize, &data[localBufferId * dataSize]);
17377 } else {
17378 std::copy_n(&a_normalVectorG(cellId, 0, 0), dataSize, &data[localBufferId * dataSize]);
17379 }
17380 break;
17381 }
17382 case 3: {
17383 std::copy_n(&a_curvatureG(cellId, 0), dataSize, &data[localBufferId * dataSize]);
17384 break;
17385 }
17386 case 4: {
17387 std::copy_n(&a_levelSetFunctionSlope(cellId, 0, 0), dataSize, &data[localBufferId * dataSize]);
17388 break;
17389 }
17390 default:
17391 TERMM(1, "Unknown data id.");
17392 break;
17393 }
17394 localBufferId++;
17395 }
17396}
17397
17403template <MInt nDim>
17404void LsCartesianSolver<nDim>::getCellDataDlb(const MInt dataId, const MInt oldNoCells,
17405 const MInt* const bufferIdToCellId, MInt* const data) {
17406 TRACE();
17407
17408 MInt localBufferId = 0;
17409 for(MInt i = 0; i < oldNoCells; i++) {
17410 const MInt gridCellId = bufferIdToCellId[i];
17411
17412 if(gridCellId < 0) continue;
17413
17414 const MInt cellId = grid().tree().grid2solver(gridCellId);
17415 if(cellId < 0 || cellId >= noInternalCells()) {
17416 continue;
17417 }
17418
17419 switch(dataId) {
17420 case 1: {
17421 data[localBufferId] = a_regridTriggerG(cellId);
17422 break;
17423 }
17424 case 3: {
17425 std::copy_n(&m_initialGCell[cellId], 1, &data[localBufferId]);
17426 break;
17427 }
17428 case 4: {
17429 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
17430 data[localBufferId * m_noBodiesToCompute + b] = a_containingCell(cellId, b);
17431 }
17432 break;
17433 }
17434 default:
17435 TERMM(1, "Unknown data id.");
17436 break;
17437 }
17438 localBufferId++;
17439 }
17440}
17441
17447template <MInt nDim>
17448void LsCartesianSolver<nDim>::setCellDataDlb(const MInt dataId, const MFloat* const data) {
17449 TRACE();
17450
17451 // Nothing to do if solver is not active
17452 if(!isActive()) {
17453 return;
17454 }
17455
17456 // Set the variables if this is the correct reinitialization stage
17457 if(m_loadBalancingReinitStage == 0) {
17458 switch(dataId) {
17459 case 0: {
17460 std::copy_n(data, noInternalCells() * m_noSets, &a_levelSetFunctionG(0, 0));
17461 break;
17462 }
17463 case 2: {
17464 if(m_semiLagrange) {
17465 std::copy_n(data, noInternalCells() * m_noSets, &a_oldLevelSetFunctionG(0, 0));
17466 } else {
17467 std::copy_n(data, noInternalCells(), &a_curvatureG(0, 0));
17468 }
17469 break;
17470 }
17471 case 3: {
17472 std::copy_n(data, noInternalCells() * nDim, &a_normalVectorG(0, 0, 0));
17473 break;
17474 }
17475 case 4: {
17476 std::copy_n(data, noInternalCells() * nDim, &a_levelSetFunctionSlope(0, 0, 0));
17477 break;
17478 }
17479 default:
17480 TERMM(1, "Unknown data id.");
17481 }
17482 }
17483}
17484
17490template <MInt nDim>
17491void LsCartesianSolver<nDim>::setCellDataDlb(const MInt dataId, const MInt* const data) {
17492 TRACE();
17493
17494 // Nothing to do if solver is not active
17495 if(!isActive()) {
17496 return;
17497 }
17498
17499 // Set the variables if this is the correct reinitialization stage
17500 if(m_loadBalancingReinitStage == 0) {
17501 switch(dataId) {
17502 case 1: {
17503 for(MInt i = 0; i < noInternalCells(); i++) {
17504 a_regridTriggerG(i) = (MBool)data[i];
17505 }
17506 break;
17507 }
17508 case 3: {
17509 std::copy_n(data, noInternalCells(), &m_initialGCell[0]);
17510 break;
17511 }
17512 case 4: {
17513 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
17514 for(MInt i = 0; i < noInternalCells(); i++) {
17515 a_containingCell(i, b) = data[b * noInternalCells() + i];
17516 }
17517 }
17518 break;
17519 }
17520 default:
17521 TERMM(1, "Unknown data id.");
17522 }
17523 }
17524}
17525
17530template <MInt nDim>
17531void LsCartesianSolver<nDim>::balancePre() {
17532 TRACE();
17533
17534 // Set reinitialization stage
17535 m_loadBalancingReinitStage = 0;
17536
17537 // Update the grid proxy for this solver
17538 grid().update();
17539
17540 if(!grid().isActive()) {
17541 // Reset parallelization information if solver is not active
17542 updateDomainInfo(-1, -1, MPI_COMM_NULL, AT_);
17543 } else {
17544 // Set new domain info for solver
17545 updateDomainInfo(grid().domainId(), grid().noDomains(), grid().mpiComm(), AT_);
17546 }
17547
17548 // Reset cell, surface, boundary cell data and deallocate halo/window cell arrays
17549 resetSolverFull();
17550
17551 // Reset all cells
17552 m_cells.clear();
17553
17554 // Return if solver is not active
17555 if(!grid().isActive()) {
17556 return;
17557 }
17558
17559 grid().updateLeafCellExchange();
17560
17561 // check for empry cell collector
17562 ASSERT(m_cells.size() == 0, "");
17563
17564 // Resize cell collector to internal cells
17565 m_cells.append(grid().noInternalCells());
17566
17567 // Check that global ids are sorted
17568 for(MInt cellId = 0; cellId < grid().noInternalCells(); cellId++) {
17569 if(grid().domainOffset(domainId()) + (MLong)cellId != c_globalId(cellId)) {
17570 TERMM(1, "Global id mismatch.");
17571 }
17572 m_cells.erase(cellId);
17573 }
17574}
17575
17576
17581template <MInt nDim>
17582void LsCartesianSolver<nDim>::balancePost() {
17583 TRACE();
17584
17585 m_loadBalancingReinitStage = 1;
17586
17587 // If m_buildCollectedLevelSetFunction = false, identifyBodies() is never called.
17588 // Setting bodyId to -1, however, leads to errors in cut-cell generation.
17589 MInt defaultBodyId = (m_buildCollectedLevelSetFunction ? -1 : 0);
17590 for(MInt i = 0; i < noInternalCells(); i++) {
17591 for(MInt j = 0; j < m_noSets; j++) {
17592 if(m_semiLagrange) {
17593 a_bodyIdG(i, j) = defaultBodyId;
17594 }
17595 }
17596 }
17597
17598 // append the halo-cells and erase
17599 m_cells.append(grid().tree().size() - m_cells.size());
17600 for(MInt cellId = grid().noInternalCells(); cellId < a_noCells(); cellId++) {
17601 m_cells.erase(cellId);
17602 }
17603
17604 testCellsCG();
17605
17606 // Nothing to do if solver is not active
17607 if(!grid().isActive()) {
17608 return;
17609 }
17610
17611 // reallocate exchange-storages:
17612 if(grid().noDomains() > 1) {
17613 if(m_combustion) {
17614 mDeallocate(m_intSendBuffers);
17615 mDeallocate(m_intReceiveBuffers);
17616
17617 mAlloc(m_intSendBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intSendBuffers", 0, AT_);
17618 mAlloc(m_intReceiveBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intReceiveBuffers", 0, AT_);
17619 }
17620
17621 if(!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2) {
17622 mDeallocate(m_gSendBuffers);
17623 mDeallocate(m_gReceiveBuffers);
17624
17625 mAlloc(m_gSendBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gSendBuffers", F0, AT_);
17626 mAlloc(m_gReceiveBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gReceiveBuffers", F0, AT_);
17627 }
17628
17629 if(m_combustion || (!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2)) {
17630 mDeallocate(mpi_request);
17631 mDeallocate(mpi_recive);
17632
17633 mAlloc(mpi_request, grid().noNeighborDomains(), "mpi_request", AT_);
17634 mAlloc(mpi_recive, grid().noNeighborDomains(), "mpi_recive", AT_);
17635 }
17636 }
17637
17638 generateListOfGExchangeCellsCG();
17639 this->checkNoHaloLayers();
17640
17641 // initAzimuthalExchange
17642 initAzimuthalExchange();
17643
17644 exchangeAllLevelSetData();
17645
17646 m_adaptationSinceLastRestart = true;
17647 m_loadBalancingReinitStage = 2;
17648}
17649
17654template <MInt nDim>
17655void LsCartesianSolver<nDim>::balance(const MInt* const noCellsToReceiveByDomain,
17656 const MInt* const noCellsToSendByDomain, const MInt* const sortedCellId,
17657 const MInt oldNoCells) {
17658 TRACE();
17659
17660 NEW_TIMER_GROUP(t_initTimer, "balance solver");
17661 NEW_TIMER(t_timertotal, "balance solver", t_initTimer);
17662 NEW_SUB_TIMER(t_variables, "variables", t_timertotal);
17663 NEW_SUB_TIMER(t_communicator, "communicator", t_timertotal);
17664
17665 RECORD_TIMER_START(t_timertotal);
17666 RECORD_TIMER_START(t_variables);
17667
17668 // save solver-data in grid-format (necessary for multi-solver-balancing!)
17669 // while this might not be the fastes way to ensure a multi-solver balance,
17670 // it is ginuelly simple and clear to understand what is happening!
17671 // This needs to happen before the proxy-update!! (otherwise the solver2grid might change)
17672 MFloatScratchSpace lsValuesBalance(oldNoCells, m_noSets, FUN_, "lsValuesBalance");
17673 MIntScratchSpace regridBalance(oldNoCells, FUN_, "regridBalance");
17674 MFloatScratchSpace curvatureBalance((!m_semiLagrange) * oldNoCells, FUN_, "curvatureBalance");
17675 MFloatScratchSpace normalVectorsBalance((!m_semiLagrange) * oldNoCells, nDim, FUN_, "normalVectorsBalance");
17676 MFloatScratchSpace slopeBalance((!m_semiLagrange) * oldNoCells, nDim, FUN_, "slopeBalance");
17677
17678 MFloatScratchSpace oldLsValuesBalance(m_semiLagrange * oldNoCells, m_semiLagrange * m_noSets, FUN_,
17679 "oldLsValuesBalance");
17680
17681 MLongScratchSpace containingCellsBalance((m_LsRotate && !m_reconstructOldG) * oldNoCells,
17682 (m_LsRotate && !m_reconstructOldG) * m_noBodiesToCompute, FUN_,
17683 "containingCellsBalance");
17684 MLongScratchSpace initialGCellBalance((m_LsRotate && !m_reconstructOldG) * oldNoCells, FUN_, "initialGCellBalance");
17685
17686 regridBalance.fill(-2);
17687 lsValuesBalance.fill(-900);
17688 curvatureBalance.fill(-900);
17689 normalVectorsBalance.fill(-900);
17690 slopeBalance.fill(-900);
17691
17692
17693 oldLsValuesBalance.fill(-900);
17694 containingCellsBalance.fill(-900);
17695 initialGCellBalance.fill(-900);
17696
17697 for(MInt cellId = 0; cellId < grid().tree().size(); cellId++) {
17698 MInt gridCellId = grid().tree().solver2grid(cellId);
17699 for(MInt set = 0; set < m_noSets; set++) {
17700 lsValuesBalance(gridCellId, set) = a_levelSetFunctionG(cellId, set);
17701 }
17702 if(a_regridTriggerG(cellId)) regridBalance(gridCellId) = 1;
17703 }
17704
17705 if(m_semiLagrange) {
17706 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
17707 MInt gridCellId = grid().tree().solver2grid(cellId);
17708 for(MInt set = 0; set < m_noSets; set++) {
17709 oldLsValuesBalance(gridCellId, set) = a_oldLevelSetFunctionG(cellId, set);
17710 }
17711 if(!m_reconstructOldG && m_LsRotate) {
17712 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
17713 containingCellsBalance(gridCellId, b) = a_containingCell(cellId, b);
17714 }
17715 initialGCellBalance(gridCellId) = m_initialGCell[cellId];
17716 }
17717 }
17718
17719 } else {
17720 for(MInt cellId = 0; cellId < grid().tree().size(); cellId++) {
17721 MInt gridCellId = grid().tree().solver2grid(cellId);
17722 for(MInt dim = 0; dim < nDim; dim++) {
17723 normalVectorsBalance(gridCellId, dim) = a_normalVectorG(cellId, dim, 0);
17724 slopeBalance(gridCellId, dim) = a_levelSetFunctionSlope(cellId, dim, 0);
17725 }
17726 curvatureBalance(gridCellId) = a_curvatureG(cellId, 0);
17727 }
17728 }
17729
17730
17731 // update of the proxy
17732 grid().update();
17733
17734 // Just reset parallelization information if solver is not active
17735 // NOTE: inactive ranks not supported here since the data sizes etc are not determined for the
17736 // solver but for the whole grid -> use balancePre/Post instead!
17737 if(!isActive()) {
17738 updateDomainInfo(-1, -1, MPI_COMM_NULL, AT_);
17739 TERMM(1, "fixme: inactive ranks not supported in balance(); implement balancePre/Post!");
17740 return;
17741 }
17742
17743 // Set new domain info for solver
17744 updateDomainInfo(grid().domainId(), grid().noDomains(), grid().mpiComm(), AT_);
17745
17746 // This is only working of the same domains as in the grid are used!
17747 ASSERT(domainId() == grid().raw().domainId(), "");
17748 ASSERT(noDomains() == grid().raw().noDomains(), "");
17749
17750 // data-to be saved during the balancing:
17751 //- a_levelSetFunctionG
17752 //- regridTrigger
17753 // if semiLagrange:
17754 //- a_bodyIdG
17755 //- oldLevelSetFunction
17756
17757 MFloatScratchSpace levelSet(noCellsToReceiveByDomain[noDomains()], m_noSets, FUN_, "levelSet");
17758 MIntScratchSpace regridTrigger(noCellsToReceiveByDomain[noDomains()], FUN_, "regridTrigger");
17759
17760 MFloatScratchSpace curvature((!m_semiLagrange) * noCellsToReceiveByDomain[noDomains()], FUN_, "curvature");
17761 MFloatScratchSpace normalVectors((!m_semiLagrange) * noCellsToReceiveByDomain[noDomains()], nDim, FUN_,
17762 "normalVectors");
17763 MFloatScratchSpace slopes((!m_semiLagrange) * noCellsToReceiveByDomain[noDomains()], nDim, FUN_, "slopes");
17764
17765 MFloatScratchSpace oldLevelSet(m_semiLagrange * noCellsToReceiveByDomain[noDomains()], m_semiLagrange * m_noSets,
17766 FUN_, "oldLevelSet");
17767
17768 MLongScratchSpace containingCells((m_LsRotate && !m_reconstructOldG) * noCellsToReceiveByDomain[noDomains()],
17769 (m_LsRotate && !m_reconstructOldG) * m_noBodiesToCompute, FUN_, "containingCells");
17770 MLongScratchSpace initialGCell((m_LsRotate && !m_reconstructOldG) * noCellsToReceiveByDomain[noDomains()], FUN_,
17771 "initialCell");
17772
17773 levelSet.fill(-1.0);
17774 regridTrigger.fill(-2);
17775 slopes.fill(-1.0);
17776 curvature.fill(-1.0);
17777 normalVectors.fill(-1.0);
17778
17779
17780 oldLevelSet.fill(-1.0);
17781 containingCells.fill(-1);
17782 initialGCell.fill(-1);
17783
17784 maia::mpi::communicateData(&lsValuesBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17785 noCellsToSendByDomain, noCellsToReceiveByDomain, m_noSets, &levelSet[0]);
17786
17787 maia::mpi::communicateData(&regridBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17788 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &regridTrigger[0]);
17789
17790 if(m_semiLagrange) {
17791 maia::mpi::communicateData(&oldLsValuesBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17792 noCellsToSendByDomain, noCellsToReceiveByDomain, m_noSets, &oldLevelSet[0]);
17793
17794 if(!m_reconstructOldG && m_LsRotate) {
17795 maia::mpi::communicateData(&containingCellsBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(),
17796 mpiComm(), noCellsToSendByDomain, noCellsToReceiveByDomain, m_noBodiesToCompute,
17797 &containingCells[0]);
17798 maia::mpi::communicateData(&initialGCellBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17799 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &initialGCell[0]);
17800 }
17801
17802 } else {
17803 maia::mpi::communicateData(&normalVectorsBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17804 noCellsToSendByDomain, noCellsToReceiveByDomain, nDim, &normalVectors[0]);
17805 maia::mpi::communicateData(&slopeBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17806 noCellsToSendByDomain, noCellsToReceiveByDomain, nDim, &slopes[0]);
17807 maia::mpi::communicateData(&curvatureBalance[0], oldNoCells, sortedCellId, noDomains(), domainId(), mpiComm(),
17808 noCellsToSendByDomain, noCellsToReceiveByDomain, 1, &curvature[0]);
17809 }
17810
17811 // reset all data!
17812 resetSolverFull();
17813
17814 // Reset all cells
17815 m_cells.clear();
17816
17817 // Iterate over all received grid cells
17818 for(MInt gridCellId = 0; gridCellId < noCellsToReceiveByDomain[noDomains()]; gridCellId++) {
17819 // Determine cell id and append to collector
17820 const MInt cellId = m_cells.size();
17821
17822 if(!grid().raw().treeb().solver(gridCellId, m_solverId)) continue;
17823
17824 ASSERT(grid().tree().solver2grid(cellId) == gridCellId, "");
17825
17826 if(grid().domainOffset(domainId()) + (MLong)cellId != c_globalId(cellId)) {
17827 mTerm(1, AT_, "Global id mismatch.");
17828 }
17829 m_cells.append();
17830 m_cells.erase(cellId);
17831
17832 // Set solver data
17833 for(MInt j = 0; j < m_noSets; j++) {
17834 a_levelSetFunctionG(cellId, j) = levelSet(gridCellId, j);
17835
17836 if(m_semiLagrange) {
17837 a_bodyIdG(cellId, j) = -1;
17838 a_oldLevelSetFunctionG(cellId, j) = oldLevelSet(gridCellId, j);
17839 }
17840 }
17841
17842 if(!m_reconstructOldG && m_LsRotate) {
17843 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
17844 a_containingCell(cellId, b) = containingCells(gridCellId, b);
17845 }
17846 m_initialGCell[cellId] = initialGCell[gridCellId];
17847 }
17848
17849 if(!m_semiLagrange) {
17850 for(MInt dim = 0; dim < nDim; dim++) {
17851 a_normalVectorG(cellId, dim, 0) = normalVectors(gridCellId, dim);
17852 a_levelSetFunctionSlope(cellId, dim, 0) = slopes(gridCellId, dim);
17853 }
17854 a_curvatureG(cellId, 0) = curvature(gridCellId);
17855 }
17856
17857 if(regridTrigger[gridCellId] > 0) {
17858 a_regridTriggerG(cellId) = true;
17859 }
17860 }
17861
17862 // append the halo-cells:
17863 m_cells.append(grid().tree().size() - m_cells.size());
17864 for(MInt cellId = noInternalCells(); cellId < a_noCells(); cellId++) {
17865 m_cells.erase(cellId);
17866 }
17867
17868 testCellsCG();
17869
17870 RECORD_TIMER_STOP(t_variables);
17871 RECORD_TIMER_START(t_communicator);
17872
17873 // reallocate exchange-storages:
17874 if(grid().noDomains() > 1) {
17875 if(m_combustion) {
17876 mDeallocate(m_intSendBuffers);
17877 mDeallocate(m_intReceiveBuffers);
17878
17879 mAlloc(m_intSendBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intSendBuffers", 0, AT_);
17880 mAlloc(m_intReceiveBuffers, grid().noNeighborDomains(), m_maxNoCells, "m_intReceiveBuffers", 0, AT_);
17881 }
17882
17883 if(!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2) {
17884 mDeallocate(m_gSendBuffers);
17885 mDeallocate(m_gReceiveBuffers);
17886
17887 mAlloc(m_gSendBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gSendBuffers", F0, AT_);
17888 mAlloc(m_gReceiveBuffers, grid().noNeighborDomains(), m_maxNoSets * m_maxNoCells, "m_gReceiveBuffers", F0, AT_);
17889 }
17890
17891 if(m_combustion || (!m_semiLagrange || m_guaranteeReinit || m_STLReinitMode != 2)) {
17892 mDeallocate(mpi_request);
17893 mDeallocate(mpi_recive);
17894
17895 mAlloc(mpi_request, grid().noNeighborDomains(), "mpi_request", AT_);
17896 mAlloc(mpi_recive, grid().noNeighborDomains(), "mpi_recive", AT_);
17897 }
17898 }
17899
17900 generateListOfGExchangeCellsCG();
17901
17902 this->checkNoHaloLayers();
17903
17904 startLoadTimer(AT_);
17905
17906 // Initialize the azimuthal periodic exchange
17907 initAzimuthalExchange();
17908
17909 exchangeAllLevelSetData();
17910
17911 m_adaptationSinceLastRestart = true;
17912
17913 RECORD_TIMER_STOP(t_communicator);
17914 RECORD_TIMER_STOP(t_timertotal);
17915 DISPLAY_TIMER(t_timertotal);
17916}
17917
17922template <MInt nDim>
17923void LsCartesianSolver<nDim>::finalizeBalance() {
17924 if(!grid().isActive()) {
17925 return;
17926 }
17927
17928 reInitSolver(false);
17929
17930 // Update local ids of window cell on halo rank or reconstructOldG
17931 if(m_LsRotate) {
17932 if(m_reconstructOldG) {
17933 reconstructOldGField();
17934 } else {
17935 globalToLocalIdsContainingCells();
17936 copyWindowToHaloIds();
17937 }
17938 }
17939}
17940
17941
17946template <MInt nDim>
17947void LsCartesianSolver<nDim>::rotateLevelSet(MInt returnMode, MFloat* cellData, MInt body, const MFloat* xCoord,
17948 const MFloat* xCenter, const MFloat* angle) {
17949 TRACE();
17950
17951 IF_CONSTEXPR(nDim == 2) mTerm(1, AT_, "rotateLevelSet needs to be updated to 2D!");
17952
17953 switch(returnMode) {
17954 case 1: // current coordinate
17955 cellData[0] = xCenter[0] + (cos(angle[1]) * cos(angle[0])) * (xCoord[0] - xCenter[0])
17956 + (cos(angle[1]) * sin(angle[0])) * (xCoord[1] - xCenter[1])
17957 + (-sin(angle[1])) * (xCoord[2] - xCenter[2]);
17958
17959 cellData[1] =
17960 xCenter[1]
17961 + (sin(angle[2]) * sin(angle[1]) * cos(angle[0]) - cos(angle[2]) * sin(angle[0])) * (xCoord[0] - xCenter[0])
17962 + (sin(angle[2]) * sin(angle[1]) * sin(angle[0]) + cos(angle[2]) * cos(angle[0])) * (xCoord[1] - xCenter[1])
17963 + (sin(angle[2]) * cos(angle[1])) * (xCoord[2] - xCenter[2]);
17964
17965 cellData[2] =
17966 xCenter[2]
17967 + (cos(angle[2]) * sin(angle[1]) * cos(angle[0]) + sin(angle[2]) * sin(angle[0])) * (xCoord[0] - xCenter[0])
17968 + (cos(angle[2]) * sin(angle[1]) * sin(angle[0]) - sin(angle[2]) * cos(angle[0])) * (xCoord[1] - xCenter[1])
17969 + (cos(angle[2]) * cos(angle[1])) * (xCoord[2] - xCenter[2]);
17970
17971 break;
17972
17973 case 2: // current velocity
17974
17975 cellData[0] =
17976 ((m_omega[body * nDim + 1] * cos(angle[0]) + m_omega[body * nDim + 2] * sin(angle[0]) * cos(angle[1]))
17977 * (xCoord[2] - xCenter[2])
17978 - (m_omega[body * nDim + 0] - m_omega[body * nDim + 2] * sin(angle[1])) * (xCoord[1] - xCenter[1]));
17979 cellData[1] =
17980 ((m_omega[body * nDim + 0] - m_omega[body * nDim + 2] * sin(angle[1])) * (xCoord[0] - xCenter[0])
17981 - (-m_omega[body * nDim + 1] * sin(angle[0]) + m_omega[body * nDim + 2] * cos(angle[0]) * cos(angle[1]))
17982 * (xCoord[2] - xCenter[2]));
17983 cellData[2] =
17984 ((-m_omega[body * nDim + 1] * sin(angle[0]) + m_omega[body * nDim + 2] * cos(angle[0]) * cos(angle[1]))
17985 * (xCoord[1] - xCenter[1])
17986 - (m_omega[body * nDim + 1] * cos(angle[0]) + m_omega[body * nDim + 2] * sin(angle[0]) * cos(angle[1]))
17987 * (xCoord[0] - xCenter[0]));
17988
17989 break;
17990
17991 case 3: // current acceleration
17992
17993 MFloat omeg[3], omegRad[3];
17994
17995 rotateLevelSet(5, omeg, body, nullptr, nullptr, &m_semiLagrange_xRot_STL[body * nDim]);
17996 rotateLevelSet(2, omegRad, body, xCoord, xCenter, &m_semiLagrange_xRot_STL[body * nDim]);
17997
17998 cellData[0] = omeg[1] * omegRad[2] - omeg[2] * omegRad[1];
17999 cellData[1] = omeg[2] * omegRad[0] - omeg[0] * omegRad[2];
18000 cellData[2] = omeg[0] * omegRad[1] - omeg[1] * omegRad[0];
18001
18002 break;
18003
18004 case 4: // current angle
18005
18006 cellData[0] = angle[0];
18007 cellData[1] = angle[1];
18008 cellData[2] = angle[2];
18009
18010 break;
18011
18012 case 5: // current angular velocity
18013
18014 cellData[0] =
18015 (-m_omega[body * nDim + 1] * sin(angle[0]) + m_omega[body * nDim + 2] * cos(angle[0]) * cos(angle[1]));
18016 cellData[1] =
18017 (m_omega[body * nDim + 1] * cos(angle[0]) + m_omega[body * nDim + 2] * sin(angle[0]) * cos(angle[1]));
18018 cellData[2] = (m_omega[body * nDim + 0] - m_omega[body * nDim + 2] * sin(angle[1]));
18019
18020 break;
18021
18022 case 6: // current angular acceleration
18023
18024 cellData[0] = F0;
18025 cellData[1] = F0;
18026 cellData[2] = F0;
18027
18028 break;
18029
18030 default:
18031 cellData[0] = F0;
18032 cellData[1] = F0;
18033 cellData[2] = F0;
18034 }
18035}
18036
18043template <MInt nDim>
18044MInt LsCartesianSolver<nDim>::getContainingCellHalo(MFloat* point) {
18045 TRACE();
18046
18047 MInt cellId = -1;
18048
18049 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
18050 for(MInt j = 0; j < noHaloCells(i); j++) {
18051 cellId = haloCellId(i, j);
18052 if(a_level(cellId) != a_maxGCellLevel() || (!m_reconstructOldG && m_initialGCell[cellId] == 0)) continue;
18053
18054 if(inCell(cellId, point)) {
18055 cerr << "Halo " << cellId << " " << c_coordinate(cellId, 0) << " " << c_coordinate(cellId, 1) << " "
18056 << c_coordinate(cellId, 2) << endl;
18057
18058 return cellId;
18059 }
18060 }
18061 }
18062
18063 return -1;
18064}
18065
18066
18073template <MInt nDim>
18074void LsCartesianSolver<nDim>::processRotatingLevelSet(MFloat& phi, MInt& cellId, MInt& domId, MFloat* point, MInt set) {
18075 TRACE();
18076
18077 if(a_level(cellId) != a_maxGCellLevel() || (!m_reconstructOldG && m_initialGCell[cellId] == 0)) {
18078 mTerm(1, AT_, "ContainingCell is not initialGCell or on maxLevel!");
18079 } else {
18080 const MInt magic_number = 8; // pow(2, nDim);
18081 std::array<MInt, magic_number> interpolationCells = {0, 0, 0, 0, 0, 0, 0, 0};
18082 MInt position = 0;
18083 // Set up interpolation stencil
18084 position = setUpLevelSetInterpolationStencil(cellId, interpolationCells.data(), point);
18085 // Check if all interpolationCells are initialGCells
18086 if(position > -1) {
18087 for(MInt i = 0; i < 8; i++) {
18088 if(a_level(interpolationCells[i]) != a_maxGCellLevel()
18089 || (!m_reconstructOldG && m_initialGCell[interpolationCells[i]] == 0)) {
18090 mTerm(1, AT_, "interpolationCell is not initialGCell!");
18091 position = -1;
18092 break;
18093 }
18094 }
18095 }
18096 // Interpolate level set
18097 if(position > -1) {
18098 phi = interpolateOldLevelSet(interpolationCells.data(), point, set);
18099 } else {
18100 phi = a_oldLevelSetFunctionG(cellId, set);
18101 }
18102
18103 if(a_isHalo(cellId)) {
18104 if(!m_reconstructOldG) {
18105 domId = m_cellDomIds[cellId * 2 + 1];
18106 cellId = m_cellDomIds[cellId * 2 + 0];
18107 }
18108 }
18109 }
18110}
18111
18118template <MInt nDim>
18119MInt LsCartesianSolver<nDim>::cellOutside(const MFloat* coords, const MInt level, const MInt gridCellId) {
18120 // TODO labels:LS,toremove remove and update fv-combustion testcases accordingly!
18121 if(m_combustion) return -1;
18122
18123 if(m_engineSetup) {
18124 return -1;
18125 }
18126
18127 if(m_virtualSurgery) {
18128 return -1;
18129 }
18130
18131 std::ignore = gridCellId;
18132
18133 static constexpr MInt cornerIndices[8][3] = {{-1, -1, -1}, {1, -1, -1}, {-1, 1, -1}, {1, 1, -1},
18134 {-1, -1, 1}, {1, -1, 1}, {-1, 1, 1}, {1, 1, 1}};
18135 MFloat corner[3] = {0, 0, 0};
18136 MBool outside = true;
18137 MFloat cellHalfLength = F1B2 * c_cellLengthAtLevel(level);
18138
18139 for(MInt i = 0; i < m_noCorners; i++) {
18140 for(MInt dim = 0; dim < nDim; dim++) {
18141 corner[dim] = coords[dim] + cornerIndices[i][dim] * cellHalfLength;
18142 }
18143 IF_CONSTEXPR(nDim == 2) {
18144 if(!m_geometry->pointIsInside(corner)) outside = false;
18145 // pointIsInside == true if Point is outside fluid domain
18146 }
18147 else {
18148 if(!m_geometry->pointIsInside2(corner)) outside = false;
18149 // pointIsInside == true if Point is outside fluid domain
18150 }
18151 }
18152
18153 // Why? pointIsInside checks for the outer geometry
18154 // if(m_levelSetSign[0] < 0) {
18155 // outside = !outside;
18156 //}
18157
18158 return outside;
18159}
18160
18169template <MInt nDim>
18170MInt LsCartesianSolver<nDim>::noLoadTypes() const {
18171 TRACE();
18172 // band-Cells and G0-Cells
18173 const MInt noLsLoadTypes = m_weightLevelSet ? 3 : 1;
18174 return noLsLoadTypes;
18175}
18176
18177
18179template <MInt nDim>
18180void LsCartesianSolver<nDim>::getDefaultWeights(MFloat* weights, std::vector<MString>& names) const {
18181 TRACE();
18182
18183 // TODO labels:LS set sensible default values
18184 weights[0] = 0.1;
18185 names[0] = "ls_cell";
18186 MInt count = 1;
18187
18188 if(m_weightLevelSet) {
18189 weights[1] = 0.1;
18190 names[1] = "ls_band_cell";
18191 count++;
18192
18193 weights[2] = 0.5;
18194 names[2] = "ls_g0_cell";
18195 count++;
18196 }
18197
18198 if(noLoadTypes() != count) {
18199 TERMM(1, "Count does not match noLoadTypes.");
18200 }
18201}
18202
18203
18211template <MInt nDim>
18212void LsCartesianSolver<nDim>::getLoadQuantities(MInt* const loadQuantities) const {
18213 TRACE();
18214
18215 // Nothing to do if solver is not active
18216 if(!isActive()) {
18217 return;
18218 }
18219
18220 // reset
18221 for(MInt type = 0; type < noLoadTypes(); type++) {
18222 loadQuantities[type] = 0;
18223 }
18224
18225
18226 loadQuantities[0] = noInternalCells();
18227
18228 MInt noBandCells = 0;
18229 MInt noG0Cells = 0;
18230 if(m_weightLevelSet) {
18231 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18232 MBool inAnyBand = false;
18233 for(MInt set = (MInt)m_buildCollectedLevelSetFunction; set < m_noSets; set++) {
18234 if(a_inBandG(cellId, set) && !inAnyBand) {
18235 noBandCells++;
18236 inAnyBand = true;
18237 }
18238 if(a_isGZeroCell(cellId, set)) {
18239 noG0Cells++;
18240 break;
18241 }
18242 }
18243 }
18244 }
18245
18246 loadQuantities[1] = noBandCells;
18247 loadQuantities[2] = noG0Cells;
18248}
18249
18250
18260template <MInt nDim>
18261MFloat LsCartesianSolver<nDim>::getCellLoad(const MInt gridCellId, const MFloat* const weights) const {
18262 TRACE();
18263 ASSERT(isActive(), "solver is not active");
18264
18265 // Convert to solver cell id and check
18266 const MInt cellId = grid().tree().grid2solver(gridCellId);
18267 if(cellId < 0) {
18268 return 0;
18269 }
18270
18271 if(cellId < 0 || cellId >= grid().noInternalCells()) {
18272 TERMM(1, "The given cell id is invalid.");
18273 }
18274
18275 // Default cell load
18276 MFloat cellLoad = weights[0];
18277
18278 if(m_weightLevelSet) {
18279 for(MInt set = (MInt)m_buildCollectedLevelSetFunction; set < m_noSets; set++) {
18280 if(a_inBandG(cellId, set)) {
18281 cellLoad = weights[1];
18282 if(a_isGZeroCell(cellId, set)) {
18283 cellLoad = weights[2];
18284 return cellLoad;
18285 }
18286 }
18287 }
18288 }
18289 return cellLoad;
18290}
18291
18296template <MInt nDim>
18297void LsCartesianSolver<nDim>::limitWeights(MFloat* weights) {
18298 if(m_limitWeights) {
18299 weights[0] = mMax(weights[0], 0.01 * mMax(weights[1], weights[2]));
18300 }
18301}
18302
18307template <MInt nDim>
18308void LsCartesianSolver<nDim>::getSolverTimings(std::vector<std::pair<MString, MFloat>>& solverTimings,
18309 const MBool NotUsed(allTimings)) {
18310 TRACE();
18311
18312 const MString namePrefix = "b" + std::to_string(solverId()) + "_";
18313
18314 const MFloat load = returnLoadRecord();
18315 const MFloat idle = returnIdleRecord();
18316
18317 solverTimings.emplace_back(namePrefix + "loadLsCartesianSolver", load);
18318 solverTimings.emplace_back(namePrefix + "idleLsCartesianSolver", idle);
18319
18320#ifdef MAIA_TIMER_FUNCTION
18321 solverTimings.emplace_back(namePrefix + "timeIntegration", RETURN_TIMER_TIME(m_timers[Timers::TimeInt]));
18322 solverTimings.emplace_back(namePrefix + "firstEx", RETURN_TIMER_TIME(m_timers[Timers::FirstEx]));
18323 solverTimings.emplace_back(namePrefix + "postTS", RETURN_TIMER_TIME(m_timers[Timers::PostTime]));
18324 solverTimings.emplace_back(namePrefix + "finalize", RETURN_TIMER_TIME(m_timers[Timers::Finalize]));
18325 solverTimings.emplace_back(namePrefix + "buildTube", RETURN_TIMER_TIME(m_timers[Timers::BuildTube]));
18326 solverTimings.emplace_back(namePrefix + "setBand", RETURN_TIMER_TIME(m_timers[Timers::SetBand]));
18327 solverTimings.emplace_back(namePrefix + "multiple", RETURN_TIMER_TIME(m_timers[Timers::BuildMultiple]));
18328#endif
18329}
18330
18331
18336template <MInt nDim>
18337void LsCartesianSolver<nDim>::getDomainDecompositionInformation(std::vector<std::pair<MString, MInt>>& domainInfo) {
18338 TRACE();
18339
18340 MInt noBandCells = 0;
18341 MInt noG0Cells = 0;
18342 MInt noCells = noInternalCells();
18343 if(m_weightLevelSet) {
18344 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18345 MBool inAnyBand = false;
18346 for(MInt set = (MInt)m_buildCollectedLevelSetFunction; set < m_noSets; set++) {
18347 if(a_inBandG(cellId, set) && !inAnyBand) {
18348 noBandCells++;
18349 inAnyBand = true;
18350 }
18351 if(a_isGZeroCell(cellId, set)) {
18352 noG0Cells++;
18353 break;
18354 }
18355 }
18356 }
18357 }
18358
18359 const MString namePrefix = "b" + std::to_string(solverId()) + "_";
18360 domainInfo.emplace_back(namePrefix + "noLsCells", noCells);
18361 domainInfo.emplace_back(namePrefix + "noLsBandCells", noBandCells);
18362 domainInfo.emplace_back(namePrefix + "noLsG0Cells", noG0Cells);
18363}
18364
18371template <MInt nDim>
18372MInt LsCartesianSolver<nDim>::checkSecondLayerCells(std::vector<MInt>& diag2Cells,
18373 std::map<MInt, std::vector<MInt>>& dirCode, MFloat* point) {
18374 TRACE();
18375
18376 MInt nghbrId = -1;
18377
18378 std::vector<MInt> secondLayer;
18379 MInt d[3];
18380 MInt nghbrId2, nghbrId3;
18381 MInt d1, d2, d3, e, w; //,g;
18382 MInt dir[3] = {0, 2, 4};
18383 MInt oDir[6] = {2, 4, 0, 4, 0, 2};
18384
18385 for(MInt& diag2Cell : diag2Cells) {
18386 d[0] = dirCode[diag2Cell][0];
18387 d[1] = dirCode[diag2Cell][1];
18388 d[2] = dirCode[diag2Cell][2];
18389
18390 // add neighbors
18391 for(MInt nghbr = 0; nghbr < 2 * nDim; nghbr++) {
18392 if(nghbr == d[nghbr / 2]) continue;
18393 nghbrId = c_neighborId(diag2Cell, nghbr);
18394 if(nghbrId == -1) continue;
18395
18396 secondLayer.push_back(nghbrId);
18397 }
18398
18399 // add diagonal neighbors
18400 for(MInt i = 0; i < nDim; i++) {
18401 for(MInt j = 0; j < 2; j++) {
18402 d1 = dir[i] + j;
18403 nghbrId = c_neighborId(diag2Cell, d1);
18404 if(nghbrId == -1) continue;
18405 e = d1 / 2;
18406 for(MInt k = 0; k < 2; k++) {
18407 for(MInt m = 0; m < 2; m++) {
18408 d2 = oDir[2 * e + k] + m;
18409 nghbrId2 = c_neighborId(nghbrId, d2);
18410 if(nghbrId2 == -1) continue;
18411 w = d2 / 2;
18412 // if ( !(d1 == d[i]) && !(d2 == d[w]) )
18413 secondLayer.push_back(nghbrId2);
18414
18415 for(MInt n = 0; n < 2; n++) {
18416 d3 = dir[nDim - e - w] + n;
18417 if(a_hasNeighbor(nghbrId2, d3)) {
18418 nghbrId3 = c_neighborId(nghbrId2, d3);
18419
18420 // g = d3 / 2;
18421 // if ( !(d1 == d[i]) && !(d2 == d[w]) && !(d3 == d[g] ) )
18422 secondLayer.push_back(nghbrId3);
18423 }
18424 }
18425 }
18426 }
18427 }
18428 }
18429 }
18430
18431 std::sort(secondLayer.begin(), secondLayer.end());
18432 auto last = std::unique(secondLayer.begin(), secondLayer.end());
18433 secondLayer.erase(last, secondLayer.end());
18434 for(MInt& it : secondLayer) {
18435 if(inCell(it, point)) return it;
18436 }
18437
18438 return -1;
18439}
18440
18441
18447template <MInt nDim>
18448void LsCartesianSolver<nDim>::prepareGlobalComm(MInt* noCellsToDom) {
18449 TRACE();
18450
18451 ScratchSpace<MPI_Request> requestGlobal(grid().noDomains(), AT_, "requestGlobal");
18452 MPI_Status status;
18453 MInt tag = 3;
18454
18455 requestGlobal.fill(MPI_REQUEST_NULL);
18456
18457 m_globalSndOffsets[0] = 0;
18458 for(MInt i = 0; i < grid().noDomains(); i++) {
18459 if(domainId() == i) {
18460 m_globalSndOffsets[i + 1] = m_globalSndOffsets[i];
18461 } else {
18462 m_globalSndOffsets[i + 1] = m_globalSndOffsets[i] + noCellsToDom[i];
18463 }
18464 }
18465
18466
18467 MIntScratchSpace noCellsToSend(grid().noDomains(), AT_, "sendData");
18468 MIntScratchSpace noCellsToReceive(grid().noDomains(), AT_, "receiveData");
18469 noCellsToSend.fill(0);
18470 noCellsToReceive.fill(0);
18471
18472 m_globalRcvOffsets[0] = 0;
18473 // send the size of the data set
18474 for(MInt i = 0; i < grid().noDomains(); i++) {
18475 if(domainId() == i) continue;
18476 noCellsToSend.p[i] = noCellsToDom[i];
18477 MPI_Issend(&noCellsToSend.p[i], 1, MPI_INT, i, tag, mpiComm(), &requestGlobal[i], AT_, "noCellsToSend.p[i]");
18478 }
18479
18480 // receive the size of the data set
18481 for(MInt i = 0; i < grid().noDomains(); i++) {
18482 if(domainId() == i) {
18483 m_globalRcvOffsets[i + 1] = m_globalRcvOffsets[i];
18484 } else {
18485 MPI_Recv(&noCellsToReceive.p[i], 1, MPI_INT, i, tag, mpiComm(), &status, AT_, "noCellsToReceive.p[i]");
18486 m_globalRcvOffsets[i + 1] = m_globalRcvOffsets[i] + noCellsToReceive.p[i];
18487 }
18488 }
18489 for(MInt i = 0; i < grid().noDomains(); i++) {
18490 if(domainId() == i) continue;
18491 MPI_Wait(&requestGlobal[i], &status, AT_);
18492 }
18493}
18494
18502template <MInt nDim>
18503void LsCartesianSolver<nDim>::sensorInterface(std::vector<std::vector<MFloat>>& sensors,
18504 std::vector<std::bitset<64>>& sensorCellFlag,
18505 std::vector<MFloat>& sensorWeight, MInt sensorOffset, MInt sen) {
18506 m_log << " - Sensor preparation for the interface sensor" << endl;
18507
18508 MIntScratchSpace inList(a_noCells(), AT_, "inList");
18509 setInterfaceList(inList);
18510
18511 for(MInt level = minLevel(); level < this->m_maxSensorRefinementLevel[sen]; level++) {
18512 this->markSurrndCells(inList, m_outerBandWidth[level], level, m_refineDiagonals);
18513 }
18514
18515 ASSERT(a_noCells() == grid().tree().size(), "");
18516
18517 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18518 if(inList(cellId) == 0) {
18519 // if(a_oldLevelSetFunctionG(cellId , 0) > - m_outsideGValue &&
18520 // a_oldLevelSetFunctionG(cellId , 0) < m_outsideGValue ) continue;
18521 // keep the are of the old-levelSet-function refined!
18522 if(a_level(cellId) == minLevel()) continue;
18523 if(inList(c_parentId(cellId))) continue;
18524 if(c_noChildren(cellId) == 0) {
18525 const MInt gridCellId = grid().tree().solver2grid(cellId);
18526 sensors[sensorOffset + sen][gridCellId] = -1.0;
18527 sensorCellFlag[gridCellId][sensorOffset + sen] = true;
18528 }
18529 if(!m_reconstructOldG && m_LsRotate && globalTimeStep > 0) {
18530 if(m_initialGCell[cellId] == 1) {
18531 const MInt gridCellId = grid().tree().solver2grid(cellId);
18532 sensors[sensorOffset + sen][gridCellId] = 1.0;
18533 sensorCellFlag[gridCellId][sensorOffset + sen] = true;
18534 }
18535 }
18536 } else {
18537 ASSERT(inList(cellId) > 0, "");
18538 const MInt gridCellId = grid().tree().solver2grid(cellId);
18539 if(a_level(cellId) < this->m_maxSensorRefinementLevel[sen]) { // refine cell
18540 if(c_noChildren(cellId) > 0) continue;
18541 if(a_isHalo(cellId)) continue;
18542 sensors[sensorOffset + sen][gridCellId] = 1.0;
18543 sensorCellFlag[gridCellId][sensorOffset + sen] = true;
18544 }
18545 }
18546 }
18547
18548 // find additional small-geometries:
18549
18550 if(globalTimeStep < 0 && !m_combustion) {
18551 //&& m_adaptationLevel < this->m_maxSensorRefinementLevel[sen]
18552 //(minLevel() + 2)
18553 /*&& !m_reconstructBand*/
18554 //&& !m_combustion) {
18555 if(m_engineSetup && m_adaptationLevel < this->m_maxSensorRefinementLevel[sen]) {
18556 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18557 for(MInt set = 0; set < m_noSets; set++) {
18558 if(!m_computeSet_backup[set]) continue;
18559 if(a_inBandG(cellId, set)) {
18560 const MInt gridCellId = grid().tree().solver2grid(cellId);
18561 sensors[sensorOffset + sen][gridCellId] = 1;
18562 sensorCellFlag[gridCellId][sensorOffset + sen] = 1;
18563 }
18564 }
18565 }
18566 } else if(m_adaptationLevel == minLevel() && m_reconstructBand < 1) {
18567 for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18568 for(MInt set = 0; set < m_noSets; set++) {
18569 if(a_inBandG(cellId, set)) {
18570 const MInt gridCellId = grid().tree().solver2grid(cellId);
18571 sensors[sensorOffset + sen][gridCellId] = 1;
18572 sensorCellFlag[gridCellId][sensorOffset + sen] = 1;
18573 }
18574 }
18575 }
18576 }
18577 }
18578
18579
18580 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
18581}
18582
18587template <MInt nDim>
18588void LsCartesianSolver<nDim>::setSensors(std::vector<std::vector<MFloat>>& sensors,
18589 std::vector<MFloat>& sensorWeight,
18590 std::vector<std::bitset<64>>& sensorCellFlag,
18591 std::vector<MInt>& sensorSolverId) {
18592 TRACE();
18593
18594 if(this->m_noSensors < 1) {
18595 return;
18596 }
18597
18598 // If solver is inactive the sensor arrays still need to be set to optain the
18599 // correct offsets
18600 if(!isActive()) {
18601 const MInt sensorOffset = (signed)sensors.size();
18602 ASSERT(sensorOffset == 0 || grid().raw().treeb().noSolvers() > 1, "");
18603 sensors.resize(sensorOffset + this->m_noSensors, vector<MFloat>(grid().raw().m_noInternalCells, F0));
18604 sensorWeight.resize(sensorOffset + this->m_noSensors, -1);
18605 sensorCellFlag.resize(grid().raw().m_noInternalCells, sensorOffset + this->m_noSensors);
18606 sensorSolverId.resize(sensorOffset + this->m_noSensors, solverId());
18607 ASSERT(sensorOffset + this->m_noSensors < CartesianGrid<nDim>::m_maxNoSensors, "Increase bitset size!");
18608
18609 for(MInt sen = 0; sen < this->m_noSensors; sen++) {
18610 sensorWeight[sensorOffset + sen] = this->m_sensorWeight[sen];
18611 }
18612
18613 return;
18614 }
18615
18616 // necessary here, as the sensors are also set on lower Grid-levels!
18617 // for avoid updateLowerGridLevels
18618 // updateLowerGridLevels();
18619
18620 // the sensors are added at the end of the previous sensor-vectors!
18621 const auto sensorOffset = (signed)sensors.size();
18622 ASSERT(sensorOffset == 0 || grid().raw().treeb().noSolvers() > 1, "");
18623 sensors.resize(sensorOffset + this->m_noSensors, vector<MFloat>(grid().raw().m_noInternalCells, F0));
18624 sensorWeight.resize(sensorOffset + this->m_noSensors, -1);
18625 sensorCellFlag.resize(grid().raw().m_noInternalCells, sensorOffset + this->m_noSensors);
18626 sensorSolverId.resize(sensorOffset + this->m_noSensors, solverId());
18627 ASSERT(sensorOffset + this->m_noSensors < CartesianGrid<nDim>::m_maxNoSensors, "Increase bitset size!");
18628
18629 // Sohels-sensor-method:
18630 if(m_combustion) {
18631 MIntScratchSpace regrid(1, AT_, "regrid");
18632
18633 // FIXME labels:LS,toenhance
18634 // more efficient solution can be found!!:
18635 // levelSetAdaptationTrigger is also run in the application loop at the moment to figure out if the grid controller
18636 // adaptation has to be forced for the ls-solver it is also included here in case that a different solver wants to
18637 // adapt since in that case this function has to do certain things even if levelSetAdaptationTrigger() is false
18638 regrid.p[0] = levelSetAdaptationTrigger();
18639 regrid.p[0] = 1;
18640 // FIXME labels:LS
18641 // only using this for initial refinement right now
18642 // should be removed once the proper initialAdaptation routines are used instead of this one
18643 if(globalTimeStep == 0 || globalTimeStep == -1) {
18644 regrid.p[0] = 1;
18645 }
18646
18647 // Use all sets for the mesh-adaptation!
18648 for(MInt set = 0; set < m_noSets; set++) {
18649 m_computeSet_tmp[set] = m_computeSet[set];
18650 m_computeSet[set] = true;
18651 }
18652
18653 // FIXME labels:LS
18654 // to remove, its replaced by levelSetAdaptationTrigger
18655 // From this part on a level-Set based adaptation will be triggered
18656 m_forceAdaptation = true;
18657
18658 if(regrid.p[0] == 0) {
18659 return;
18660 }
18661
18662 MIntScratchSpace sendBufferSize(grid().noNeighborDomains(), AT_, "sendBufferSize");
18663 MIntScratchSpace receiveBufferSize(grid().noNeighborDomains(), AT_, "receiveBufferSize");
18664
18665 MInt tmpCount = 0;
18666 MIntScratchSpace tmp(m_maxNoCells, AT_, "tmp");
18667 MInt lastLayerCount = 0;
18668 MIntScratchSpace lastLayer(m_maxNoCells, AT_, "lastLayer");
18669 MBoolScratchSpace isAdded(m_maxNoCells, AT_, "isAdded");
18670 MInt listCount = 0;
18671 MIntScratchSpace list(m_maxNoCells, AT_, "list");
18672 MBoolScratchSpace coarseningFlag(grid().raw().treeb().size(), AT_, "coarseningFlag");
18673
18674 for(MInt i = 0; i < a_noCells(); i++) {
18675 a_isBndryCellG(i) = false;
18676 }
18677
18678 for(MInt c = 0; c < m_maxNoCells; c++) {
18679 isAdded.p[c] = false;
18680 }
18681
18682 for(MInt c = 0; c < grid().raw().treeb().size(); c++) {
18683 coarseningFlag.p[c] = true;
18684 }
18685
18686 // if this is not done the g0 cells are sometimes not determined correctly after adaptation
18687 determineG0Cells(0);
18688 // first layer consists of g0 cells
18689 MInt endSet = m_noSets;
18690 if(m_buildCollectedLevelSetFunction) endSet = 1;
18691 for(MInt set = 0; set < endSet; set++) {
18692 for(MInt id = 0; id < a_noG0Cells(set); id++) {
18693 MInt cellId = a_G0CellId(id, set);
18694 if(a_isHalo(cellId)) continue; // dont add halo cells here
18695 lastLayer.p[lastLayerCount] = cellId;
18696 list.p[lastLayerCount] = cellId;
18697 isAdded.p[cellId] = true;
18698 lastLayerCount++;
18699 listCount++;
18700 }
18701 }
18702
18703 ASSERT(lastLayerCount == listCount, "");
18704
18705 // now add the correct halo cells to the list
18706 // gather:
18707 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
18708 sendBufferSize.p[i] = 0;
18709 for(MInt j = 0; j < noWindowCells(i); j++) {
18710 m_intSendBuffers[i][sendBufferSize.p[i]++] = isAdded(windowCellId(i, j));
18711 }
18712 }
18713 if(grid().azimuthalPeriodicity()) {
18714 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
18715 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
18716 m_intSendBuffers[i][sendBufferSize.p[i]++] = isAdded(grid().azimuthalWindowCell(i, j));
18717 }
18718 }
18719 }
18720 // exchange data -> send, receive
18721 exchangeIntBuffers(sendBufferSize.getPointer(), receiveBufferSize.getPointer(), 4, 1);
18722 // scatter:
18723 // update the halo information
18724 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
18725#ifdef LS_DEBUG
18726 // check, if received data size matches expected size:
18727 if(!(receiveBufferSize.p[i] == noHaloCells(i))) {
18728 cerr << "this was not expected to happen: wrong number of halo information, buf=" << receiveBufferSize.p[i]
18729 << "noGHaloCells=" << noHaloCells(i) << ", has been added" << endl;
18730 ;
18731 }
18732#endif
18733 for(MInt j = 0; j < noHaloCells(i); j++) {
18734 MInt gc = haloCellId(i, j);
18735 if(m_intReceiveBuffers[i][j]) {
18736 lastLayer.p[lastLayerCount] = gc;
18737 lastLayerCount++;
18738 isAdded.p[gc] = true;
18739 }
18740 }
18741 }
18742 if(grid().azimuthalPeriodicity()) {
18743 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
18744 MInt offset = noHaloCells(grid().azimuthalNeighborDomain(i));
18745 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
18746 MInt n = offset + j;
18747 MInt haloCell = grid().azimuthalHaloCell(i, j);
18748 if(m_intReceiveBuffers[i][n]) {
18749 lastLayer.p[lastLayerCount] = haloCell;
18750 lastLayerCount++;
18751 isAdded.p[haloCell] = true;
18752 }
18753 }
18754 }
18755 }
18756
18757
18759 MInt level = minLevel();
18760
18761 // calculate the number of layers of the current level
18762 MInt factor = IPOW2((a_maxGCellLevel(0) - level));
18763 MInt currentWidth = m_gShadowWidth / factor;
18764 if(currentWidth * factor < m_gShadowWidth) { // round up the currentWidth value
18765 currentWidth++;
18766 }
18767 if(currentWidth == 1) {
18768 cerr << "WARNING: you only have 1 layer of cells for your level set band on the coarsest level right now... you "
18769 "may want to rethink your level set grid resolution"
18770 << endl;
18771 }
18772 MInt currentLayer = 0;
18773
18774 tmpCount = 0;
18775 // add g0 cells to the list
18776 for(MInt i = 0; i < lastLayerCount; i++) {
18777 if(!isAdded.p[lastLayer.p[i]]) {
18778 list.p[listCount] = lastLayer.p[i];
18779 listCount++;
18780 isAdded.p[lastLayer.p[i]] = true;
18781 }
18782 }
18783 currentLayer = 0;
18784 while(currentLayer < currentWidth) {
18785 // find next layer of cells
18786 for(MInt i = 0; i < lastLayerCount; i++) {
18787 MInt gc = lastLayer.p[i];
18788
18789 // if gc is on a higher level than the current level, take the parent until you find a parent with the correct
18790 // level
18791 while(a_level(gc) > level) {
18792 gc = c_parentId(gc);
18793 }
18794
18795 for(MInt d = 0; d < m_noDirs; d++) {
18796 if(a_hasNeighbor(gc, d)) {
18797 if(!isAdded.p[c_neighborId(gc, d)]) {
18798 tmp.p[tmpCount] = c_neighborId(gc, d);
18799 isAdded.p[tmp.p[tmpCount]] = true;
18800 tmpCount++;
18801 }
18802 }
18803 }
18804 }
18805
18806 // check if halo cells must be coarsened
18807 // gather:
18808 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
18809 sendBufferSize.p[i] = 0;
18810 for(MInt j = 0; j < noWindowCells(i); j++) {
18811 m_intSendBuffers[i][sendBufferSize.p[i]++] = isAdded(windowCellId(i, j));
18812 }
18813 }
18814 if(grid().azimuthalPeriodicity()) {
18815 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
18816 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
18817 m_intSendBuffers[i][sendBufferSize.p[i]++] = isAdded[grid().azimuthalWindowCell(i, j)];
18818 }
18819 }
18820 }
18821 // exchange data -> send, receive
18822 exchangeIntBuffers(sendBufferSize.getPointer(), receiveBufferSize.getPointer(), 4, 1);
18823 // scatter:
18824 // update the halo information
18825 for(MInt i = 0; i < grid().noNeighborDomains(); i++) {
18826#ifdef LS_DEBUG
18827 // check, if received data size matches expected size:
18828 if(!(receiveBufferSize.p[i] == noHaloCells(i))) {
18829 m_log << "this was not expected to happen: wrong number of halo information, buf=" << receiveBufferSize.p[i]
18830 << "noGHaloCells=" << noHaloCells(i) << ", has been added" << endl;
18831 ;
18832 }
18833#endif
18834 for(MInt j = 0; j < noHaloCells(i); j++) {
18835 MInt gc = haloCellId(i, j);
18836 if(m_intReceiveBuffers[i][j]) {
18837 tmp.p[tmpCount] = gc;
18838 isAdded.p[tmp.p[tmpCount]] = true;
18839 tmpCount++;
18840 }
18841 }
18842 }
18843 if(grid().azimuthalPeriodicity()) {
18844 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
18845 MInt offset = noHaloCells(grid().azimuthalNeighborDomain(i));
18846 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
18847 MInt n = offset + j;
18848 MInt haloCell = grid().azimuthalHaloCell(i, j);
18849 if(m_intReceiveBuffers[i][n]) {
18850 tmp.p[tmpCount] = haloCell;
18851 isAdded.p[tmp.p[tmpCount]] = true;
18852 tmpCount++;
18853 }
18854 }
18855 }
18856 }
18857
18858 // add new layer to list
18859 for(MInt i = 0; i < tmpCount; i++) {
18860 list.p[listCount] = tmp.p[i];
18861 listCount++;
18862 // and replace the last layer list with the tmp list
18863 lastLayer.p[i] = tmp.p[i];
18864 }
18865 lastLayerCount = tmpCount;
18866 tmpCount = 0;
18867 currentLayer++;
18868 }
18869
18870 // add all children to the list
18871 for(MInt i = 0; i < listCount; i++) {
18872 MInt gc = list.p[i];
18873 if(c_noChildren(gc) > 0) {
18874 for(MInt child = 0; child < IPOW2(nDim); child++) {
18875 if(c_childId(gc, child) == -1) {
18876 continue;
18877 }
18878 MInt cId = c_childId(gc, child);
18879 if(!isAdded.p[cId]) {
18880 isAdded.p[cId] = true;
18881 list.p[listCount] = cId;
18882 listCount++;
18883 }
18884 }
18885 }
18886 }
18887
18888 // set sensor for all cells that have been added to the list
18889 for(MInt c = 0; c < listCount; c++) {
18890 MInt gridCellId = grid().tree().solver2grid(list.p[c]);
18891 coarseningFlag.p[gridCellId] = false;
18892 if(a_level(list.p[c]) < a_maxGCellLevel(0)) { // refine cell
18893 if(c_noChildren(list.p[c]) > 0) continue;
18894 if(a_isHalo(list.p[c])) continue;
18895 sensors[sensorOffset][gridCellId] = 1.0;
18896 sensorCellFlag[gridCellId][sensorOffset] = 1;
18897 }
18898 }
18899
18900 // now coarsen all cells that are not tagged and that have no children
18901 // only do this for the grid proxy though
18902 for(MInt i = 0; i < grid().tree().size(); i++) {
18903 if(!coarseningFlag.p[grid().tree().solver2grid(i)]) {
18904 continue;
18905 }
18906 if(grid().tree().level(i) == minLevel()) {
18907 continue;
18908 }
18909 if(grid().tree().noChildren(i) == 0) {
18910 MInt solverCellId = i;
18911 if(grid().tree().hasProperty(solverCellId, Cell::IsHalo)) {
18912 continue;
18913 }
18914 MInt gridCellId = grid().tree().solver2grid(solverCellId); // use correct grid id for the sensor
18915 sensors[sensorOffset][gridCellId] = -1.0;
18916 sensorCellFlag[gridCellId][sensorOffset] = 1;
18917 }
18918 }
18919
18920 } else { // using Tims-sensor-method:
18921
18922 // only set sensors if the adaptation was globally triggered in buildLevelSetTubeCG!
18923 if(this->m_adapts && ((m_forceAdaptation && globalTimeStep > 0) || (globalTimeStep < 0))) {
18924 if(domainId() == 0) {
18925 cerr << "Setting " << this->m_noSensors << " sensor(s) for the ls-solver adaptation!" << endl;
18926 }
18927
18928 for(MInt sen = 0; sen < this->m_noSensors; sen++) {
18929 (this->*(this->m_sensorFnPtr[sen]))(sensors, sensorCellFlag, sensorWeight, sensorOffset, sen);
18930 }
18931 }
18932
18933 /*
18934 // debug-output:
18935 for(MInt i=0;i<grid().raw().treeb().size();i++){
18936 grid().raw().treeb().weight(i)=1;
18937 }
18938 m_bodyIdOutput = true;
18939 MInt globalTimeStep_temp = globalTimeStep;
18940 globalTimeStep = m_adaptationLevel;
18941 // for(MInt cellId = 0; cellId < noInternalCells(); cellId++) {
18942 // const MInt gridCellId = grid().tree().solver2grid(cellId);
18943 // a_bodyIdG(cellId, 0) = sensors[sensorOffset][gridCellId];
18944 //}
18945 writeRestartLevelSetFileCG(1, "restartLSGridCG_sensors" , "restartLSCG_sensors");
18946 globalTimeStep = globalTimeStep_temp;
18947 */
18948
18949 ASSERT(m_freeIndices.empty(), "");
18950 m_freeIndices.clear();
18951
18952 m_refinedCells.clear();
18953 }
18954}
18955
18960template <MInt nDim>
18961void LsCartesianSolver<nDim>::postAdaptation() {
18962 TRACE();
18963
18964 this->compactCells();
18965 // URL
18966 if(!g_multiSolverGrid) {
18967 for(MInt gridCellId = 0; gridCellId < grid().raw().treeb().size(); gridCellId++) {
18968 ASSERT(grid().tree().solver2grid(gridCellId) == gridCellId, "");
18969 ASSERT(grid().tree().grid2solver(gridCellId) == gridCellId, "");
18970 }
18971 }
18972 //}
18973
18974 grid().updateOther();
18975
18976 updateDomainInfo(grid().domainId(), grid().noDomains(), grid().mpiComm(), AT_);
18977
18978 // Nothing further to be done if solver inactive
18979 if(!isActive()) return;
18980
18981 grid().updateLeafCellExchange();
18982
18983 ASSERT(!m_constructGField, "");
18984
18985 generateListOfGExchangeCellsCG();
18986
18987 this->checkNoHaloLayers();
18988
18989 // Initialize the azimuthal periodic exchange
18990 initAzimuthalExchange();
18991
18992 exchangeAllLevelSetData();
18993 exchangeGapInfo();
18994
18995 // previous part from initialRefinement!
18996 if(globalTimeStep < 0 && m_geometryChange == nullptr) {
18997 if(m_combustion) {
18998 initSolver();
18999 } else {
19000 for(MInt set = 0; set < m_noSets; set++) {
19001 std::vector<MInt>().swap(m_bandCells[set]);
19002 }
19003
19004 if(m_GFieldInitFromSTL) constructGFieldFromSTL(1);
19005
19006 if(m_buildCollectedLevelSetFunction) buildCollectedLevelSet(0);
19007
19008 determineG0Cells();
19009 createGgridCG();
19010
19011 if(m_GFieldInitFromSTL) {
19012 determineG0Cells();
19013 determineBandCells();
19014 m_log << "Initialize G Field from stl data...";
19015 constructGFieldFromSTL(3);
19016 m_log << "ok" << endl;
19017 for(MInt set = 0; set < m_noSets; set++) {
19018 std::vector<MInt>().swap(m_bandCells[set]);
19019 }
19020 }
19021
19022 if(m_buildCollectedLevelSetFunction) buildCollectedLevelSet(0);
19023 determineG0Cells();
19024 determineBandCells();
19025 updateBndryCellList();
19026 resetOutsideCells();
19027 if(m_GFieldInitFromSTL) constructGFieldFromSTL(0);
19028 if(m_buildCollectedLevelSetFunction) buildCollectedLevelSet(0);
19029 if(m_GFieldInitFromSTL) resetOutsideCells();
19030
19031 if(m_LsRotate) resetContainingGCells();
19032 exchangeAllLevelSetData();
19033 checkHaloCells();
19034 }
19035 } else if(globalTimeStep < 0 && m_geometryChange != nullptr) {
19036 for(MInt set = 0; set < m_noSets; set++) {
19037 std::vector<MInt>().swap(m_bandCells[set]);
19038 }
19039
19040 determineG0Cells();
19041 determineBandCells();
19042 m_log << "Initialize G Field from mew stl data...";
19043 constructGFieldFromSTL(5);
19044 m_log << "ok" << endl;
19045
19046 // NOTE: two loops ensure that new bandCells are also already initialised in the
19047 // first adaptationLoop. This increases the load but ensures the current
19048 // construction of the new levelSet Field!
19049 // thus only necessary if this is only called once!
19050 if(maxRefinementLevel() - maxUniformRefinementLevel() < 2) {
19051 for(MInt set = 0; set < m_noSets; set++) {
19052 std::vector<MInt>().swap(m_bandCells[set]);
19053 }
19054
19055 determineG0Cells();
19056 determineBandCells();
19057 updateBndryCellList();
19058 resetOutsideCells();
19059
19060 determineG0Cells();
19061 determineBandCells();
19062 m_log << "Initialize G Field from mew stl data...";
19063 constructGFieldFromSTL(5);
19064 m_log << "ok" << endl;
19065 }
19066
19067 if(m_buildCollectedLevelSetFunction) buildCollectedLevelSet(2);
19068
19069 reInitSolver(true);
19070
19071 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
19072 for(MInt set = m_startSet; set < m_noSets; set++) {
19073 if(!m_geometryChange[set]) continue;
19074 a_oldLevelSetFunctionG(cellId, set) = a_levelSetFunctionG(cellId, set);
19075 }
19076 }
19077
19078 if(m_LsRotate) resetContainingGCells();
19079
19080 // exchange required afterwards
19081 exchangeDataLS(&(a_oldLevelSetFunctionG(0, 0)), m_maxNoSets);
19082
19083 } else { // globalTimeStep > -1
19084 if(m_combustion) {
19085 if(globalTimeStep == 0) {
19086 initSolver();
19087 }
19088 } else {
19089 MInt noRefinedBandCells = (signed)m_refinedCells.size();
19090 MPI_Allreduce(MPI_IN_PLACE, &noRefinedBandCells, 1, MPI_INT, MPI_SUM, mpiComm(), AT_, "MPI_IN_PLACE",
19091 "noRefinedBandCells");
19092
19093 // On the fly reconstruction of levelset band cells outside the G0 Set!
19094 if(noRefinedBandCells > 0 && !m_virtualSurgery) {
19095 if(domainId() == 0 && m_reconstructBand > 1) {
19096 cerr << "Reinitialisation of " << noRefinedBandCells << " cells " << endl;
19097 }
19098 if(domainId() == 0 && m_reconstructBand == 1) {
19099 cerr << "Interpolation of " << noRefinedBandCells << " cells " << endl;
19100 }
19101
19102 m_newRefinedBand = true;
19103
19104 ASSERT(m_semiLagrange, "");
19105 ASSERT(m_reconstructBand > 0,
19106 "CAUTION: refining a band cell after the initial adaptation without reconstructBand!");
19107
19108 ASSERT(m_GFieldInitFromSTL, "");
19109
19110 // construct old-LevelSet data based on shifted geometry!
19111 if(m_reconstructBand > 1) {
19112 constructGFieldFromSTL(4);
19113 exchangeDataLS(&(a_oldLevelSetFunctionG(0, 0)), m_maxNoSets);
19114
19115 if(m_maxLevelChange) {
19116 resetOldOutsideCells();
19117 }
19118
19119 // copy old levelset to levelset for stationary bodies
19120 for(auto& m_refinedCell : m_refinedCells) {
19121 const MInt cellId = m_refinedCell.first;
19122 ASSERT(!a_isHalo(cellId), "");
19123 const MInt set = m_refinedCell.second;
19124 if(set > 0) {
19125 if(!m_computeSet_backup[set]) {
19126 a_levelSetFunctionG(cellId, set) = a_oldLevelSetFunctionG(cellId, set);
19127 }
19128 } else {
19129 for(MInt setI = m_startSet; setI < m_noSets; setI++) {
19130 if(m_computeSet_backup[setI]) {
19131 continue;
19132 }
19133 a_levelSetFunctionG(cellId, setI) = a_oldLevelSetFunctionG(cellId, setI);
19134 }
19135 }
19136 }
19137 } else {
19138 // interpolate level set
19139 for(auto& m_refinedCell : m_refinedCells) {
19140 const MInt cellId = m_refinedCell.first;
19141 const MInt set = m_refinedCell.second;
19142 if(set == 0) {
19143 continue;
19144 }
19145 std::array<MInt, 8> interpolationCells = {0, 0, 0, 0, 0, 0, 0, 0};
19146 std::array<MFloat, nDim> cellPos = {};
19147 for(MInt i = 0; i < nDim; i++) {
19148 cellPos[i] = c_coordinate(cellId, i);
19149 }
19150 const MInt parent = c_parentId(cellId);
19151 const MInt position = setUpLevelSetInterpolationStencil(parent, interpolationCells.data(), cellPos.data());
19152 if(position > -1) {
19153 a_levelSetFunctionG(cellId, set) = interpolateLevelSet(interpolationCells.data(), cellPos.data(), set);
19154 a_oldLevelSetFunctionG(cellId, set) =
19155 interpolateOldLevelSet(interpolationCells.data(), cellPos.data(), set);
19156 }
19157 }
19158 }
19159 exchangeLevelSet();
19160
19161 reInitSolver(m_forceAdaptation);
19162
19163 if(grid().azimuthalPeriodicity()) {
19164 this->exchangeAzimuthalPer(&(a_oldLevelSetFunctionG(0, 0)), m_maxNoSets);
19165 }
19166 }
19167 }
19168 }
19169
19170 // debug-output:
19171 /*
19172 for(MInt i=0;i<grid().raw().treeb().size();i++){
19173 grid().raw().treeb().weight(i)=1;
19174 }
19175 MInt globalTimeStep_temp = globalTimeStep;
19176 globalTimeStep = m_adaptationLevel;
19177 writeRestartLevelSetFileCG(1, "restartLSGridCG_init" , "restartLSCG_init");
19178 globalTimeStep = globalTimeStep_temp;
19179 */
19180 m_adaptationLevel++;
19181}
19182
19183
19188template <MInt nDim>
19189void LsCartesianSolver<nDim>::finalizeAdaptation() {
19190 TRACE();
19191
19192 // Set properties and return if solver is inactive
19193 if(!isActive()) {
19194 m_forceAdaptation = false;
19195 m_adaptationSinceLastRestart = false;
19196 return;
19197 }
19198
19199 if(m_combustion || m_freeSurface) {
19200 finalizeLevelSet_(0, 0);
19201 m_forceAdaptation = false;
19202 m_adaptationSinceLastRestart = true;
19203 return;
19204 }
19205
19206 if(globalTimeStep > 0) { // part from reinitAfterAdaptation:
19207
19208
19209 reInitSolver(m_forceAdaptation);
19210
19211 if(m_LsRotate) {
19212 updateContainingGCells();
19213 copyWindowToHaloIds();
19214 }
19215
19216 if(m_maxLevelChange) {
19217 if(domainId() == 0) {
19218 cerr << "Ls-MaxLevel after adaptation: " << maxLevel() << endl;
19219 }
19220 }
19221
19222 } else if(m_geometryChange == nullptr) { // part from postInitialRefinementStep:
19223
19224 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
19225 for(MInt set = 0; set < m_maxNoSets; set++) {
19226 if(!m_semiLagrange) {
19227 for(MInt d = 0; d < nDim; d++) {
19228 a_extensionVelocityG(cellId, d, set) = F0;
19229 }
19230 } else {
19231 a_oldLevelSetFunctionG(cellId, set) = a_levelSetFunctionG(cellId, set);
19232 }
19233 }
19234 if(m_maxNoSets > 1 && m_closeGaps) {
19235 a_potentialGapCell(cellId) = 0;
19236 a_potentialGapCellClose(cellId) = 0;
19237 }
19238 }
19239
19240 setGCellBndryProperty();
19241
19242 if(!m_semiLagrange) {
19243 computeNormalVectors();
19244 computeCurvature();
19245 }
19246
19247 finalizeLevelSetInitialization();
19248
19249 buildMultipleLevelSet(2);
19250
19251 if(m_GFieldFromSTLInitCheck) {
19252 // FIXME labels:LS hack to initialise weights,
19253 // necessary for writing a restart-file out of the solver, after an adaptation
19254 // move into the meshAdaptation to initialice new cells with weight 1/0
19255 for(MInt i = 0; i < grid().raw().treeb().size(); i++) {
19256 grid().raw().treeb().weight(i) = 1;
19257 }
19258
19259 MInt globalTimeStep_temp = globalTimeStep;
19260 globalTimeStep = 0;
19261 if(!m_initFromRestartFile) {
19262 writeRestartLevelSetFileCG(1, "restartLSGridCG_init", "restartLSCG_init");
19263 } else {
19264 writeRestartLevelSetFileCG(1, "restartLSGridCG_reinit", "restartLSCG_reinit");
19265 }
19266 globalTimeStep = globalTimeStep_temp;
19267 }
19268
19269 if(m_LSSolver) initSolver();
19270
19271 } else { // globalTimeStep = -1 && m_geometryChange != nullptr
19272
19273 finalizeLevelSetInitialization();
19274
19275 if(!m_oldG0Cells.empty()) {
19276 MInt startSet = 0;
19277 if(m_buildCollectedLevelSetFunction) startSet = 1;
19278
19279 // check new G0-cells and delete entries which were were also a G0 cell in the old geometry!
19280 for(MInt set = startSet; set < m_noSets; set++) {
19281 if(!m_geometryChange[set]) continue;
19282 for(MInt id = 0; id < a_noG0Cells(set); id++) {
19283 const MInt cellId = a_G0CellId(id, set);
19284 if(a_isHalo(cellId)) continue;
19285 auto it0 = m_oldG0Cells.find(cellId);
19286 if(it0 != m_oldG0Cells.end()) {
19287 const MInt oldSet = it0->second;
19288 if(oldSet == set) {
19289 m_oldG0Cells.erase(it0);
19290 }
19291 }
19292 }
19293 }
19294 }
19295 }
19296
19297 if((m_maxLevelChange || m_geometryChange != nullptr) && m_trackMovingBndry) {
19298 // shift STL back!
19299 ASSERT(m_GCtrlPntMethod == 2, "Only working for controlPoint-Method 2!");
19300 MFloat dx[3] = {F0, F0, F0};
19301 MFloat xCurrent[3] = {F0, F0, F0};
19302 MFloat xOld[3] = {F0, F0, F0};
19303 const MFloat usedTime = m_geometryChange != nullptr ? time() : time() + timeStep();
19304 for(MInt set = m_startSet; set < m_noSets; set++) {
19305 if(!m_computeSet_backup[set]) continue;
19306 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
19307 const MInt body = m_setToBodiesTable[set][b];
19308 const MInt bcId = m_bodyBndryCndIds[body];
19309 computeBodyPropertiesForced(1, xCurrent, body, usedTime);
19310 computeBodyPropertiesForced(1, xOld, body, 0.0);
19311
19312 for(MInt d = 0; d < nDim; d++) {
19313 // dx[d] = -(xCurrent[d] - xOld[d]);
19314 dx[d] = -m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body];
19315 }
19316 m_gCtrlPnt.CtrlPnt2_shiftSTL(bcId, dx);
19317 }
19318 }
19319 }
19320
19321 // reset properties back to default after the sucessful adaptation
19322 if(m_maxLevelChange && (maxLevel() == maxRefinementLevel() || maxLevel() == this->m_maxSensorRefinementLevel[0])) {
19323 m_maxLevelChange = false;
19324 }
19325 if(m_geometryChange != nullptr) {
19326 mDeallocate(m_geometryChange);
19327 }
19328
19329 exchangeAllLevelSetData();
19330
19331 if(m_virtualSurgery) {
19332 if(globalTimeStep < 0) {
19333 initializeCollectedLevelSet(0);
19334 } else {
19335 initializeCollectedLevelSet(1);
19336 }
19337 }
19338
19339 // ASSERT sanity checks
19340 testCellsCG();
19341
19342 checkHaloCells();
19343
19344 m_forceAdaptation = false;
19345 m_adaptationSinceLastRestart = true;
19346}
19347
19352template <MInt nDim>
19353void LsCartesianSolver<nDim>::prepareAdaptation() {
19354 TRACE();
19355
19356 ASSERT(m_freeIndices.empty(), "");
19357
19358 m_adaptationLevel = maxUniformRefinementLevel();
19359 m_newRefinedBand = false;
19360 m_oldG0Cells.clear();
19361
19362 if(!isActive()) return;
19363
19364 if(this->m_noSensors <= 0) {
19365 return;
19366 }
19367
19368 if(maxRefinementLevel() > maxLevel() && globalTimeStep > 0) {
19369 m_forceAdaptation = true;
19370 if(domainId() == 0) {
19371 cerr << "Max Refinement Level has been increased at restart. " << endl;
19372 cerr << "Initialising interpolation at adaptation!" << endl;
19373 }
19374
19375 // recalculate outside-G-value for max-Level-change!
19376 if(m_maxLevelChange) {
19377 if(!Context::propertyExists("maxGCellLevel", m_solverId)) {
19378 m_maxGCellLevel[0] = Context::getSolverProperty<MInt>("maxRfnmntLvl", m_solverId, AT_);
19379 } else {
19380 m_maxGCellLevel[0] = Context::getSolverProperty<MInt>("maxGCellLevel", m_solverId, AT_, 0);
19381 }
19382
19383 m_gCellDistance = c_cellLengthAtLevel(m_maxGCellLevel[0]);
19384 m_FgCellDistance = F1 / m_gCellDistance;
19385 m_log << "smallest gCell length " << m_gCellDistance << endl;
19386
19387 m_outsideGValue = (MFloat)(2 * m_gBandWidth * m_gCellDistance);
19388 m_log << "Outside G value: " << m_outsideGValue << endl;
19389 }
19390 }
19391
19392 if(this->m_maxSensorRefinementLevel[0] < maxLevel()) {
19393 m_forceAdaptation = true;
19394 if(domainId() == 0) {
19395 cerr << "Max Refinement Level has been decreased at restart." << endl;
19396 cerr << "Initialising interpolation at adaptation!" << endl;
19397 }
19398 if(Context::propertyLength("maxRfnmntLvl", m_solverId) == 1) {
19399 m_maxGCellLevel[0] = this->m_maxSensorRefinementLevel[0];
19400 } else {
19401 for(MInt set = 0; set < m_maxNoSets; set++) {
19402 m_maxGCellLevel[set] = this->m_maxSensorRefinementLevel[0];
19403 }
19404 }
19405
19406 m_gCellDistance = c_cellLengthAtLevel(m_maxGCellLevel[0]);
19407 m_FgCellDistance = F1 / m_gCellDistance;
19408 m_log << "smallest gCell length " << m_gCellDistance << endl;
19409
19410 m_outsideGValue = (MFloat)(2 * m_gBandWidth * m_gCellDistance);
19411 m_log << "Outside G value: " << m_outsideGValue << endl;
19412 }
19413
19414 if(grid().newMinLevel() > maxUniformRefinementLevel()) m_forceAdaptation = true;
19415
19416
19417 if(globalTimeStep < 0 && m_geometryChange != nullptr) {
19418 // save old G0-Cells, so that a sponging can be applied to the fv-solution
19419 // if they are no longer a G0-cell for the new geometry!
19420
19421 MInt startSet = 0;
19422 if(m_buildCollectedLevelSetFunction) startSet = 1;
19423
19424 for(MInt set = startSet; set < m_noSets; set++) {
19425 if(!m_geometryChange[set]) continue;
19426 for(MInt id = 0; id < a_noG0Cells(set); id++) {
19427 const MInt cellId = a_G0CellId(id, set);
19428 if(a_isHalo(cellId)) continue;
19429 ASSERT(a_isGZeroCell(cellId, set), "");
19430 m_oldG0Cells.insert(make_pair(cellId, set));
19431 }
19432 }
19433 }
19434
19435 // the levelset of a moving STL will be reconstructed during the adaptation!
19436 // shift all STLs to the correct place
19437 if((m_geometryChange != nullptr || m_maxLevelChange) && m_trackMovingBndry) {
19438 ASSERT(m_GCtrlPntMethod == 2, "Only working for controlPoint-Method 2!");
19439 MFloat dx[3] = {F0, F0, F0};
19440 MFloat xCurrent[3] = {F0, F0, F0};
19441 MFloat xOld[3] = {F0, F0, F0};
19442 const MFloat usedTime = m_geometryChange != nullptr ? time() : time() + timeStep();
19443 for(MInt set = m_startSet; set < m_noSets; set++) {
19444 if(!m_computeSet_backup[set]) continue;
19445 for(MInt b = 0; b < m_noBodiesInSet[set]; b++) {
19446 const MInt body = m_setToBodiesTable[set][b];
19447 const MInt bcId = m_bodyBndryCndIds[body];
19448 computeBodyPropertiesForced(1, xCurrent, body, usedTime);
19449 computeBodyPropertiesForced(1, xOld, body, 0.0);
19450
19451 for(MInt d = 0; d < nDim; d++) {
19452 // dx[d] = xCurrent[d] - xOld[d];
19453 dx[d] = m_semiLagrange_xShift_ref[d * m_noEmbeddedBodies + body];
19454 }
19455 m_gCtrlPnt.CtrlPnt2_shiftSTL(bcId, dx);
19456 }
19457 }
19458 }
19459}
19460
19466template <MInt nDim>
19467void LsCartesianSolver<nDim>::postTimeStep() {
19468 TRACE();
19469
19470 if(!m_trackMovingBndry || globalTimeStep < m_trackMbStart || globalTimeStep > m_trackMbEnd) {
19471 return;
19472 }
19473
19474 RECORD_TIMER_START(m_timers[Timers::PostTime]);
19475
19476 if(m_combustion) {
19477 m_forceAdaptation = levelSetAdaptationTrigger();
19478 if(!m_forceAdaptation) {
19479 finalizeLevelSet_(0, 0);
19480 }
19481
19482 } else if(m_freeSurface) {
19483 finalizeLevelSet_(0, 0);
19484
19485 } else {
19486 finalizeLevelSet();
19487 }
19488
19489 RECORD_TIMER_STOP(m_timers[Timers::PostTime]);
19490}
19491
19492
19497template <MInt nDim>
19498void LsCartesianSolver<nDim>::reInitSolver(const MBool regrid) {
19499 TRACE();
19500
19501 // reset
19502 for(MInt set = 0; set < m_noSets; set++) {
19503 std::vector<MInt>().swap(m_bandCells[set]);
19504 m_computeSet[set] = true;
19505 m_changedSet[set] = true;
19506 }
19507
19508 // recreate a_regridTriggerG
19509 if(regrid) {
19510 determineG0Cells();
19511 if(m_buildCollectedLevelSetFunction) determineG0Cells(0);
19512
19513 createGgridCG(); // requires all G0-cells
19514 } else {
19515 determineG0Cells();
19516 }
19517
19518 determineBandCells();
19519
19520 if(!m_semiLagrange) {
19521 setGCellBndryProperty();
19522 updateBndryCellList();
19523 }
19524
19525 resetOutsideCells();
19526
19527 setUpPotentialGapCells();
19528 buildMultipleLevelSet(2);
19529 exchangeGapInfo();
19530
19531 updateLowerGridLevels();
19532
19533 exchangeAllLevelSetData();
19534
19535 checkHaloCells();
19536
19537 // reset m_computeSet, to the original values before the adaptation
19538 if(globalTimeStep > -1) {
19539 for(MInt set = 0; set < m_noSets; set++) {
19540 m_computeSet[set] = m_computeSet_backup[set];
19541 }
19542 }
19543}
19544
19552template <MInt nDim>
19553MFloat LsCartesianSolver<nDim>::crankAngle(const MFloat elapsedTime, const MInt mode) {
19554 TRACE();
19555
19556 MFloat& Strouhal = m_static_crankAngle_Strouhal;
19557 MFloat& initialCad = m_static_crankAngle_initialCad;
19558
19559 if(initialCad < 0) {
19560 Strouhal = Context::getSolverProperty<MFloat>("Strouhal", m_solverId, AT_, &Strouhal);
19561 initialCad = 0;
19562 initialCad = Context::getSolverProperty<MFloat>("initialCrankAngle", m_solverId, AT_, &initialCad);
19563 }
19564
19565 return maia::math::crankAngle(elapsedTime, Strouhal, initialCad, mode);
19566}
19567
19572template <MInt nDim>
19573void LsCartesianSolver<nDim>::initAzimuthalExchange() {
19574 TRACE();
19575
19576 if(grid().noAzimuthalNeighborDomains() == 0) return;
19577
19578 MUint sndSize = maia::mpi::getBufferSize(grid().azimuthalHaloCells());
19579 MFloatScratchSpace haloBuff(sndSize * nDim, AT_, "haloBuff");
19580 haloBuff.fill(0);
19581 MUint rcvSize = maia::mpi::getBufferSize(grid().azimuthalWindowCells());
19582 MFloatScratchSpace windowBuff(rcvSize * nDim, AT_, "windowBuff");
19583 windowBuff.fill(0);
19584
19585 this->m_azimuthalCartRecCoord.clear();
19586 this->m_azimuthalCartRecCoord.reserve(rcvSize * nDim);
19587
19588 // Get azimuthal image coordinate
19589 MFloat angle = grid().azimuthalAngle();
19590 MInt sndCnt = 0;
19591 MFloat haloCoords[nDim];
19592 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
19593 for(MInt j = 0; j < grid().noAzimuthalHaloCells(i); j++) {
19594 MInt haloId = grid().azimuthalHaloCell(i, j);
19595 ASSERT(grid().raw().a_hasProperty(grid().tree().solver2grid(haloId), Cell::IsPeriodic),
19596 "azimuthal halo is not isPeriodic!");
19597
19598 for(MInt d = 0; d < nDim; d++) {
19599 haloCoords[d] = c_coordinate(haloId, d);
19600 }
19601
19602 MInt side = grid().determineAzimuthalBoundarySide(haloCoords);
19603
19604 grid().rotateCartesianCoordinates(haloCoords, (side * angle));
19605
19606 for(MInt d = 0; d < nDim; d++) {
19607 haloBuff[sndCnt++] = haloCoords[d];
19608 }
19609 }
19610 }
19611
19612 maia::mpi::exchangeBuffer(grid().azimuthalNeighborDomains(), grid().azimuthalWindowCells(),
19613 grid().azimuthalHaloCells(), mpiComm(), haloBuff.getPointer(), windowBuff.getPointer(),
19614 nDim);
19615
19616 MInt rcvCnt = 0;
19617 for(MInt i = 0; i < grid().noAzimuthalNeighborDomains(); i++) {
19618 for(MInt j = 0; j < grid().noAzimuthalWindowCells(i); j++) {
19619 for(MInt d = 0; d < nDim; d++) {
19620 this->m_azimuthalCartRecCoord[rcvCnt] = windowBuff[rcvCnt];
19621 rcvCnt++;
19622 }
19623 }
19624 }
19625}
19626
19630template <MInt nDim>
19631void LsCartesianSolver<nDim>::rotateSTL(MInt direction, MInt body, MFloat* center) {
19632 TRACE();
19633
19634 MFloat phiRot[nDim];
19635 const MInt bcId = m_bodyBndryCndIds[body];
19636
19637 for(MInt n = 0; n < nDim; n++) {
19638 phiRot[n] = -1 * direction * m_semiLagrange_xRot_STL[body * nDim + n];
19639 }
19640
19641 m_gCtrlPnt.CtrlPnt2_rotateSTL(bcId, phiRot, center);
19642}
19643
19647template <MInt nDim>
19648void LsCartesianSolver<nDim>::rotateSTL(MInt direction) {
19649 TRACE();
19650
19651 MFloat center[nDim];
19652
19653 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
19654 const MInt body = m_bodiesToCompute[b];
19655
19656 computeBodyPropertiesForced(1, center, body, time());
19657
19658 rotateSTL(direction, body, center);
19659 }
19660}
19661
19665template <MInt nDim>
19666void LsCartesianSolver<nDim>::localToGlobalIdsContainingCells() {
19667 TRACE();
19668
19669 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
19670 MInt body = m_bodiesToCompute[b];
19671 MInt set = m_bodyToSetTable[body];
19672
19673 MIntScratchSpace noCellsToDom(grid().noDomains(), AT_, "noCellsToDom");
19674 noCellsToDom.fill(0);
19675
19676 for(MInt id = 0; id < a_noBandCells(set); id++) {
19677 MInt cellId = a_bandCellId(id, set);
19678 if(!(a_bodyIdG(cellId, set) == body)) continue;
19679 if(grid().tree().hasProperty(cellId, Cell::IsHalo)) continue;
19680 if(a_level(cellId) != a_maxGCellLevel()) continue;
19681
19682 MInt domId = a_containingDomain(cellId, b);
19683 if(domId > -1) {
19684 noCellsToDom[domId]++;
19685 }
19686 }
19687
19688 startLoadTimer(AT_);
19689
19690 prepareGlobalComm(&noCellsToDom[0]);
19691
19692 MInt noCellsComm = mMax(m_globalSndOffsets[grid().noDomains()], m_globalRcvOffsets[grid().noDomains()]);
19693
19694 MLongScratchSpace sndBufGlob(noCellsComm, AT_, "sndBufGlob");
19695 MLongScratchSpace rcvBufGlob(noCellsComm, AT_, "rcvBufGlob");
19696 MIntScratchSpace sndBufSizeGlob(grid().noDomains(), AT_, "sndBufSizeGlob");
19697 MIntScratchSpace rcvBufSizeGlob(grid().noDomains(), AT_, "rcvBufSizeGlob");
19698
19699 sndBufGlob.fill(-1);
19700 rcvBufGlob.fill(-1);
19701 sndBufSizeGlob.fill(0);
19702 rcvBufSizeGlob.fill(0);
19703
19704 std::vector<std::vector<MInt>> cellIdsLoc;
19705 cellIdsLoc.resize(grid().noDomains());
19706
19707 for(MInt cell = 0; cell < a_noCells(); cell++) {
19708 if(a_isHalo(cell)) continue;
19709 ASSERT(a_domainId(c_globalId(cell)) == domainId(), "globalId conversion is broken!");
19710 MInt cellId = a_containingCell(cell, b);
19711 if(cellId > -1 && a_inBandG(cell, set) && a_bodyIdG(cell, set) == body && a_level(cell) == a_maxGCellLevel()) {
19712 MInt domId = a_containingDomain(cell, b);
19713 if(domainId() == domId) {
19714 ASSERT(a_localId(c_globalId(cellId)) == cellId, "GlobalId conversion is broken!");
19715 a_containingCell(cell, b) = c_globalId(cellId);
19716 } else {
19717 cellIdsLoc[domId].push_back(cell);
19718 sndBufGlob[m_globalSndOffsets[domId] + sndBufSizeGlob.p[domId]] = cellId;
19719 sndBufSizeGlob.p[domId]++;
19720 }
19721 } else {
19722 a_containingCell(cell, b) = -1;
19723 }
19724 }
19725
19726 exchangeBuffersGlobal(sndBufGlob.getPointer(), rcvBufGlob.getPointer(), sndBufSizeGlob.getPointer(),
19727 rcvBufSizeGlob.getPointer(), &m_globalSndOffsets[0], &m_globalRcvOffsets[0], 3);
19728
19729 sndBufGlob.fill(-1);
19730 sndBufSizeGlob.fill(0);
19731 for(MInt i = 0; i < grid().noDomains(); i++) {
19732 MInt ind = m_globalRcvOffsets[i];
19733 for(MInt j = 0; j < rcvBufSizeGlob(i); j++) {
19734 MInt cellId = rcvBufGlob(ind + j);
19735 ASSERT(a_localId(c_globalId(cellId)) == cellId, "GlobalId conversion is broken!");
19736 sndBufGlob(ind + sndBufSizeGlob.p[i]) = c_globalId(cellId);
19737 sndBufSizeGlob.p[i]++;
19738 }
19739 }
19740 rcvBufGlob.fill(-1);
19741 rcvBufSizeGlob.fill(0);
19742
19743 exchangeBuffersGlobal(sndBufGlob.getPointer(), rcvBufGlob.getPointer(), sndBufSizeGlob.getPointer(),
19744 rcvBufSizeGlob.getPointer(), &m_globalRcvOffsets[0], &m_globalSndOffsets[0], 3);
19745
19746 for(MInt i = 0; i < grid().noDomains(); i++) {
19747 MInt ind = m_globalSndOffsets[i];
19748 for(MInt j = 0; j < rcvBufSizeGlob(i); j++) {
19749 MInt cellId = cellIdsLoc[i][j];
19750 a_containingCell(cellId, b) = rcvBufGlob(ind + j);
19751 }
19752 }
19753 }
19754}
19755
19759template <MInt nDim>
19760void LsCartesianSolver<nDim>::globalToLocalIdsContainingCells() {
19761 TRACE();
19762
19763 MIntScratchSpace noCellsToDom(grid().noDomains(), AT_, "noCellsToDom");
19764 noCellsToDom.fill(0);
19765
19766 for(MInt b = 0; b < m_noBodiesToCompute; b++) {
19767 for(MInt i = 0; i < a_noCells(); ++i) {
19768 if(grid().tree().hasProperty(i, Cell::IsHalo)) continue;
19769 if(a_level(i) != a_maxGCellLevel()) continue;
19770
19771 MLong globalId = a_containingCell(i, b);
19772 if(globalId > -1) {
19773 MInt domId = a_domainId(globalId);
19774 noCellsToDom[domId]++;
19775 }
19776 }
19777
19778 prepareGlobalComm(&noCellsToDom[0]);
19779
19780 MInt noCellsComm = mMax(m_globalSndOffsets[grid().noDomains()], m_globalRcvOffsets[grid().noDomains()]);
19781
19782 MLongScratchSpace sndBufGlob(noCellsComm, AT_, "sndBufGlob");
19783 MLongScratchSpace rcvBufGlob(noCellsComm, AT_, "rcvBufGlob");
19784 MIntScratchSpace sndBufSizeGlob(grid().noDomains(), AT_, "sndBufSizeGlob");
19785 MIntScratchSpace rcvBufSizeGlob(grid().noDomains(), AT_, "rcvBufSizeGlob");
19786 sndBufGlob.fill(-1);
19787 rcvBufGlob.fill(-1);
19788 sndBufSizeGlob.fill(0);
19789 rcvBufSizeGlob.fill(0);
19790
19791 std::vector<std::vector<MInt>> cellIdsLoc;
19792 cellIdsLoc.resize(grid().noDomains());
19793
19794 for(MInt i = 0; i < a_noCells(); ++i) {
19795 if(grid().tree().hasProperty(i, Cell::IsHalo)) continue;
19796
19797 ASSERT(a_domainId(c_globalId(i)) == domainId(), "globalId conversion is broken!");
19798
19799 MLong globalId = a_containingCell(i, b);
19800 if(globalId > -1 && a_level(i) == a_maxGCellLevel()) {
19801 MInt domId = a_domainId(globalId);
19802 if(domainId() == domId) {
19803 ASSERT(c_globalId(a_localId(globalId)) == globalId, "GlobalId conversion is broken!");
19804 a_containingCell(i, b) = a_localId(globalId);
19805 a_containingDomain(i, b) = domId;
19806 } else {
19807 cellIdsLoc[domId].push_back(i);
19808 sndBufGlob[m_globalSndOffsets[domId] + sndBufSizeGlob.p[domId]] = globalId;
19809 sndBufSizeGlob.p[domId]++;
19810 }
19811 } else {
19812 a_containingCell(i, b) = -1;
19813 a_containingDomain(i, b) = -1;
19814 }
19815 }
19816
19817 exchangeBuffersGlobal(sndBufGlob.getPointer(), rcvBufGlob.getPointer(), sndBufSizeGlob.getPointer(),
19818 rcvBufSizeGlob.getPointer(), &m_globalSndOffsets[0], &m_globalRcvOffsets[0], 3);
19819 sndBufGlob.fill(-1);
19820 sndBufSizeGlob.fill(0);
19821
19822 for(MInt i = 0; i < grid().noDomains(); i++) {
19823 MInt ind = m_globalRcvOffsets[i];
19824 for(MInt j = 0; j < rcvBufSizeGlob(i); j++) {
19825 MLong globalId = rcvBufGlob(ind + j);
19826 ASSERT(c_globalId(a_localId(globalId)) == globalId, "GlobalId conversion is broken!");
19827 sndBufGlob(ind + sndBufSizeGlob.p[i]) = a_localId(globalId);
19828 sndBufSizeGlob.p[i]++;
19829 }
19830 }
19831 rcvBufGlob.fill(-1);
19832 rcvBufSizeGlob.fill(0);
19833
19834 exchangeBuffersGlobal(sndBufGlob.getPointer(), rcvBufGlob.getPointer(), sndBufSizeGlob.getPointer(),
19835 rcvBufSizeGlob.getPointer(), &m_globalRcvOffsets[0], &m_globalSndOffsets[0], 3);
19836
19837 for(MInt i = 0; i < grid().noDomains(); i++) {
19838 MInt ind = m_globalSndOffsets[i];
19839 for(MInt j = 0; j < rcvBufSizeGlob(i); j++) {
19840 MInt containingId = rcvBufGlob(ind + j);
19841 MInt cellId = cellIdsLoc[i][j];
19842
19843 a_containingCell(cellId, b) = containingId;
19844 a_containingDomain(cellId, b) = i;
19845 }
19846 }
19847 }
19848}
19849
19850
19854template <MInt nDim>
19855void LsCartesianSolver<nDim>::localToGlobalIds() {
19856 TRACE();
19857
19858 // Nothing to do if solver is not active
19859 if(!isActive()) {
19860 return;
19861 }
19862
19863 if(!m_reconstructOldG && m_LsRotate) {
19864 updateContainingGCells();
19865 localToGlobalIdsContainingCells();
19866 }
19867}
19868
19872template <MInt nDim>
19873void LsCartesianSolver<nDim>::reconstructOldGField() {
19874 TRACE();
19875
19876 if(domainId() == 0) cerr << "Reconstruct oldG Field...";
19877
19878 mAlloc(m_geometryChange, m_noSets, "geometryChange", false, AT_);
19879 for(MInt i = 0; i < m_noBodiesToCompute; i++) {
19880 MInt body = m_bodiesToCompute[i];
19881 MInt set = m_bodyToSetTable[body];
19882 m_geometryChange[set] = true;
19883 }
19884 rotateSTL(1);
19885 constructGFieldFromSTL(6);
19886 /*
19887 constructGFieldFromSTL(5);
19888 if(m_buildCollectedLevelSetFunction) buildCollectedLevelSet(0);
19889 for(MInt cellId = 0; cellId < a_noCells(); cellId++) {
19890 for(MInt set = m_startSet; set < m_noSets; set++) {
19891 if(!m_geometryChange[set]) continue;
19892 a_oldLevelSetFunctionG(cellId, set) = a_levelSetFunctionG(cellId, set);
19893 }
19894 }
19895 */
19896 rotateSTL(-1);
19897 mDeallocate(m_geometryChange);
19898 // Reset the rotated angle
19899 for(MInt i = 0; i < m_noBodiesToCompute; i++) {
19900 MInt body = m_bodiesToCompute[i];
19901 for(MInt d = 0; d < nDim; d++) {
19902 m_semiLagrange_xRot_ref[body * nDim + d] = F0;
19903 }
19904 }
19905 resetContainingGCells();
19906
19907 m_rotatingReinitTrigger = 0;
19908 if(domainId() == 0) cerr << " done" << endl;
19909}
19910
19916template <MInt nDim>
19917template <MBool currentLevelSet>
19918void LsCartesianSolver<nDim>::exchangeLeafDataLS() {
19919 TRACE();
19920
19921 if(m_firstSolutionExchange) {
19922 RECORD_TIMER_START(m_timers[Timers::FirstEx]);
19923 }
19924
19925 std::function<MFloat&(const MInt, const MInt)> scalarField = [&](const MInt cellId, const MInt set) -> MFloat& {
19926 IF_CONSTEXPR(currentLevelSet) { return a_levelSetFunctionG(cellId, set); }
19927 else {
19928 return a_oldLevelSetFunctionG(cellId, set);
19929 }
19930 };
19931
19932 this->exchangeLeafData(scalarField, m_maxNoSets);
19933
19934 if(grid().azimuthalPeriodicity()) {
19935 IF_CONSTEXPR(currentLevelSet) { this->exchangeAzimuthalPer(&a_levelSetFunctionG(0, 0), m_maxNoSets); }
19936 else {
19937 this->exchangeAzimuthalPer(&a_oldLevelSetFunctionG(0, 0), m_maxNoSets);
19938 }
19939 }
19940
19941 if(m_firstSolutionExchange) {
19942 RECORD_TIMER_STOP(m_timers[Timers::FirstEx]);
19943 m_firstSolutionExchange = false;
19944 }
19945}
19946
19947
19953template <MInt nDim>
19954template <typename T>
19955void LsCartesianSolver<nDim>::exchangeDataLS(T* data, const MInt dataSize) {
19956 TRACE();
19957
19958 if(m_firstSolutionExchange) {
19959 RECORD_TIMER_START(m_timers[Timers::FirstEx]);
19960 }
19961
19962 exchangeData(data, dataSize);
19963
19964 if(grid().azimuthalPeriodicity()) {
19965 this->exchangeAzimuthalPer(data, dataSize);
19966 }
19967
19968 if(m_firstSolutionExchange) {
19969 RECORD_TIMER_STOP(m_timers[Timers::FirstEx]);
19970 m_firstSolutionExchange = false;
19971 }
19972}
19973
19974
19979template <MInt nDim>
19980void LsCartesianSolver<nDim>::initializeTimers() {
19981 TRACE();
19982
19983 std::fill(m_timers.begin(), m_timers.end(), -1);
19984
19985 // Create timer group & timer for solver, and start the timer
19986 NEW_TIMER_GROUP_NOCREATE(m_timerGroup, "LS (solverId = " + to_string(m_solverId) + ")");
19987 NEW_TIMER_NOCREATE(m_timers[Timers::Solver], "total object lifetime", m_timerGroup);
19988 RECORD_TIMER_START(m_timers[Timers::Solver]);
19989
19990 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::TimeInt], "Time-integration", m_timers[Timers::Solver]);
19991 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::FirstEx], "firstLSExchange", m_timers[Timers::TimeInt]);
19992 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::PostTime], "PostTimeStep", m_timers[Timers::Solver]);
19993 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Finalize], "finalizeLS", m_timers[Timers::PostTime]);
19994 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::BuildTube], "buildLSTube", m_timers[Timers::Finalize]);
19995 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SetBand], "setLSBand", m_timers[Timers::Finalize]);
19996 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::BuildMultiple], "buildMultipleLS", m_timers[Timers::Finalize]);
19997}
19998
19999template class LsCartesianSolver<2>;
20000template class LsCartesianSolver<3>;
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
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
Definition: alloc.h:544
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
MFloat ** m_vertices
void initializeIntegrationScheme_semiLagrange()
void updateAllLowerGridLevels(MInt mode=-1)
void identifyBodies(MInt mode=0)
sets a_bodyIdG(gCells,set) for all sets exept for the collected levelset (this is done in buildCollec...
void shiftOldLevelSetField(MInt dir, MInt set, MInt body)
void exchangeAllLevelSetData()
void setUpPotentialGapCells()
Set up cells, that may be tagged as gap cells during the solver run! Initialises the arrays,...
void setUpBodyToSetTable()
void regionGrowing(MInt cellId, MInt region)
MFloat secondOrderEikonalSolver(MFloat *q, const MInt *nghbrs, MInt cellListSize, MInt maxIterations, MInt set)
void computeCurvature(MInt mode=-1)
MBool semiLagrangeTimeStep()
void determineSteadyFlameLength()
void determinePropagationSpeed()
void finalizeLevelSetInitialization()
void exchangeIntBuffers(MInt *, MInt *, MInt, MInt)
void spatiallyAdaptiveCorrectionFromSTL()
this function does a correction based on the curvature of the geometry. The high curvature regions ar...
void extendVelocity(const MInt set)
void initializeGField()
Initializes the solver values with the values of the undisturbed flow The values are given by the pro...
void computeBodyPropertiesForced(MInt returnMode, MFloat *bodyData, MInt body, MFloat time, MBool printPosition=false)
returns a specific property of the specifuec body used to provide a unique function for both level-se...
void determineMinMaxMeanInterfacePosition()
void initializeGControlPoint()
this function is used to initialize the control point.
MFloat firstOrderEikonalSolver(MInt cellListSize, MInt maxIterations, MInt set)
void computeLevelSetRHS()
void initializeIntegrationScheme()
void computeZeroLevelSetArcLength()
MBool inCell(MInt cellId, MFloat *point)
void allocateLevelSetMemory()
void computeExtensionVelocityGEQUPVMarksteinOpt(MFloat *FfluidDensity, MInt set)
void determineMinMaxMeanRegionInterfacePosition(MFloat xRegN, MFloat xRegP, MFloat yRegN, MFloat yRegP, MInt set)
MInt hyperbolicExtensionOpt(MFloat *q, MInt *cellList, MInt cellListSize, MFloat convergenceCriterion, MInt set)
void setGCellBndryProperty()
void levelSetReinitialization(MInt mode=1)
void updateLowerGridLevels(MInt mode=-1)
void levelSetRestriction()
void levelSetGapCorrect()
void initializeCollectedLevelSet(MInt mode)
void resetOutsideCells(MInt mode=-1)
void exchangeLs(MFloat *, MInt, MInt)
MBool levelSetReinitializationTrigger()
void applyLevelSetBoundaryConditions()
void computeNormalVectorsPeriodic()
void levelSetHighOrderConstrainedReinitialization(MInt methodId, MInt startSet, MInt endSet, MInt gapMode)
void computeCurvaturePeriodic()
void exchangeBuffersGlobal(T *sendBuffer, T *receiveBuffer, MInt *, MInt *, MInt *, MInt *, MInt, MInt offset=1)
MInt determineLevelSetSignFromSTL(MFloat *target, MInt set)
this function checks if the "target" coordinates is inside(return 1) or outside (return -1) STL and r...
void reBuildCollectedLevelSet(MInt mode)
void levelSetGapRecorrect()
MFloat interpolateLevelSet(MInt *interpolationCells, MFloat *point, MInt referenceSet)
void readLevelSetProperties()
MFloat computeDistanceFromSTL(MFloat *target, MInt *closestElement, MFloat *closestPoint, MInt set, MFloat sphereRadiusFactor=F5)
MFloat fifthOrderEikonalSolver(MInt cellListSize, MInt maxIterations, MInt *crCells, MInt noCRCells, MFloat *factors, MInt crMode, MInt set)
void setUpLevelSetInterpolationStencil(MInt cellId, MInt *interpolationCells, MInt position)
void updateBndryCellList()
void buildCollectedLevelSet(MInt mode=1)
void allocateRotatingLs()
void resetOldOutsideCells()
LsCartesianSolver(MInt, const MBool *, GridProxy &gridProxy_, Geom &geometry_, const MPI_Comm comm)
MInt getContainingCell(MFloat *point)
void maintainOuterBandLayers(MInt order, MInt startSet, MInt endSet)
MBool levelSetSolver()
void setChildRegions(MInt cellId, MInt region)
void reinitBand(MInt startSet, MInt endSet)
void getContainingCellFromNeighbor(MInt body, MInt cellId, MFloat *xCoord, MFloat *xOld)
void constructGFieldFromSTL(MInt ConstructFlag)
Used for initializing G field into the domain. ConstructFlag == 0: only reinitialization part will be...
void setBandNewArrivals(MInt computingSet=-1)
MBool regridLevelSet()
void determineG0Cells(MInt computingSet=-1)
void determineBandCells(MInt mode=-1)
void levelSetConstrainedReinitialization(MInt methodId, MInt startSet, MInt endSet, MInt gapMode)
MFloat interpolateOldLevelSet(MInt *interpolationCells, MFloat *point, MInt referenceSet)
void computeNormalVectorsAtFront()
void computeNormalVectors(MInt mode=-1)
void initSolver() override
void computeGCellTimeStep()
MBool localGapCellsExist()
This class is a ScratchSpace.
Definition: scratch.h:758
Parent class of all solvers This class is the base for all solvers. I.e. all solver class (e....
Definition: solver.h:29
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ CR2
Definition: enums.h:192
@ HCR2_FULLREINIT
Definition: enums.h:196
@ HCR2_LIMITED
Definition: enums.h:195
@ HCR1
Definition: enums.h:193
@ no
Definition: enums.h:208
@ HCR2
Definition: enums.h:194
@ CR1
Definition: enums.h:191
@ BACKWARDS_PAR
Definition: enums.h:220
@ ROTATING_LS
Definition: enums.h:221
@ SYMMETRIC
Definition: enums.h:226
@ STL
Definition: enums.h:365
@ MAIA_SEMI_LAGRANGE_LEVELSET_LB
Definition: enums.h:68
@ MAIA_RUNGE_KUTTA_MB_SEMI_LAGRANGE_LEVELSET
Definition: enums.h:71
@ MAIA_LEVELSET_SURFACE
Definition: enums.h:70
@ MAIA_SEMI_LAGRANGE_LEVELSET
Definition: enums.h:67
@ COMBUSTION
Definition: enums.h:276
@ LS_SOLVER
Definition: enums.h:280
@ LEVELSETMB
Definition: enums.h:275
@ LEVELSET
Definition: enums.h:274
@ LS_RANS
Definition: enums.h:277
@ LEVELSET_LB
Definition: enums.h:281
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
constexpr Real POW4(const Real x)
Definition: functions.h:127
constexpr Real POW3(const Real x)
Definition: functions.h:123
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 globalTimeStep
void printAllocatedMemory(const MLong oldAllocatedBytes, const MString &solverName, const MPI_Comm comm)
Prints currently allocated memory.
InfoOutFile m_log
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
int64_t MLong
Definition: maiatypes.h:64
bool MBool
Definition: maiatypes.h:58
MInt id
Definition: maiatypes.h:71
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Isend
int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Irecv
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
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
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Send
void const MInt cellId
Definition: collector.h:239
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125
MFloat crankAngle(const MFloat time, const MFloat Strouhal, const MFloat offset, const MInt mode)
help-function for engine calculations which returns the crank-angle for a given time,...
Definition: maiamath.h:506
Namespace for auxiliary functions/classes.
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)
Definition: pointbox.h:54
Definition: contexttypes.h:19
define array structures