24template <MInt nDim, MInt nDist,
class SysEqn>
60template <MInt nDim, MInt nDist,
class SysEqn>
63 const MInt solverId = m_solver->m_solverId;
65 for(
MInt id = 0;;
id++) {
70 auto& monopole = m_monopole.emplace_back();
72 for(
MInt d = 0; d < nDim; d++) {
73 monopole.position[d] = Context::getSolverProperty<MFloat>(
"monopolePos_" + std::to_string(
id), solverId, AT_);
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_);
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_,
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());
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));
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) {
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 <<
"))"
100 std::cout << ss.str();
103 if(noMonopole == 0) {
104 TERMM(1,
"Property monopoleAmplitude_0 is missing!");
108template <MInt nDim, MInt nDist,
class SysEqn>
111 for(
auto& monopole : m_monopole) {
113 monopole.cellIds.clear();
114 monopole.srcTerms.clear();
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);
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];
127 for(
MInt d = 0; d < nDim; d++) {
128 radiusSq_ +=
POW2(monopole.position[d] - m_solver->a_coordinate(cellId, d));
130 if(radiusSq_ < radiusSq) {
131 monopole.isActive =
true;
132 monopole.cellIds.push_back(cellId);
136 const MInt noSrcTermCells = monopole.cellIds.size();
137 monopole.srcTerms.resize(noSrcTermCells, 0.0);
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;
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();
163template <MInt nDim, MInt nDist,
class SysEqn>
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++) {
172 monopole.srcTerms[i] =
173 -monopole.rhoFluct * monopole.omega * sin((monopole.omega + monopole.phaseShift) *
globalTimeStep);
174 if(monopole.windowing) {
179 monopole.srcTerms[i] *= hannHalfWindow;
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];
196 reg_Monopoled3q19(
"LB_SRC_MONOPOLE");
198 reg_Monopoled3q27(
"LB_SRC_MONOPOLE");
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
This class represents all LB models.
Class for registering a source term to the factory registry.
Class to handle acoustic monopole source terms in lb solver.
LbSrcTerm_monopole(LbSolverDxQy< nDim, nDist, SysEqn > *p_solver)
LbSolverDxQy< nDim, nDist, SysEqn > * m_solver
void readProperties() override
void apply_postPropagation() override
void apply_postCollision() override
void apply_preCollision() override
std::vector< MonopoleInfo > m_monopole
Abstract class for lb source terms.
constexpr Real POW3(const Real x)
constexpr Real POW2(const Real x)
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::vector< MFloat > srcTerms
std::array< MFloat, nDim > position
std::vector< MInt > cellIds