29template <MInt nDim, MInt nDist,
class SysEqn>
50template <MInt nDim, MInt nDist,
class SysEqn>
54 RECORD_TIMER_STOP(m_timers[Timers::Class]);
64template <MInt nDim, MInt nDist,
class SysEqn>
69 NEW_TIMER_GROUP_NOCREATE(m_timers[Timers::TimerGroup],
"LbRb");
70 NEW_TIMER_NOCREATE(m_timers[Timers::Class],
"Total object lifetime", m_timers[Timers::TimerGroup]);
71 RECORD_TIMER_START(m_timers[Timers::Class]);
74 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Constructor],
"Constructor", m_timers[Timers::Class]);
75 RECORD_TIMER_START(m_timers[Timers::Constructor]);
78 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::CouplePostRb],
"Couple post RB", m_timers[Timers::Class]);
79 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ConstructGField],
"ConstructGField", m_timers[Timers::CouplePostRb]);
80 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Preparation],
"Prepare construct", m_timers[Timers::ConstructGField]);
82 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::FindBoundaryCells],
"FindBoundaryCells", m_timers[Timers::CouplePostRb]);
84 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::PreCouple],
"Pre Couple", m_timers[Timers::FindBoundaryCells]);
85 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::FindBoundaryMapping],
"Find Boundary Mapping",
86 m_timers[Timers::FindBoundaryCells]);
88 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::InitSolidDomain],
"InitSolidDomain", m_timers[Timers::CouplePostRb]);
89 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SetBoundaryVelocity],
"SetBoundaryVelocity", m_timers[Timers::CouplePostRb]);
91 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::CouplePostLb],
"Couple post LB", m_timers[Timers::Class]);
93 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::CreateComm],
"CreateComm", m_timers[Timers::CouplePostLb]);
94 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ApplyBC],
"ApplyBC", m_timers[Timers::CouplePostLb]);
95 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::ComputeBodyForces],
"ComputeBodyForces", m_timers[Timers::CouplePostLb]);
104template <MInt nDim, MInt nDist,
class SysEqn>
109 bodies().updateMaxLevel(lbSolver().maxLevel());
112 const MFloat dx = a_cellLengthAtLevel(lbSolver().maxLevel());
114 conversionLbRb.length = dx;
115 conversionRbLb.length = 1 / conversionLbRb.length;
117 conversionLbRb.velocity = sqrt(3) / a_Ma();
118 conversionRbLb.velocity = 1 / conversionLbRb.velocity;
120 conversionLbRb.time = conversionLbRb.length / conversionLbRb.velocity;
121 conversionRbLb.time = 1 / conversionLbRb.time;
123 conversionLbRb.force =
POW2(conversionLbRb.velocity) *
POW2(conversionLbRb.length);
124 conversionRbLb.force = 1 / conversionLbRb.force;
126 conversionLbRb.torque = conversionLbRb.force * conversionLbRb.length;
127 conversionRbLb.torque = 1 / conversionLbRb.torque;
129 bodies().setTimestep(conversionLbRb.time);
132 if(!lbSolver().domainId()) {
133 std::cout <<
"CONVERSION" << std::endl
134 <<
"LENGTH LB RB " << conversionLbRb.length << std::endl
135 <<
"LENGTH RB LB " << conversionRbLb.length << std::endl
136 <<
"VEL LB RB " << conversionLbRb.velocity << std::endl
137 <<
"VEL RB LB " << conversionRbLb.velocity << std::endl
138 <<
"TIME LB RB " << conversionLbRb.time << std::endl
139 <<
"TIME RB LB " << conversionRbLb.time << std::endl
140 <<
"FORCE LB RB " << conversionLbRb.force << std::endl
141 <<
"FORCE RB LB " << conversionRbLb.force << std::endl;
151template <MInt nDim, MInt nDist,
class SysEqn>
155 lbSolver().m_noLevelSetsUsedForMb = 1;
156 lbSolver().m_maxNoSets = 1;
164template <MInt nDim, MInt nDist,
class SysEqn>
172template <MInt nDim, MInt nDist,
class SysEqn>
177 lbSolver().initializeMovingBoundaries();
178 lbBndCnd().initializeBndMovingBoundaries();
181 bodies().setTimestep(conversionLbRb.time);
184 RECORD_TIMER_START(m_timers[Timers::CouplePostRb]);
185 RECORD_TIMER_START(m_timers[Timers::ConstructGField]);
187 RECORD_TIMER_STOP(m_timers[Timers::ConstructGField]);
188 RECORD_TIMER_STOP(m_timers[Timers::CouplePostRb]);
191template <MInt nDim, MInt nDist,
class SysEqn>
196 RECORD_TIMER_START(m_timers[Timers::CouplePostRb]);
197 RECORD_TIMER_START(m_timers[Timers::ConstructGField]);
199 RECORD_TIMER_STOP(m_timers[Timers::ConstructGField]);
200 RECORD_TIMER_STOP(m_timers[Timers::CouplePostRb]);
212template <MInt nDim, MInt nDist,
class SysEqn>
215 if(solverId == lbSolver().solverId()) {
216 lbSolver().initializeMovingBoundaries();
217 lbBndCnd().initializeBndMovingBoundaries();
221template <MInt nDim, MInt nDist,
class SysEqn>
224 if(solverCompleted[lbSolver().solverId()] && solverCompleted[bodies().solverId()]) {
228 if(sid == bodies().solverId()) {
230 RECORD_TIMER_START(m_timers[Timers::CouplePostRb]);
231 RECORD_TIMER_START(m_timers[Timers::ConstructGField]);
233 RECORD_TIMER_STOP(m_timers[Timers::ConstructGField]);
235 std::vector<MInt> maxGCellLevels(lbSolver().m_maxNoSets);
236 for(
MInt set = 0; set < lbSolver().m_maxNoSets; set++) {
237 maxGCellLevels[set] = lbSolver().maxLevel();
240 RECORD_TIMER_START(m_timers[Timers::FindBoundaryCells]);
241 RECORD_TIMER_START(m_timers[Timers::PreCouple]);
242 lbSolver().preCoupleLs(maxGCellLevels);
243 RECORD_TIMER_STOP(m_timers[Timers::PreCouple]);
245 RECORD_TIMER_START(m_timers[Timers::FindBoundaryMapping]);
246 lbSolver().createBndryToBodyMapping(bndryToBodyMapping, bodyToBndryMapping);
247 RECORD_TIMER_STOP(m_timers[Timers::FindBoundaryMapping]);
248 RECORD_TIMER_STOP(m_timers[Timers::FindBoundaryCells]);
250 RECORD_TIMER_START(m_timers[Timers::InitSolidDomain]);
251 initializeSolidDomain();
252 RECORD_TIMER_STOP(m_timers[Timers::InitSolidDomain]);
254 RECORD_TIMER_START(m_timers[Timers::SetBoundaryVelocity]);
261 } conversion{conversionRbLb.velocity, conversionLbRb.time, 1.0 / a_cellLengthAtLevel(lbSolver().maxLevel()), 1.0};
263 maia::coupling::setBoundaryVelocity<nDim>(bodies(), a_mbCell(), bodyToBndryMapping, conversion);
265 RECORD_TIMER_STOP(m_timers[Timers::SetBoundaryVelocity]);
266 RECORD_TIMER_STOP(m_timers[Timers::CouplePostRb]);
268 }
else if(sid == lbSolver().solverId()) {
270 RECORD_TIMER_START(m_timers[Timers::CouplePostLb]);
271 RECORD_TIMER_START(m_timers[Timers::CreateComm]);
272 lbBndCnd().createMBComm();
273 RECORD_TIMER_STOP(m_timers[Timers::CreateComm]);
275 RECORD_TIMER_START(m_timers[Timers::ApplyBC]);
276 lbBndCnd().postCouple();
277 RECORD_TIMER_STOP(m_timers[Timers::ApplyBC]);
279 RECORD_TIMER_START(m_timers[Timers::ComputeBodyForces]);
284 }
const conversion{conversionLbRb.force, 1.0};
286 if(a_noCollectorBodies() > 0) {
287 maia::coupling::setBoundaryForceAndTorque<nDim>(a_mbCell(), bodies(), bndryToBodyMapping, conversion);
291 for(
MInt b = 0;
b < a_noCollectorBodies();
b++) {
292 for(
MInt n = 0; n < nDim; n++) {
293 if(std::isnan(bodies().a_bodyForce(
b, n))) {
294 std::cout <<
"SUM FORCE IS NAN AFTER SETBOUNDANDFORCE AT TIMESETEP: " << lbSolver().getCurrentTimeStep()
302 RECORD_TIMER_STOP(m_timers[Timers::ComputeBodyForces]);
303 RECORD_TIMER_STOP(m_timers[Timers::CouplePostLb]);
315template <MInt nDim, MInt nDist,
class SysEqn>
317 for(
MInt n = 0; n < nDim; n++) {
318 bodyVelocity[n] = bodies().a_bodyVelocity(body, n) * conversionRbLb.velocity;
330template <MInt nDim, MInt nDist,
class SysEqn>
332 for(
MInt n = 0; n < nRot; n++) {
333 angularVelocity[n] = bodies().a_angularVelocity(body, n) / conversionRbLb.time;
342template <MInt nDim, MInt nDist,
class SysEqn>
346 lbSolver().m_noEmbeddedBodies = 1;
347 lbSolver().m_geometryIntersection->m_noLevelSetsUsedForMb = 1;
348 lbSolver().m_geometryIntersection->m_noEmbeddedBodies = bodies().size();
356template <MInt nDim, MInt nDist,
class SysEqn>
360 if(lbSolver().noNeighborDomains() > 0) {
361 lbSolver().exchangeOldDistributions();
364 MFloatScratchSpace bodyVelocities(a_noCollectorBodies(), nDim, AT_,
"bodyVelocities");
367 for(
MInt body = 0; body < a_noCollectorBodies(); body++) {
368 getBodyVelocity(body, &bodyVelocities(body, 0));
371 for(
MInt i = 0; i < a_noCells(); i++) {
373 if(a_isActive(i) && a_wasActive(i)) {
379 if(!lbSolver().c_isLeafCell(i)) {
386 for(
MInt set = lbSolver().m_levelSetId; set < lbSolver().m_maxNoSets; set++) {
387 if(a_associatedBodyIdsMb(i, set) >= 0) {
388 bodyId = a_associatedBodyIdsMb(i, set);
396 if(bodyId == -1 && lbSolver().a_isHalo(i) && bodies().m_bodyWasDeleted) {
397 lbBndCnd().refillEmergedCell(i);
398 lbSolver().a_isActive(i) = 1;
402 ASSERT(bodyId > -1,
"No valid bodyId for solid cell! (bodyId=" << bodyId <<
") (" << lbSolver().a_coordinate(i, 0)
403 <<
" " << lbSolver().a_coordinate(i, 1) <<
") ("
404 << i <<
" " << lbSolver().c_globalId(i) <<
")"
405 <<
" isHalo " << lbSolver().a_isHalo(i));
409 if((bodyId >= 0) && (bodyId < a_noCollectorBodies()) && (a_levelSetFunctionMb(i, setOfBody) < 0)) {
410 for(
MInt j = 0; j < nDim; j++) {
411 a_variable(i, j) = bodyVelocities(bodyId, j);
412 a_oldVariable(i, j) = bodyVelocities(bodyId, j);
415 for(
MInt j = 0; j < a_noVariables(); j++) {
416 a_variable(i, j) = F0;
417 a_oldVariable(i, j) = F0;
420 a_variable(i, a_pvrho()) = 1.0;
421 a_oldVariable(i, a_pvrho()) = 1.0;
424 a_variable(i, a_pvt()) = a_initTemperatureKelvin();
430 lbBndCnd().refillEmergedCell(i);
433 bodies().m_bodyWasDeleted =
false;
441template <MInt nDim, MInt nDist,
class SysEqn>
443 if(bodies().a_bodyType() == 1)
444 constructGField_<1>();
445 else if(bodies().a_bodyType() == 2)
446 constructGField_<2>();
447 else if(bodies().a_bodyType() == 3)
448 constructGField_<3>();
449 else if(bodies().a_bodyType() == 4)
450 constructGField_<4>();
451 else if(bodies().a_bodyType() == 7)
452 constructGField_<7>();
454 mTerm(1, AT_,
"Body type not implemented!");
464template <MInt nDim, MInt nDist,
class SysEqn>
465template <MInt bodyType>
469 RECORD_TIMER_START(m_timers[Timers::Preparation]);
473 MInt level = lbSolver().maxUniformRefinementLevel() - 1;
474 MFloat m_bodyDistThreshold = 0.0;
475 if(lbSolver().m_adaptation) {
476 m_bodyDistThreshold = lbSolver().m_bandWidth[level] * a_cellLengthAtLevel(level);
479 m_bodyDistThreshold = 2 * a_cellLengthAtLevel(lbSolver().maxLevel());
483 const MInt m_noLevelSetsUsedForMb = 1;
486 for(
MInt cellId = 0; cellId < a_noCells(); cellId++) {
487 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
488 a_associatedBodyIdsMb(cellId, set) = -1;
489 a_levelSetFunctionMb(cellId, set) = m_bodyDistThreshold + 1e-14;
493 const MInt noRelevantBodies = a_noCollectorBodies();
495 if(noRelevantBodies == 0) {
496 RECORD_TIMER_STOP(m_timers[Timers::Preparation]);
500 RECORD_TIMER_STOP(m_timers[Timers::Preparation]);
503 std::vector<MInt> collectorBodyIds(a_noCollectorBodies());
504 for(
MInt i = 0; i < a_noCollectorBodies(); i++) {
505 collectorBodyIds[i] = i;
508 for(
MInt i = 0; i < noMinCells(); i++) {
509 const MInt cellId = minCell(i);
510 const MFloat minDist = m_bodyDistThreshold + 1e-14;
512 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
513 a_associatedBodyIdsMb(cellId, set) = -1;
514 a_levelSetFunctionMb(cellId, set) = minDist;
517 if(a_noCollectorBodies() > 0) {
518 descendLevelSetValue<bodyType>(cellId, collectorBodyIds.data(), noRelevantBodies);
521 MInt parentId = a_parentId(cellId);
522 while(parentId > -1) {
523 for(
MInt set = 0; set < m_noLevelSetsUsedForMb; set++) {
524 a_levelSetFunctionMb(parentId, set) = a_levelSetFunctionMb(cellId, set);
525 a_associatedBodyIdsMb(parentId, set) = a_associatedBodyIdsMb(cellId, set);
527 parentId = a_parentId(parentId);
544template <MInt nDim, MInt nDist,
class SysEqn>
545template <MInt bodyType>
547 const MFloat minLevelThreshold = a_cellLengthAtLevel(lbSolver().a_level(cellId));
549 MBool skipDescend =
true;
551 for(
MInt b = 0;
b < bodyCnt;
b++) {
552 const MInt k = bodyIds[
b];
555 MFloat dist = bodies().template getDistance<bodyType>(&lbSolver().a_coordinate(cellId, 0), k);
557 if(
dist < minLevelThreshold) {
561 if(fabs(
dist) < fabs(a_levelSetFunctionMb(cellId, set)) || (
dist < F0)) {
562 a_levelSetFunctionMb(cellId, set) =
dist;
563 a_associatedBodyIdsMb(cellId, set) = k;
567 if(skipDescend || !lbSolver().grid().tree().hasChildren(cellId)) {
572 constexpr MInt maxNoChildren = nDim == 3 ? 8 : 4;
573 for(
MInt child = 0; child < maxNoChildren; child++) {
574 if(a_childId(cellId, child) < 0)
continue;
575 descendLevelSetValue<bodyType>(a_childId(cellId, child), bodyIds, bodyCnt);
579template <MInt nDim, MInt nDist,
class SysEqn>
582 if(!lbSolver().grid().isActive())
return;
586 m_timerType = Context::getSolverProperty<MString>(
"timerType", lbSolver().solverId(), AT_, &m_timerType);
589 const MInt noTimers = m_timers.size();
592 std::vector<MFloat> timerValues_;
593 timerValues_.reserve(noTimers);
594 for(
MInt i = 0; i < noTimers; i++) {
595 timerValues_.emplace_back(RETURN_TIMER_TIME(m_timers[i]));
599 if(m_timerType ==
"average") {
601 lbSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
"timerValues_");
604 lbSolver().mpiComm(), AT_,
"MPI_IN_PLACE",
"timerValues_");
608 if(m_timerType ==
"average") {
609 const MInt noDomains_ = lbSolver().noDomains();
610 for(
MInt i = 0; i < noTimers; i++) {
611 const MFloat meanValue = timerValues_[i] / noDomains_;
612 SET_RECORD(m_timers[i], meanValue);
615 for(
MInt i = 0; i < noTimers; i++) {
616 SET_RECORD(m_timers[i], timerValues_[i]);
typename CouplingRb::RBodies RBodies
void initTimers()
Creates all timers and subtimers.
void init() override
Initialize solver data needed for this coupling.
std::array< MInt, Timers::_count > m_timers
void descendLevelSetValue(const MInt cellId, const MInt *bodyId, const MInt bodyCnt)
Descend the level set value to the cells children.
void checkProperties()
Checks property-data which is read in by both ls-and Lb-Solver.
void initializeSolidDomain()
Initialize cells which are inisde the solid domain or just entered the fluid domain.
void constructGField_()
Constructs the level-set field after each time step.
void subCouple(MInt, MInt, std::vector< MBool > &) override
void initData()
Initializes coupler specific data.
~LbRb()
D'tor for the lattice Boltzmann rigid bodies coupler.
void readProperties()
Read all relevant properties.
void getBodyVelocity(const MInt body, MFloat *const velocity)
Get body velocity converted to LB units.
LbRb(MInt couplingId, LbSolver *lb, RBodies *rb)
C'tor for the lattice Boltzmann rigid bodies coupler.
void constructGField()
Dispatch function for the body specific construction of the level set.
void finalizeAdaptation(const MInt solverId) override
Coupling between solver substeps.
void updateGeometry()
Updates the member-variables in the geometry-intersection class.
void getBodyAngularVelocity(const MInt body, MFloat *const angularVelocity)
Get angular body velocity converted to LB units.
void postAdaptation() override
This class represents all LB models.
This class is a ScratchSpace.
void mTerm(const MInt errorCode, const MString &location, const MString &message)
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
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)