MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
lbsrcterm.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 "lbsrcterm.h"
8
9#include "IO/context.h"
10#include "UTIL/debug.h"
11#include "lbsolverdxqy.h"
12#include "lbsrctermcontroller.h"
13
14#include <vector>
15
16namespace maia::lb {
17
18//---LbSrcTerm_monopole-----------------------------------------------------
19//-declaration
24template <MInt nDim, MInt nDist, class SysEqn>
25class LbSrcTerm_monopole : public LbSrcTerm<nDim, nDist, SysEqn> {
26 private:
28
29 struct MonopoleInfo {
30 MInt id = -1;
31 MBool isActive = false;
32 MFloat amplitude; // of pulsating mass
34 MFloat radius = -1.0;
39 std::array<MFloat, nDim> position{};
40 std::vector<MInt> cellIds{};
41 std::vector<MFloat> srcTerms{};
42 };
43 std::vector<MonopoleInfo> m_monopole;
44
45 protected:
46 void readProperties() override;
47
48 public:
49 // static const LbRegSrcTerm<nDim, nDist, LbSrcTerm_monopole<nDim, nDist>> reg;
50
52
53 void init() override;
54 void apply_preCollision() override{/*UNUSED FOR FIRST ORDER IMPLEMENTATION*/};
55 void apply_postCollision() override;
56 void apply_postPropagation() override{};
57};
58
59//-definiton
60template <MInt nDim, MInt nDist, class SysEqn>
62 TRACE();
63 const MInt solverId = m_solver->m_solverId;
64 MInt noMonopole = 0;
65 for(MInt id = 0;; id++) {
66 if(!Context::propertyExists("monopoleAmplitude_" + std::to_string(id))) {
67 break;
68 }
69 noMonopole++;
70 auto& monopole = m_monopole.emplace_back();
71 monopole.id = id;
72 for(MInt d = 0; d < nDim; d++) {
73 monopole.position[d] = Context::getSolverProperty<MFloat>("monopolePos_" + std::to_string(id), solverId, AT_);
74 }
75 monopole.amplitude = Context::getSolverProperty<MFloat>("monopoleAmplitude_" + std::to_string(id), solverId, AT_);
76 monopole.strouhal = Context::getSolverProperty<MFloat>("monopoleStrouhal_" + std::to_string(id), solverId, AT_);
77 monopole.radius =
78 Context::getSolverProperty<MFloat>("monopoleRadius_" + std::to_string(id), solverId, AT_, &monopole.radius);
79 monopole.windowing = Context::getSolverProperty<MBool>("monopoleWindowing_" + std::to_string(id), solverId, AT_,
80 &monopole.windowing);
81 const MFloat phaseShiftStrouhal = Context::getSolverProperty<MFloat>("monopolePhaseShift_" + std::to_string(id),
82 solverId, AT_, &monopole.phaseShift);
83 if(monopole.radius < m_solver->c_cellLengthAtLevel(m_solver->maxLevel())) {
84 m_log << "monopoleRadius < max level cell length: Hence, it is clipped to max level cell length" << std::endl;
85 monopole.radius = m_solver->c_cellLengthAtLevel(m_solver->maxLevel());
86 }
87 const MFloat u_infty = m_solver->m_Ma * LBCS;
88 const MFloat dxLb = m_solver->c_cellLengthAtLevel(m_solver->maxLevel());
89 const MFloat massAmp = monopole.amplitude * (POW3(1.0 / dxLb)); // from STL to LB units m=rho*L^3
90 const MFloat densityAmp = massAmp / (F4B3 * PI * POW3(monopole.radius / dxLb));
91 monopole.omega = 2.0 * PI * (monopole.strouhal * u_infty / m_solver->m_referenceLength);
92 monopole.rhoFluct = densityAmp;
93 monopole.phaseShift = 2.0 * PI * (phaseShiftStrouhal * u_infty / m_solver->m_referenceLength);
94 if(m_solver->domainId() == 0) {
95 std::stringstream ss;
96 ss << "INFO: LbSrcTerm_monopole " << monopole.id << " analytical solution:" << std::endl;
97 ss << "rho(r,t)= 1.0 -" << (massAmp * POW2(monopole.omega)) / (4 * PI * POW2(LBCS)) << "/ (mag(coords)/" << dxLb
98 << ") * cos(" << monopole.omega << "* (" << g_timeSteps - 1 << " - mag(coords)/" << dxLb << "/" << LBCS << "))"
99 << std::endl;
100 std::cout << ss.str();
101 }
102 }
103 if(noMonopole == 0) {
104 TERMM(1, "Property monopoleAmplitude_0 is missing!");
105 }
106}
107
108template <MInt nDim, MInt nDist, class SysEqn>
110 TRACE();
111 for(auto& monopole : m_monopole) {
112 // First, clear everything -> usable to reinit
113 monopole.cellIds.clear();
114 monopole.srcTerms.clear();
115 // Now initialize
116 if(monopole.radius < 0.0) {
117 const MInt monopoleCellId = m_solver->getIdAtPoint(monopole.position.data());
118 if(monopoleCellId != -1) {
119 monopole.isActive = true;
120 monopole.cellIds.push_back(monopoleCellId);
121 }
122 } else {
123 const MFloat radiusSq = POW2(monopole.radius);
124 for(MInt i = 0; i < m_solver->m_currentMaxNoCells; i++) {
125 const MInt cellId = m_solver->m_activeCellList[i];
126 MFloat radiusSq_ = 0.0;
127 for(MInt d = 0; d < nDim; d++) {
128 radiusSq_ += POW2(monopole.position[d] - m_solver->a_coordinate(cellId, d));
129 }
130 if(radiusSq_ < radiusSq) {
131 monopole.isActive = true;
132 monopole.cellIds.push_back(cellId);
133 }
134 }
135 }
136 const MInt noSrcTermCells = monopole.cellIds.size();
137 monopole.srcTerms.resize(noSrcTermCells, 0.0);
138 //- info output
139 MInt noSrcTermCellsGlobal = noSrcTermCells;
140 MPI_Allreduce(MPI_IN_PLACE, &noSrcTermCellsGlobal, 1, MPI_INT, MPI_SUM, m_solver->mpiComm(), AT_, "MPI_IN_PLACE",
141 "noSrcTermCellsGlobal");
142 const MFloat ppw = 2 * PI * LBCS / monopole.omega; // ppw = lambda in LB units
143 const MFloat periode = m_solver->m_referenceLength / (monopole.strouhal * m_solver->m_Ma * LBCS);
144 std::stringstream ss;
145 ss << "INFO: LbSrcTerm_monopole " << monopole.id << ":" << std::endl;
146 ss << " amplitude :" << monopole.amplitude << std::endl;
147 ss << " rhoFluct :" << monopole.rhoFluct << std::endl;
148 ss << " radius :" << monopole.radius << std::endl;
149 ss << " strouhal :" << monopole.strouhal << std::endl;
150 ss << " omega :" << monopole.omega << std::endl;
151 ss << " phaseShift :" << monopole.phaseShift << std::endl;
152 ss << " windowing :" << monopole.windowing << std::endl;
153 ss << " noSrcTermCells :" << noSrcTermCellsGlobal << std::endl;
154 ss << " points per wave :" << ppw << std::endl;
155 ss << " timesteps per periode :" << periode << std::endl;
156 if(m_solver->domainId() == 0) {
157 std::cout << ss.str();
158 }
159 m_log << ss.str();
160 }
161}
162
163template <MInt nDim, MInt nDist, class SysEqn>
166 TRACE();
167 for(auto& monopole : m_monopole) {
168 if(!monopole.isActive) continue;
169 const MInt noSrcTermCells = monopole.cellIds.size();
170 for(MInt i = 0; i < noSrcTermCells; i++) {
171 //-update source term
172 monopole.srcTerms[i] =
173 -monopole.rhoFluct * monopole.omega * sin((monopole.omega + monopole.phaseShift) * globalTimeStep);
174 if(monopole.windowing) {
175 // Windowing shall be performed for the first wave length
176 if(globalTimeStep < 2 * PI / (monopole.omega)) {
177 const MFloat S = (globalTimeStep == 0 ? 0.5 : 1);
178 const MFloat hannHalfWindow = S * 0.5 * (1 - cos(monopole.omega * globalTimeStep / 2.0));
179 monopole.srcTerms[i] *= hannHalfWindow;
180 }
181 }
182
183 //-apply source term in solver
184 const MInt cellId = monopole.cellIds[i];
185 for(MInt j = 0; j < nDist; j++) {
186 m_solver->a_distribution(cellId, j) += Ld::tp(Ld::distType(j)) * monopole.srcTerms[i];
187 }
188 }
189 }
190}
191
192//-registration for LbSrcTermFactory class
193// V1 : no static member reg in LbSrcTerm_monopole needed
194static const LbRegSrcTerm<LbSrcTerm_monopole<2, 9, LbSysEqnIncompressible<2, 9>>> reg_Monopoled2q9("LB_SRC_MONOPOLE");
196 reg_Monopoled3q19("LB_SRC_MONOPOLE");
198 reg_Monopoled3q27("LB_SRC_MONOPOLE");
199static const LbRegSrcTerm<LbSrcTerm_monopole<2, 9, LbSysEqnCompressible<2, 9>>> reg_Monopoled2q9C("LB_SRC_MONOPOLE");
200static const LbRegSrcTerm<LbSrcTerm_monopole<3, 19, LbSysEqnCompressible<3, 19>>> reg_Monopoled3q19C("LB_SRC_MONOPOLE");
201static const LbRegSrcTerm<LbSrcTerm_monopole<3, 27, LbSysEqnCompressible<3, 27>>> reg_Monopoled3q27C("LB_SRC_MONOPOLE");
202// V2 : using static member reg in LbSrcTerm_monopole
203// template <MInt nDim, MInt nDist, class SysEqn>
204// LbRegSrcTerm<nDim, nDist, LbSrcTerm_monopole<nDim, nDist>>
205// LbSrcTerm_monopole<nDim, nDist>::reg("LB_SRC_MONOPOLE");
206// template class LbSrcTerm_monopole<3, 19>;
207// template class LbSrcTerm_monopole<3, 27>;
208
209//---LbSrcTerm_XXX----------------------------------------------------------
210// add furhter source terms below
211
212} // namespace maia::lb
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
Definition: context.cpp:494
This class represents all LB models.
Definition: lbsolverdxqy.h:29
Class for registering a source term to the factory registry.
Class to handle acoustic monopole source terms in lb solver.
Definition: lbsrcterm.cpp:25
LbSrcTerm_monopole(LbSolverDxQy< nDim, nDist, SysEqn > *p_solver)
Definition: lbsrcterm.cpp:51
LbSolverDxQy< nDim, nDist, SysEqn > * m_solver
Definition: lbsrcterm.cpp:27
void readProperties() override
Definition: lbsrcterm.cpp:61
void apply_postPropagation() override
Definition: lbsrcterm.cpp:56
void apply_postCollision() override
Definition: lbsrcterm.cpp:164
void apply_preCollision() override
Definition: lbsrcterm.cpp:54
std::vector< MonopoleInfo > m_monopole
Definition: lbsrcterm.cpp:43
Abstract class for lb source terms.
Definition: lbsrcterm.h:22
constexpr Real POW3(const Real x)
Definition: functions.h:123
constexpr Real POW2(const Real x)
Definition: functions.h:119
MInt globalTimeStep
MInt g_timeSteps
InfoOutFile m_log
int32_t MInt
Definition: maiatypes.h:62
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
MInt id
Definition: maiatypes.h:71
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
LB lattice descriptor for arrays depending on D and Q.
std::array< MFloat, nDim > position
Definition: lbsrcterm.cpp:39