MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
dgcartesianbcacousticperturbrbc.h
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#ifndef DGBOUNDARYCONDITIONACOUSTICPERTURBRBC_H_
8#define DGBOUNDARYCONDITIONACOUSTICPERTURBRBC_H_
9
10#include "UTIL/timer.h"
12
13template <MInt nDim>
14class DgBcAcousticPerturbRBC final : public DgBoundaryCondition<nDim, DgSysEqnAcousticPerturb<nDim>> {
15 // Typedefs
16 public:
19 using Base::begin;
24 using Base::dt;
25 using Base::elements;
26 using Base::end;
27 using Base::flux;
30 using Base::helements;
31 using Base::id;
35 using Base::isRestart;
37 using Base::maxPolyDeg;
40 using Base::solver;
42 using Base::surfaces;
43 using Base::sysEqn;
45 using typename Base::SolverType;
46 using typename Base::SysEqn;
47
48 // Methods
49 DgBcAcousticPerturbRBC(SolverType& solver_, MInt bcId) : Base(solver_, bcId) {
50 // Create timers
51 // @ansgar TODO labels:DG,TIMERS this creates new timers every time DLB is performed and new RBCs are created
52 initTimers();
53 }
55 // Free allocated memory
57 // Stop the class timer
58 RECORD_TIMER_STOP(m_timers[Timers::Class]);
59 }
60
61 MString name() const override { return "radiation boundary condition"; }
62
63 void init() override;
64
65 void initTimers();
66
67 void apply(const MFloat time) override;
68
69 void applyAtSurface(const MInt surfaceId, const MFloat NotUsed(time));
70
71 void calcFlux(const MFloat* nodeVars, const MFloat* q, const MInt noNodes1D, MFloat* flux_) const;
72
73 void calcRiemann(const MFloat* nodeVarsL,
74 const MFloat* nodeVarsR,
75 const MFloat* stateL,
76 const MFloat* stateR,
77 const MInt noNodes1D,
78 const MInt dirId,
79 MFloat* flux_) const;
80
81 void calcSource(const MFloat* nodeVars, const MFloat* u, const MInt noNodes1D, const MFloat t, const MFloat* x,
82 MFloat* src) const;
83
84 MInt noRestartVars() const override { return Base::SysEqn::noVars(); };
85 MInt getLocalNoNodes() const override;
86 MString restartVarName(const MInt id_) const override;
87 void setRestartVariable(const MInt id_, const MFloat* const data) override;
88 void getRestartVariable(const MInt id_, MFloat* const data) const override;
89
90 MInt noBcElements() const override { return m_rbElements.size(); };
91 MBool hasBcElement(const MInt elementId) const override;
92
94 // Number of variables in BC
95 MInt noCellDataDlb() const override { return noRestartVars(); }
96
97 // Data types of variables
98 MInt cellDataTypeDlb(const MInt NotUsed(dataId)) const override {
99 return MFLOAT; // Note: assumes there are not MInt to communicate
100 }
101
102 // Data size of variables
103 MInt cellDataSizeDlb(const MInt dataId, const MInt cellId) const override;
104
105 // Get BC solution data
106 void getCellDataDlb(const MInt dataId, MFloat* const data) const override { getRestartVariable(dataId, data); }
107
108 // Set BC solution data
109 void setCellDataDlb(const MInt dataId, const MFloat* const data) override { setRestartVariable(dataId, data); }
110
111 private:
112 void calcFlux1D(const MFloat* nodeVars, const MFloat* q, const MInt noNodes1D, const MInt dirId, MFloat* flux_) const;
113
114 void calcElementNodeVars();
115 void calcSurfaceNodeVars();
116 void calcNodeVars(const MFloat* pos, const MFloat* nodeVarsAPE, MFloat* nodeVars);
117
118 // Member variables
119 private:
123
124 // Element variables
125 // Collector of rb-elements
127
128 // Store corresponding rb-element id for each boundary surface
129 std::vector<MInt> m_rbElementId;
130 // Store corresponding rb-surface id for each boundary surface
131 std::vector<MInt> m_rbSurfaceId;
132
133 // Store corresponding element id for each rb-element
134 std::vector<MInt> m_elementId;
135 // Store corresponding surface id for each rb-surface
136 std::vector<MInt> m_surfaceId;
137
138 // Surface variables
139 // Collector of rb-surfaces
141
142 // Store additional rb-boundary surface ids (with a different bcId) and their
143 // corresponding rb-element
144 std::vector<std::pair<MInt, MInt>> m_addBndrySrfcIds;
145
146 // h-refinement
147 // Collector of elements
149
150 // Store solution of RBC system
151 MFloat** m_rbSolution = nullptr;
152
153 // Total number of values (DOF * noVars * noRbElements)
155
156 // Current Runge Kutta stage
158
159 // RBC reference position which should be close to the acoustic sources
160 std::array<MFloat, MAX_SPACE_DIMENSIONS> m_rbcReferencePos{};
161
162 // Store if RBC node variables are initialized and initial condition is set
164
165 // Number of node variables
166 static const constexpr MInt s_noNodeVars = nDim + 2;
167
168 // Timing
169 struct Timers {
170 enum {
171 // Timer group and main timer
174
175 // Regular (method-specific timers)
186
187 // Counter
188 _count
189 };
190 };
191 std::array<MInt, Timers::_count> m_timers;
192};
193
194
204template <MInt nDim>
206 TRACE();
207 RECORD_TIMER_START(m_timers[Timers::Init]);
208
222 for(MInt i = 0; i < nDim; i++) {
223 m_rbcReferencePos[i] = Context::getSolverProperty<MFloat>("rbcReferencePos", solver().solverId(), AT_, i);
224 }
225
226 // Element mapping: elementId -> rbElementId
227 std::map<MInt, MInt> elementMap;
228 MInt noRbElements = 0;
229
230 // Collect rb-elements to be created
231 // Loop over boundary and check internal elements
232 for(MInt srfcId = begin(); srfcId < end(); srfcId++) {
233 const MInt internalSide = surfaces().internalSideId(srfcId);
234 const MInt elementId = surfaces().nghbrElementIds(srfcId, internalSide);
235
236 // Check if rb-element id already exists for current element
237 const auto it = elementMap.find(elementId);
238 if(it != elementMap.end()) {
239 // rb-element already exists, store its id for current boundary surface
240 m_rbElementId.push_back(it->second);
241 continue;
242 }
243
244 // Determine new rb-element id
245 const MInt rbElementId = noRbElements++;
246
247 // Store mapping: elementId -> rbElementId
248 elementMap[elementId] = rbElementId;
249
250 // Store rb-element id for current boundary surface
251 m_rbElementId.push_back(rbElementId);
252 }
253
254 MInt maxNoSurfaces = 2 * nDim * noRbElements;
255 MInt noHRbElements = 0;
256 ScratchSpace<MInt> hRbElementIds(noRbElements, AT_, "hRbElementIds");
257
258 m_elementId.clear();
259 // Store element ids in ascending order, create rb-elements in this order and
260 // check for h-refinement
261 for(const auto& it : elementMap) {
262 const MInt elementId = it.first;
263 m_elementId.push_back(elementId);
264
265 // Check if h-rb-element is needed, store rb-element id
266 const MInt cellId = elements().cellId(elementId);
267 if(needHElementForCell(cellId)) {
268 hRbElementIds[noHRbElements] = it.second;
269 noHRbElements++;
270
271 // Upper bound for additional surfaces needed by the h-refinement
272 maxNoSurfaces += 2 * nDim * (2 * (nDim - 1) - 1);
273 }
274 }
275
276 // Allocate rb-elements
277 m_rbElements.maxPolyDeg(maxPolyDeg());
278 m_rbElements.maxNoNodes1D(maxNoNodes1D());
279 m_rbElements.noNodeVars(s_noNodeVars);
280 m_rbElements.reset(noRbElements);
281
282 // Allocate rb-surfaces
283 m_rbSurfaces.maxPolyDeg(maxPolyDeg());
284 m_rbSurfaces.maxNoNodes1D(maxNoNodes1D());
285 m_rbSurfaces.noNodeVars(s_noNodeVars);
286 m_rbSurfaces.reset(maxNoSurfaces);
287
288 // Allocate h-rb-elements
289 m_hRbElements.reset(noHRbElements);
290
291 // Create rb-elements
292 for(MInt rbId = 0; rbId < noRbElements; rbId++) {
293 m_rbElements.append();
294
295 // Copy member variables from elements to rb-elements
296 m_rbElements.copy(elements(), m_elementId[rbId], rbId);
297 }
298
299 // Create h-rb-elements
300 for(MInt hRbId = 0; hRbId < noHRbElements; hRbId++) {
301 m_hRbElements.append();
302
303 // Set corresponding rb-element id
304 m_hRbElements.elementId(hRbId) = hRbElementIds[hRbId];
305 }
306
307 // Create rb-surfaces
308 m_rbSurfaceId.assign(end() - begin() + 1, -1);
309 std::map<MInt, MInt> srfcMap;
310 const MInt noDirs = 2 * nDim;
311 // Iterate over rb-elements
312 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
313 const MInt eId = m_elementId[rbId]; // Element id
314
315 // Loop over all directions
316 for(MInt dir = 0; dir < noDirs; dir++) {
317 const MInt sId = elements().surfaceIds(eId, dir);
318
319 const MInt nghbrSideId = dir % 2;
320 const MInt elementSideId = (nghbrSideId + 1) % 2;
321
322 // Check if rb-surface is already created
323 const auto srfcMapIt = srfcMap.find(sId);
324 if(srfcMapIt == srfcMap.end()) { // rb-surface does not exist
325 const MInt rbSurfaceId = m_rbSurfaces.size();
326 m_rbSurfaces.append();
327
328 // Store mapping: surfaceId -> rbSurfaceId
329 srfcMap[sId] = rbSurfaceId;
330
331 // Store surface id
332 m_surfaceId.push_back(sId);
333
334 // Store rb-surface ids only for boundary surfaces
335 if(begin() <= sId && sId < end()) {
336 m_rbSurfaceId[sId - begin()] = rbSurfaceId;
337 }
338
339 // Store rb-surface id in rb-element
340 m_rbElements.surfaceIds(rbId, dir) = rbSurfaceId;
341
342 // Copy variables of surface to rb-surface
343 m_rbSurfaces.copy(surfaces(), sId, rbSurfaceId);
344
345 // Store neighboring rb-element ids in rb-surface
346 m_rbSurfaces.nghbrElementIds(rbSurfaceId, elementSideId) = rbId;
347 m_rbSurfaces.nghbrElementIds(rbSurfaceId, nghbrSideId) = -1;
348
349 const MInt internalSide = surfaces().internalSideId(sId);
350
351 // Check for boundary surface which is not belonging to the RBC boundary
352 // Note: Such boundary surfaces are assumed to belong also to a
353 // radiation boundary, i.e. the RBC surface flux is computed with the
354 // prolonged RBC solution as inner and outer state
355 // TODO labels:DG other boundary conditions (e.g. solid wall)
356 if(internalSide != -1 && (sId < begin() || sId >= end()) && !isMpiSurface(sId)) {
357 // Store the rb-surface id and also the corresponding rb-element id
358 // such that later the RBC-solution can also be prolonged to this
359 // rb-surface
360 m_addBndrySrfcIds.push_back(std::make_pair(rbSurfaceId, rbId));
361 }
362 } else { // rb-surface exists, store id in rb-element
363 const MInt rbSurfaceId = srfcMapIt->second;
364 m_rbElements.surfaceIds(rbId, dir) = rbSurfaceId;
365
366 // Store neighboring rb-element id in rb-surface
367 m_rbSurfaces.nghbrElementIds(rbSurfaceId, elementSideId) = rbId;
368 }
369 }
370 }
371
372 // Store h-refined surface ids in h-rb-elements, create missing surfaces
373 const MInt noSurfs = 2 * (nDim - 1);
374 for(MInt hRbId = 0; hRbId < noHRbElements; hRbId++) {
375 const MInt rbId = m_hRbElements.elementId(hRbId);
376 const MInt eId = m_elementId[rbId];
377 const MInt hId = getHElementId(eId);
378
379 for(MInt dir = 0; dir < 2 * nDim; dir++) {
380 const MInt side = 1 - dir % 2;
381 const MInt oppositeSide = dir % 2;
382
383 for(MInt hSurfId = 0; hSurfId < noSurfs; hSurfId++) {
384 // Id of h-refined surface
385 const MInt sId = helements().hrefSurfaceIds(hId, dir, hSurfId);
386
387 MInt hSId = -1;
388 const auto it = srfcMap.find(sId);
389
390 // For an existing h-refined surface check if a rb-surface exists
391 if(sId != -1 && it != srfcMap.end()) {
392 hSId = it->second;
393
394 // (h-)rb-surface exists, just store the neighboring rb-element id
395 m_rbSurfaces.nghbrElementIds(hSId, side) = rbId;
396 } else if(sId != -1 && hSId == -1) {
397 // rb-surface does not exist, create it if there is a h-refined
398 // surface. This covers the cases of h-mpi surfaces and h-refinement
399 // parallel to the boundary in the interior of the domain
400 hSId = m_rbSurfaces.size();
401 m_rbSurfaces.append();
402
403 // Store surface id
404 m_surfaceId.push_back(sId);
405
406 // Copy variables of surface to rb-surface
407 m_rbSurfaces.copy(surfaces(), sId, hSId);
408
409 // Store neighboring rb-element ids in rb-surface
410 m_rbSurfaces.nghbrElementIds(hSId, side) = rbId;
411 m_rbSurfaces.nghbrElementIds(hSId, oppositeSide) = -1;
412 }
413
414 // Store h-rb-surface id in h-rb-element
415 // -1 if there is no h-refinement in this direction
416 m_hRbElements.hrefSurfaceIds(hRbId, dir, hSurfId) = hSId;
417 }
418 }
419 }
420
421 // Allocate space for RBC solution
422 const MInt dataSize = Base::SysEqn::noVars() * ipow(maxNoNodes1D(), nDim);
423 mDeallocate(m_rbSolution);
424 if(noRbElements > 0) {
425 mAlloc(m_rbSolution, noRbElements, dataSize, "m_rbSolution", F0, AT_);
426 }
427 m_internalDataSize = noRbElements * dataSize;
428
429 RECORD_TIMER_STOP(m_timers[Timers::Init]);
430}
431
432
437template <MInt nDim>
439 TRACE();
440
441 // Create timer group & timer for solver, and start the timer
442 NEW_TIMER_GROUP_NOCREATE(m_timers[Timers::TimerGroup],
443 "DgBcAcousticPerturbRBC (solverId = " + std::to_string(solver().solverId())
444 + ", bcId = " + std::to_string(id()) + ")");
445 NEW_TIMER_NOCREATE(m_timers[Timers::Class], "total object lifetime", m_timers[Timers::TimerGroup]);
446 RECORD_TIMER_START(m_timers[Timers::Class]);
447
448 // Create regular solver-wide timers
449 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Init], "init", m_timers[Timers::Class]);
450
451 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Apply], "apply", m_timers[Timers::Class]);
452 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::InitializeVars], "initializeVars", m_timers[Timers::Apply]);
453 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::CopySurfaceVars], "copySurfaceVars", m_timers[Timers::Apply]);
454 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Prolong], "prolong", m_timers[Timers::Apply]);
455 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::TimeDeriv], "timeDeriv", m_timers[Timers::Apply]);
456 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::RungeKuttaStep], "RungeKuttaStep", m_timers[Timers::Apply]);
457 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ApplyAtSurface], "applyAtSurface", m_timers[Timers::Apply]);
458
459 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SetRestartVars], "setRestartVars", m_timers[Timers::Class]);
460 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::GetRestartVars], "getRestartVars", m_timers[Timers::Class]);
461}
462
463
479template <MInt nDim>
481 using namespace maia::dg::interpolation;
482 TRACE();
483
484 // Nothing to be done if there are no RBC elements
485 if(m_rbElements.size() == 0) {
486 return;
487 }
488
489 RECORD_TIMER_START(m_timers[Timers::Apply]);
490
491 // 0. Initialize node variables and set initial condition if not already done
492 const MInt* const noNodes = &m_rbElements.noNodes1D(0);
493 if(!m_isInitialized) {
494 RECORD_TIMER_START(m_timers[Timers::InitializeVars]);
495
496 // Set initial condition (same as for APE)
497 if(!isRestart()) {
498 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
499 const MInt eId = m_elementId[rbId];
500 const MInt noNodes1D = noNodes[rbId];
501 const MInt noNodesXD = ipow(noNodes1D, nDim);
502 const MInt dataSize = noNodesXD * Base::SysEqn::noVars();
503
504 // Copy element variables to rb-element
505 std::copy_n(&elements().variables(eId), dataSize, &m_rbElements.variables(rbId));
506 }
507 }
508
509 // Copy APE nodeVars to outer state of boundary surfaces
510 for(MInt srfcId = begin(); srfcId < end(); srfcId++) {
511 const MInt noNodes1D = surfaces().noNodes1D(srfcId);
512 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
513 const MInt noNodesXD = noNodes1D * noNodes1D3;
514 const MInt internalSide = surfaces().internalSideId(srfcId);
515 const MInt outerSide = (internalSide + 1) % 2;
516
517 // Copy node vars to outer surface state
518 std::copy_n(&surfaces().nodeVars(srfcId, internalSide),
519 noNodesXD * Base::SysEqn::noNodeVars(),
520 &surfaces().nodeVars(srfcId, outerSide));
521 }
522
523 // Also copy APE node vars to outer state of additional boundary surfaces
524 const MInt noAddBcIds = m_addBndrySrfcIds.size();
525 for(MInt sId = 0; sId < noAddBcIds; sId++) {
526 const MInt rbSrfcId = m_addBndrySrfcIds[sId].first;
527 const MInt srfcId = m_surfaceId[rbSrfcId];
528
529 const MInt noNodes1D = surfaces().noNodes1D(srfcId);
530 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
531 const MInt noNodesXD = noNodes1D * noNodes1D3;
532 const MInt internalSide = surfaces().internalSideId(srfcId);
533 const MInt outerSide = (internalSide + 1) % 2;
534
535 // Copy node vars to outer surface state
536 std::copy_n(&surfaces().nodeVars(srfcId, internalSide),
537 noNodesXD * Base::SysEqn::noNodeVars(),
538 &surfaces().nodeVars(srfcId, outerSide));
539 }
540
541 // Calculate RBC node variables
542 calcElementNodeVars();
543 calcSurfaceNodeVars();
544
545 // Set initial Runge Kutta stage
546 m_rkStage = 0;
547
548 m_isInitialized = true;
549
550 RECORD_TIMER_STOP(m_timers[Timers::InitializeVars]);
551 }
552
553 // 1. Copy surface variables to rb-surfaces for surface flux computation
554 // For boundary surfaces: variables are later overwritten with prolonged
555 // rb-solutions
556 RECORD_TIMER_START(m_timers[Timers::CopySurfaceVars]);
557
558 for(MInt rbSId = 0; rbSId < m_rbSurfaces.size(); rbSId++) {
559 const MInt sId = m_surfaceId[rbSId];
560
561 const MInt noNodesXD = ipow(maxNoNodes1D(), nDim - 1);
562 const MInt dataSize = noNodesXD * Base::SysEqn::noVars();
563
564 std::copy_n(&surfaces().variables(sId, 0), dataSize, &m_rbSurfaces.variables(rbSId, 0));
565 std::copy_n(&surfaces().variables(sId, 1), dataSize, &m_rbSurfaces.variables(rbSId, 1));
566 }
567
568 RECORD_TIMER_STOP(m_timers[Timers::CopySurfaceVars]);
569
570 // 2.1 Prolong RBC solution to boundary surfaces
571 RECORD_TIMER_START(m_timers[Timers::Prolong]);
572
573 for(MInt srfcId = begin(); srfcId < end(); srfcId++) {
574 // Get corresponding rb-element id for boundary surface
575 const MInt rbId = m_rbElementId[srfcId - begin()];
576
577 const MInt polyDeg = m_rbElements.polyDeg(rbId);
578 const MInt noNodes1D = m_rbElements.noNodes1D(rbId);
579 const MInt orientation = surfaces().orientation(srfcId);
580 const MInt internalSide = surfaces().internalSideId(srfcId);
581 const MInt outerSide = (internalSide + 1) % 2;
582 const MInt dir = 2 * orientation + outerSide;
583
584 // Prolong to outer state of boundary surface
585 MFloat* src = &m_rbElements.variables(rbId);
586 MFloat* dest = &surfaces().variables(srfcId, outerSide);
587
588 if(integrationMethod() == DG_INTEGRATE_GAUSS) {
589 prolongToFaceGauss<nDim, Base::SysEqn::noVars()>(src, dir, noNodes1D,
590 &interpolation(polyDeg, noNodes1D).m_LFace[0][0],
591 &interpolation(polyDeg, noNodes1D).m_LFace[1][0], dest);
592 } else if(integrationMethod() == DG_INTEGRATE_GAUSS_LOBATTO) {
593 prolongToFaceGaussLobatto<nDim, Base::SysEqn::noVars()>(src, dir, noNodes1D, dest);
594 }
595
596 const MInt rbSId = m_rbSurfaceId[srfcId - begin()];
597 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
598 const MInt noNodesXD = noNodes1D * noNodes1D3;
599 const MInt dataSize = noNodesXD * Base::SysEqn::noVars();
600
601 // Copy prolonged rbc solution to rb boundary surfaces
602 std::copy_n(dest, dataSize, &m_rbSurfaces.variables(rbSId, 0));
603 std::copy_n(dest, dataSize, &m_rbSurfaces.variables(rbSId, 1));
604 }
605
606 // 2.2 Prolong RBC solution to additional boundary surfaces
607 const MInt noAddBcIds = m_addBndrySrfcIds.size();
608 for(MInt srfcId = 0; srfcId < noAddBcIds; srfcId++) {
609 const MInt rbSrfcId = m_addBndrySrfcIds[srfcId].first;
610 const MInt rbId = m_addBndrySrfcIds[srfcId].second;
611
612 const MInt polyDeg = m_rbElements.polyDeg(rbId);
613 const MInt noNodes1D = m_rbElements.noNodes1D(rbId);
614 const MInt orientation = m_rbSurfaces.orientation(rbSrfcId);
615 const MInt internalSide = m_rbSurfaces.internalSideId(rbSrfcId);
616 const MInt outerSide = (internalSide + 1) % 2;
617 const MInt dir = 2 * orientation + outerSide;
618
619 // Prolong to left state of boundary surface
620 MFloat* src = &m_rbElements.variables(rbId);
621 MFloat* dest = &m_rbSurfaces.variables(rbSrfcId, 0);
622
623 if(integrationMethod() == DG_INTEGRATE_GAUSS) {
624 prolongToFaceGauss<nDim, Base::SysEqn::noVars()>(src, dir, noNodes1D,
625 &interpolation(polyDeg, noNodes1D).m_LFace[0][0],
626 &interpolation(polyDeg, noNodes1D).m_LFace[1][0], dest);
627 } else if(integrationMethod() == DG_INTEGRATE_GAUSS_LOBATTO) {
628 prolongToFaceGaussLobatto<nDim, Base::SysEqn::noVars()>(src, dir, noNodes1D, dest);
629 }
630
631 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
632 const MInt dataSize = noNodes1D * noNodes1D3 * Base::SysEqn::noVars();
633
634 // Copy prolonged left state to right state
635 std::copy_n(&m_rbSurfaces.variables(rbSrfcId, 0), dataSize, &m_rbSurfaces.variables(rbSrfcId, 1));
636 }
637
638 RECORD_TIMER_STOP(m_timers[Timers::Prolong]);
639
640 // 3. Solve RBC system
641 RECORD_TIMER_START(m_timers[Timers::TimeDeriv]);
642
643 // Reset rbc-rhs
644 resetBuffer(m_internalDataSize, &m_rbElements.rightHandSide(0));
645
646 // Store rbc-solution and copy element variables to rb-elements for flux
647 // computation
648 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
649 const MInt eId = m_elementId[rbId];
650 const MInt noNodes1D = noNodes[rbId];
651 const MInt noNodesXD = ipow(noNodes1D, nDim);
652 const MInt dataSize = noNodesXD * Base::SysEqn::noVars();
653
654 // Store rb-element variables in m_rbSolution
655 std::copy_n(&m_rbElements.variables(rbId), dataSize, m_rbSolution[rbId]);
656
657 // Copy element variables to rb-element
658 std::copy_n(&elements().variables(eId), dataSize, &m_rbElements.variables(rbId));
659 }
660
661 // Calculate volume integral (with APE variables)
662 calcVolumeIntegral(m_rbElements.size(), m_rbElements, *this);
663
664 // Calculate surface fluxes
665 // Inner fluxes are computed with the APE variables on the surfaces
666 // Boundary fluxes use the prolonged rbc solutions for both the left and right
667 // state
668 calcRegularSurfaceFlux(0, m_rbSurfaces.size(), m_rbSurfaces, *this);
669
670 // Calculate surface integral
671 calcSurfaceIntegral(0, m_rbElements.size(), m_rbElements, m_rbSurfaces, m_hRbElements, m_hRbElements.size());
672
673 // Apply jacobian
674 applyJacobian(m_rbElements.size(), m_rbElements);
675
676 // Calculate source terms
677 calcSourceTerms(time, m_rbElements.size(), m_rbElements, *this);
678
679 // Copy rbc-solutions back to rb-elements for time integration
680 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
681 const MInt noNodes1D = noNodes[rbId];
682 const MInt noNodesXD = ipow(noNodes1D, nDim);
683 const MInt dataSize = noNodesXD * Base::SysEqn::noVars();
684
685 std::copy_n(m_rbSolution[rbId], dataSize, &m_rbElements.variables(rbId));
686 }
687
688 RECORD_TIMER_STOP(m_timers[Timers::TimeDeriv]);
689
690 // Perform rk substep
691 RECORD_TIMER_START(m_timers[Timers::RungeKuttaStep]);
692 subTimeStepRk(dt(), m_rkStage, m_internalDataSize, &m_rbElements.rightHandSide(0), &m_rbElements.variables(0),
693 &m_rbElements.timeIntStorage(0));
694
695 // Define the number of Rk-steps according to the Scheme being used
696 if(timeIntegrationScheme() == DG_TIMEINTEGRATION_CARPENTER_4_5) {
697 m_rkStage = (m_rkStage + 1) % 5;
698 } else if(timeIntegrationScheme() == DG_TIMEINTEGRATION_TOULORGEC_4_8) {
699 m_rkStage = (m_rkStage + 1) % 8;
700 } else if(timeIntegrationScheme() == DG_TIMEINTEGRATION_NIEGEMANN_4_14) {
701 m_rkStage = (m_rkStage + 1) % 14;
702 } else if(timeIntegrationScheme() == DG_TIMEINTEGRATION_NIEGEMANN_4_13) {
703 m_rkStage = (m_rkStage + 1) % 13;
704 } else if(timeIntegrationScheme() == DG_TIMEINTEGRATION_TOULORGEC_3_7) {
705 m_rkStage = (m_rkStage + 1) % 7;
706 } else if(timeIntegrationScheme() == DG_TIMEINTEGRATION_TOULORGEF_4_8) {
707 m_rkStage = (m_rkStage + 1) % 8;
708 }
709
710 RECORD_TIMER_STOP(m_timers[Timers::RungeKuttaStep]);
711
712 // 4. Apply boundary condition
713 RECORD_TIMER_START(m_timers[Timers::ApplyAtSurface]);
715 RECORD_TIMER_STOP(m_timers[Timers::ApplyAtSurface]);
716
717 RECORD_TIMER_STOP(m_timers[Timers::Apply]);
718}
719
720
725template <MInt nDim>
726void DgBcAcousticPerturbRBC<nDim>::applyAtSurface(const MInt surfaceId, const MFloat NotUsed(time)) {
727 // TRACE();
728
729 MFloat* nodeVarsL = &surfaces().nodeVars(surfaceId, 0);
730 MFloat* nodeVarsR = &surfaces().nodeVars(surfaceId, 1);
731 MFloat* stateL = &surfaces().variables(surfaceId, 0);
732 MFloat* stateR = &surfaces().variables(surfaceId, 1);
733 const MInt noNodes1D = surfaces().noNodes1D(surfaceId);
734 const MInt dirId = surfaces().orientation(surfaceId);
735
736 // The boundary state contains the prolonged rbc-solution and the same node
737 // variables as the inner state
738 MFloat* f = flux(surfaceId);
739 sysEqn().calcRiemann(nodeVarsL, nodeVarsR, stateL, stateR, noNodes1D, dirId, f);
740}
741
742
750template <MInt nDim>
752 const MFloat* q,
753 const MInt noNodes1D,
754 MFloat* flux_) const {
755 // TRACE();
756
757 const MInt noVars = Base::SysEqn::noVars();
758 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
759 const MFloatTensor U(const_cast<MFloat*>(q), noNodes1D, noNodes1D, noNodes1D3, noVars);
760 const MFloatTensor coeff(const_cast<MFloat*>(nodeVars), noNodes1D, noNodes1D, noNodes1D3, s_noNodeVars);
761
762 MFloatTensor f(flux_, noNodes1D, noNodes1D, noNodes1D3, nDim, noVars);
763
764 // The following flux equations are calculated here (if 2D, consider all
765 // z-components to be zero and sin(theta)=1):
766 // vg: speed of wave propagation
767 // theta, phi: angles in cylindrical coordinates
768
769 // Flux in x-direction:
770 // f1 = vg*sin(theta)*cos(phi)
771 // f_x(CV[u]) = f1*u
772 // f_x(CV[v]) = f1*v
773 // f_x(CV[w]) = f1*w
774 // f_x(CV[p]) = f1*p
775
776 // Flux in y-direction:
777 // f2 = vg*sin(theta)*sin(phi)
778 // f_y(CV[u]) = f2*u
779 // f_y(CV[v]) = f2*v
780 // f_y(CV[w]) = f2*w
781 // f_y(CV[p]) = f2*p
782
783 // Flux in z-direction:
784 // f3 = vg*cos(theta)
785 // f_z(CV[u]) = f3*u
786 // f_z(CV[v]) = f3*v
787 // f_z(CV[w]) = f3*w
788 // f_z(CV[p]) = f3*p
789
790 for(MInt i = 0; i < noNodes1D; i++) {
791 for(MInt j = 0; j < noNodes1D; j++) {
792 for(MInt k = 0; k < noNodes1D3; k++) {
793 for(MInt d = 0; d < nDim; d++) {
794 for(MInt var = 0; var < noVars; var++) {
795 f(i, j, k, d, var) = coeff(i, j, k, d) * U(i, j, k, var);
796 }
797 }
798 }
799 }
800 }
801}
802
803
812template <MInt nDim>
813void DgBcAcousticPerturbRBC<nDim>::calcFlux1D(const MFloat* nodeVars, const MFloat* q, const MInt noNodes1D,
814 const MInt dirId, MFloat* flux_) const {
815 // TRACE();
816
817 const MInt noVars = Base::SysEqn::noVars();
818 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
819 const MFloatTensor U(const_cast<MFloat*>(q), noNodes1D, noNodes1D3, noVars);
820 const MFloatTensor coeff(const_cast<MFloat*>(nodeVars), noNodes1D, noNodes1D3, s_noNodeVars);
821 MFloatTensor f(flux_, noNodes1D, noNodes1D3, noVars);
822
823 for(MInt i = 0; i < noNodes1D; i++) {
824 for(MInt j = 0; j < noNodes1D3; j++) {
825 for(MInt var = 0; var < noVars; var++) {
826 f(i, j, var) = coeff(i, j, dirId) * U(i, j, var);
827 }
828 }
829 }
830}
831
832
842template <MInt nDim>
844 const MFloat* u,
845 const MInt noNodes1D,
846 const MFloat NotUsed(t),
847 const MFloat* NotUsed(x),
848 MFloat* src) const {
849 // TRACE();
850
851 const MInt noVars = Base::SysEqn::noVars();
852
853 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
854 MFloatTensor s(src, noNodes1D, noNodes1D, noNodes1D3, noVars);
855
856 const MFloatTensor U(const_cast<MFloat*>(u), noNodes1D, noNodes1D, noNodes1D3, noVars);
857 const MFloatTensor coeff(const_cast<MFloat*>(nodeVars), noNodes1D, noNodes1D, noNodes1D3, nDim + 2);
858
859 for(MInt i = 0; i < noNodes1D; i++) {
860 for(MInt j = 0; j < noNodes1D; j++) {
861 for(MInt k = 0; k < noNodes1D3; k++) {
862 for(MInt var = 0; var < noVars; var++) {
863 s(i, j, k, var) = coeff(i, j, k, nDim + 1) * U(i, j, k, var);
864 }
865 }
866 }
867 }
868}
869
870
878template <MInt nDim>
880 const MFloat* nodeVarsR,
881 const MFloat* stateL,
882 const MFloat* stateR,
883 const MInt noNodes1D,
884 const MInt dirId,
885 MFloat* flux_) const {
886 // TRACE();
887
888 const MInt noVars = Base::SysEqn::noVars();
889 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
890 const MFloatTensor uL(const_cast<MFloat*>(stateL), noNodes1D, noNodes1D3, noVars);
891 const MFloatTensor uR(const_cast<MFloat*>(stateR), noNodes1D, noNodes1D3, noVars);
892
893#ifndef _OPENMP
894 MFloatScratchSpace maxLambda(noNodes1D, noNodes1D3, AT_, "maxLambda");
895#else
896 MFloatTensor maxLambda(noNodes1D, noNodes1D3);
897#endif
898
899 // Left and right node variables
900 const MFloatTensor cL(const_cast<MFloat*>(nodeVarsL), noNodes1D, noNodes1D3, s_noNodeVars);
901 const MFloatTensor cR(const_cast<MFloat*>(nodeVarsR), noNodes1D, noNodes1D3, s_noNodeVars);
902
903 // Calculate maximum eigenvalue from speed of sound propagation
904 for(MInt i = 0; i < noNodes1D; i++) {
905 for(MInt j = 0; j < noNodes1D3; j++) {
906 maxLambda(i, j) = std::max(fabs(cL(i, j, nDim)), fabs(cR(i, j, nDim)));
907 }
908 }
909
910#ifndef _OPENMP
911 MFloatScratchSpace fluxL(noNodes1D, noNodes1D3, noVars, AT_, "fluxL");
912 MFloatScratchSpace fluxR(noNodes1D, noNodes1D3, noVars, AT_, "fluxR");
913#else
914 MFloatTensor fluxL(noNodes1D, noNodes1D3, noVars);
915 MFloatTensor fluxR(noNodes1D, noNodes1D3, noVars);
916#endif
917
918 // Calculate flux from left and right state
919 calcFlux1D(nodeVarsL, stateL, noNodes1D, dirId, &fluxL[0]);
920 calcFlux1D(nodeVarsR, stateR, noNodes1D, dirId, &fluxR[0]);
921
922 // Solve Riemann problem
923 MFloatTensor riemann(flux_, noNodes1D, noNodes1D3, noVars);
924 for(MInt i = 0; i < noNodes1D; i++) {
925 for(MInt j = 0; j < noNodes1D3; j++) {
926 for(MInt n = 0; n < noVars; n++) {
927 riemann(i, j, n) = 0.5 * ((fluxL(i, j, n) + fluxR(i, j, n)) - maxLambda(i, j) * (uR(i, j, n) - uL(i, j, n)));
928 }
929 }
930 }
931}
932
933
941template <MInt nDim>
943 TRACE();
944
945 // Loop over rb-elements
946 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
947 const MInt eId = m_elementId[rbId]; // Corresponding element id
948 const MInt noNodesXD = m_rbElements.noNodesXD(rbId);
949 const MFloat* coordinates = &m_rbElements.nodeCoordinates(rbId);
950
951 for(MInt pId = 0; pId < noNodesXD; pId++) {
952 calcNodeVars(&coordinates[pId * nDim],
953 &elements().nodeVars(eId) + pId * Base::SysEqn::noNodeVars(),
954 &m_rbElements.nodeVars(rbId) + pId * s_noNodeVars);
955 }
956 }
957}
958
959
967template <MInt nDim>
969 TRACE();
970
971 // Loop over rb-surfaces
972 for(MInt rbSId = 0; rbSId < m_rbSurfaces.size(); rbSId++) {
973 const MInt sId = m_surfaceId[rbSId];
974 const MFloat* coordinates = &m_rbSurfaces.nodeCoords(rbSId);
975 const MInt noNodesXD = m_rbSurfaces.noNodesXD(rbSId);
976
977 for(MInt pId = 0; pId < noNodesXD; pId++) {
978 calcNodeVars(&coordinates[pId * nDim],
979 &((&surfaces().nodeVars(sId, 0))[pId * Base::SysEqn::noNodeVars()]),
980 &((&m_rbSurfaces.nodeVars(rbSId, 0))[pId * s_noNodeVars]));
981
982 calcNodeVars(&coordinates[pId * nDim],
983 &((&surfaces().nodeVars(sId, 1))[pId * Base::SysEqn::noNodeVars()]),
984 &((&m_rbSurfaces.nodeVars(rbSId, 1))[pId * s_noNodeVars]));
985 }
986 }
987}
988
989
1010template <MInt nDim>
1011void DgBcAcousticPerturbRBC<nDim>::calcNodeVars(const MFloat* pos, const MFloat* nodeVarsAPE, MFloat* nodeVars) {
1012 // Mean speed of sound
1013 const MFloat c = nodeVarsAPE[Base::SysEqn::CV::C0];
1014
1015 IF_CONSTEXPR(nDim == 2) { // 2D
1016 const MFloat x = pos[0];
1017 const MFloat y = pos[1];
1018
1019 const MFloat x0 = m_rbcReferencePos[0];
1020 const MFloat y0 = m_rbcReferencePos[1];
1021
1022 // Inverse distance of given position and reference position
1023 const MFloat rInv = 1.0 / sqrt(POW2(x - x0) + POW2(y - y0));
1024
1025 // Orientation of given position with respect to the reference position
1026 const MFloat cosPhi = (x - x0) * rInv;
1027 const MFloat sinPhi = (y - y0) * rInv;
1028
1029 // Mean velocities
1030 const MFloat u0 = nodeVarsAPE[Base::SysEqn::CV::U0];
1031 const MFloat v0 = nodeVarsAPE[Base::SysEqn::CV::V0];
1032
1033 // Speed of wave propagation
1034 //
1035 // v_g = u0 * cos(phi) + v0 * sin(phi)
1036 // + sqrt(c^2 - (-u0 * sin(phi) + v0 * cos(phi))^2)
1037 //
1038 // c: mean sound speed
1039 // u0, v0: mean velocities
1040 // phi: angle between given position and reference position
1041 //
1042 // Reference: see 3D case
1043 const MFloat vg = u0 * cosPhi + v0 * sinPhi + sqrt(POW2(c) - POW2(-u0 * sinPhi + v0 * cosPhi));
1044
1045 // Projection of speed of wave propagation in both Cartesian coordinate
1046 // directions (coefficients for flux computation)
1047 nodeVars[0] = vg * cosPhi;
1048 nodeVars[1] = vg * sinPhi;
1049
1050 // Speed of wave propagation (needed in calcRiemann)
1051 nodeVars[2] = vg;
1052
1053 // Source term coefficient
1054 nodeVars[3] = 0.5 * vg * rInv;
1055 }
1056 else { // 3D
1057 const MFloat x = pos[0];
1058 const MFloat y = pos[1];
1059 const MFloat z = pos[2];
1060
1061 const MFloat x0 = m_rbcReferencePos[0];
1062 const MFloat y0 = m_rbcReferencePos[1];
1063 const MFloat z0 = m_rbcReferencePos[2];
1064
1065 // Inverse distance of given position and reference position
1066 const MFloat rInv = 1.0 / sqrt(POW2(x - x0) + POW2(y - y0) + POW2(z - z0));
1067
1068 // Inverse distance in x-y-plane of given position and reference position
1069 const MFloat r2Inv = 1.0 / sqrt(POW2(x - x0) + POW2(y - y0));
1070
1071 // Orientation of given position with respect to the reference position
1072 // (spherical coordinates (r, theta, phi))
1073 const MFloat cosPhi = (x - x0) * r2Inv;
1074 const MFloat sinPhi = (y - y0) * r2Inv;
1075 const MFloat cosTheta = (z - z0) * rInv;
1076 const MFloat sinTheta = sqrt(1 - POW2(cosTheta));
1077
1078 // Mean velocities
1079 const MFloat u0 = nodeVarsAPE[Base::SysEqn::CV::UU0[0]];
1080 const MFloat v0 = nodeVarsAPE[Base::SysEqn::CV::UU0[1]];
1081 const MFloat w0 = nodeVarsAPE[Base::SysEqn::CV::UU0[2]];
1082
1083 // Speed of wave propagation in radial direction
1084 const MFloat u_er = u0 * sinTheta * cosPhi + v0 * sinTheta * sinPhi + w0 * cosTheta;
1085
1086 // Speed of wave propagation in theta direction
1087 const MFloat u_et = u0 * cosTheta * cosPhi + v0 * cosTheta * sinPhi + w0 * (-sinTheta);
1088
1089 // Speed of wave propagation in phi direction
1090 const MFloat u_ep = u0 * (-sinPhi) + v0 * cosPhi;
1091
1092 // Speed of wave propagation
1093 //
1094 // v_g = u_m*e_r + sqrt(c^2 - (u_m*e_t)^2 - (u_m*e_p)^2)
1095 //
1096 // u_m: mean flow velocity vector u_m = [u0, v0, w0]'
1097 // e_r: unit vector in radial direction
1098 // e_r = [sin(phi)*cos(theta), sin(theta)*sin(phi), cos(theta)]'
1099 // e_t: unit vector in theta direction
1100 // e_t = [cos(theta)*cos(phi), cos(theta)*sin(phi), -sin(theta)]'
1101 // e_p: unit vector in phi direction
1102 // e_p = [-sin(phi), cos(phi), 0]'
1103 // c: mean sound speed
1104 //
1105 // Reference: C .Bogey, C. Bailly; Three-dimensional non-reflective boundary
1106 // conditions for acoustic simulations: far field formulation and validation
1107 // test cases, Eqns. (1) and (2)
1108 const MFloat vg = u_er + sqrt(POW2(c) - POW2(u_et) - POW2(u_ep));
1109
1110 // Projection of speed of wave propagation in all Cartesian coordinate
1111 // directions (coefficients for flux computation)
1112 nodeVars[0] = vg * sinTheta * cosPhi;
1113 nodeVars[1] = vg * sinTheta * sinPhi;
1114 nodeVars[2] = vg * cosTheta;
1115
1116 // Speed of wave propagation (needed in calcRiemann)
1117 nodeVars[3] = vg;
1118
1119 // Source term coefficient
1120 nodeVars[4] = vg * rInv;
1121 }
1122}
1123
1124
1129template <MInt nDim>
1131 TRACE();
1132
1133 MInt localNoNodes = 0;
1134 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
1135 const MInt noNodesXD = m_rbElements.noNodesXD(rbId);
1136
1137 localNoNodes += noNodesXD;
1138 }
1139
1140 return localNoNodes;
1141}
1142
1143
1150template <MInt nDim>
1152 TRACE();
1153
1154 std::stringstream varName;
1155 varName << "bc" << id() << "_" << Base::SysEqn::consVarNames(id_);
1156
1157 return varName.str();
1158}
1159
1160
1168template <MInt nDim>
1170 TRACE();
1171 RECORD_TIMER_START(m_timers[Timers::SetRestartVars]);
1172
1173 // Copy variables to rb elements (in ascending cell/element id order)
1174 MInt offset = 0;
1175 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
1176 const MInt noNodesXD = m_rbElements.noNodesXD(rbId);
1177 MFloat* const vars = &m_rbElements.variables(rbId);
1178 for(MInt n = 0; n < noNodesXD; n++) {
1179 vars[n * Base::SysEqn::noVars() + id_] = data[offset + n];
1180 }
1181
1182 offset += noNodesXD;
1183 }
1184
1185 RECORD_TIMER_STOP(m_timers[Timers::SetRestartVars]);
1186}
1187
1188
1196template <MInt nDim>
1198 TRACE();
1199 RECORD_TIMER_START(m_timers[Timers::GetRestartVars]);
1200
1201 // Copy variables to data buffer (in ascending cell/element id order)
1202 MInt offset = 0;
1203 for(MInt rbId = 0; rbId < m_rbElements.size(); rbId++) {
1204 const MInt noNodesXD = m_rbElements.noNodesXD(rbId);
1205
1206 for(MInt n = 0; n < noNodesXD; n++) {
1207 data[offset + n] = m_rbElements.variables(rbId, n * Base::SysEqn::noVars() + id_);
1208 }
1209
1210 offset += noNodesXD;
1211 }
1212
1213 RECORD_TIMER_STOP(m_timers[Timers::GetRestartVars]);
1214}
1215
1216
1220template <MInt nDim>
1222 TRACE();
1223
1224 // Only the variables need to be considered
1225 if(dataId < 0 || dataId > Base::SysEqn::noVars()) {
1226 TERMM(1, "Invalid dataId.");
1227 }
1228
1229 // Get element id and find corresponding RB-element (if there is one)
1230 const MInt elementId = getElementByCellId(cellId);
1231 auto rbElemIt = std::find(m_elementId.begin(), m_elementId.end(), elementId);
1232
1233 MInt dataSize = 0;
1234 if(rbElemIt != m_elementId.end()) {
1235 // Compute rb-element id
1236 const MInt rbId = std::distance(m_elementId.begin(), rbElemIt);
1237 const MInt noNodesXD = m_rbElements.noNodesXD(rbId);
1238
1239 dataSize = noNodesXD;
1240 }
1241
1242 return dataSize;
1243}
1244
1245
1249template <MInt nDim>
1251 TRACE();
1252
1253 return std::find(m_elementId.begin(), m_elementId.end(), elementId) != m_elementId.end();
1254}
1255
1256
1257#endif // DGBOUNDARYCONDITIONACOUSTICPERTURBRBC_H_
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
void apply(const MFloat time) override
Apply RBC.
MInt getLocalNoNodes() const override
Return local number of nodes.
void setCellDataDlb(const MInt dataId, const MFloat *const data) override
MBool hasBcElement(const MInt elementId) const override
Check if there is a boundary condition element associated with the given element.
MInt cellDataTypeDlb(const MInt NotUsed(dataId)) const override
void getCellDataDlb(const MInt dataId, MFloat *const data) const override
std::array< MFloat, MAX_SPACE_DIMENSIONS > m_rbcReferencePos
void calcFlux1D(const MFloat *nodeVars, const MFloat *q, const MInt noNodes1D, const MInt dirId, MFloat *flux_) const
Calculates the physical fluxes in direction 'dirId' on a surface.
void applyAtSurface(const MInt surfaceId, const MFloat NotUsed(time))
Calculate boundary surface flux.
static const constexpr MInt s_noNodeVars
MString restartVarName(const MInt id_) const override
Return name of restart variable.
void calcFlux(const MFloat *nodeVars, const MFloat *q, const MInt noNodes1D, MFloat *flux_) const
Calculates the physical fluxes in all directions for all integration points in an element.
MInt noCellDataDlb() const override
Dynamic load balancing.
void getRestartVariable(const MInt id_, MFloat *const data) const override
Copy restart variable data to pointer.
MString name() const override
Returns name of boundary condition.
void init() override
Initialize RBC.
void initTimers()
Initialize all timers and start the class timer.
void setRestartVariable(const MInt id_, const MFloat *const data) override
Copy restart variable data to boundary conditon.
void calcNodeVars(const MFloat *pos, const MFloat *nodeVarsAPE, MFloat *nodeVars)
Calculate RBC node variables at a given position.
void calcSurfaceNodeVars()
Calculate node variables of rb-surfaces.
void calcSource(const MFloat *nodeVars, const MFloat *u, const MInt noNodes1D, const MFloat t, const MFloat *x, MFloat *src) const
Calculates the source terms of the RBC system.
void calcElementNodeVars()
Calculate node variables of rb-elements.
std::vector< std::pair< MInt, MInt > > m_addBndrySrfcIds
std::array< MInt, Timers::_count > m_timers
DgBcAcousticPerturbRBC(SolverType &solver_, MInt bcId)
void calcRiemann(const MFloat *nodeVarsL, const MFloat *nodeVarsR, const MFloat *stateL, const MFloat *stateR, const MInt noNodes1D, const MInt dirId, MFloat *flux_) const
Calculates the numerical flux at a surface given two states.
MInt cellDataSizeDlb(const MInt dataId, const MInt cellId) const override
Solution data size for given cell and data id.
const DgInterpolation & interpolation(const MInt polyDeg, const MInt noNodes1D) const
Return interpolation.
void calcSourceTerms(const MFloat t, const MInt noElements, ElementCollector &elem, F &sourceFct)
MInt id() const
Return boundary condition if of this boundary condition.
SurfaceCollector & surfaces()
Return reference to surfaces.
MBool needHElementForCell(const MInt cellId)
Return if h-element is needed for given cell.
ElementCollector & elements()
Return reference to elements.
MInt getElementByCellId(const MInt cellId) const
Return element id corresponding to given cell id.
void calcSurfaceIntegral(const MInt begin_, const MInt end_, ElementCollector &elem, SurfaceCollector &surf, HElementCollector &helem, const MInt noHElements)
void applyJacobian(const MInt noElements, ElementCollector &elem)
void subTimeStepRk(const MFloat dt_, const MInt stage, const MInt totalSize, const MFloat *const rhs, MFloat *const variables, MFloat *const timeIntStorage)
Access to time integration method.
HElementCollector & helements()
Return reference to h-elements.
MInt getHElementId(const MInt elementId)
Return h-element id for an element.
MBool isMpiSurface(const MInt id_) const
Return true if surface is a MPI surface.
void calcVolumeIntegral(const MInt noElements, ElementCollector &elem, F &fluxFct)
void resetBuffer(const MInt totalSize, MFloat *const buffer)
MInt end() const
Return index of one-past-last surface.
void calcRegularSurfaceFlux(const MInt begin_, const MInt end_, SurfaceCollector &surf, F &riemannFct)
MFloat * flux(const MInt i)
Return pointer to surface flux.
This class is a ScratchSpace.
Definition: scratch.h:758
constexpr MInt size() const
Return size (i.e., currently used number of nodes)
Definition: container.h:89
Class that represents DG element collector.
Class that represents DG element collector.
Class that represents DG element collector.
@ MFLOAT
Definition: enums.h:269
@ DG_INTEGRATE_GAUSS
Definition: enums.h:313
@ DG_INTEGRATE_GAUSS_LOBATTO
Definition: enums.h:313
@ DG_TIMEINTEGRATION_CARPENTER_4_5
Definition: enums.h:321
@ DG_TIMEINTEGRATION_TOULORGEC_3_7
Definition: enums.h:325
@ DG_TIMEINTEGRATION_TOULORGEC_4_8
Definition: enums.h:322
@ DG_TIMEINTEGRATION_TOULORGEF_4_8
Definition: enums.h:326
@ DG_TIMEINTEGRATION_NIEGEMANN_4_13
Definition: enums.h:324
@ DG_TIMEINTEGRATION_NIEGEMANN_4_14
Definition: enums.h:323
constexpr Real POW2(const Real x)
Definition: functions.h:119
MInt ipow(MInt base, MInt exp)
Integer exponent function for non-negative exponents.
Definition: functions.h:317
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
MInt id
Definition: maiatypes.h:71
void const MInt cellId
Definition: collector.h:239
void loop(Functor &&fun, Class *object, const IdType begin, const IdType end, Args... args)
Holds helper functions for the interpolation.
define array structures