76 m_debugFileStream.close();
81 RECORD_TIMER_STOP(m_timers[Timers::Class]);
84 printScalingVariables();
92 NEW_TIMER_GROUP_NOCREATE(m_timers[Timers::TimerGroup],
"RigidBodies");
93 NEW_TIMER_NOCREATE(m_timers[Timers::Class],
"Total object lifetime", m_timers[Timers::TimerGroup]);
94 RECORD_TIMER_START(m_timers[Timers::Class]);
97 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Constructor],
"Constructor", m_timers[Timers::Class]);
98 RECORD_TIMER_START(m_timers[Timers::Constructor]);
100 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::SolutionStep],
"Solution Step", m_timers[Timers::Class]);
102 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Predict],
"Predict", m_timers[Timers::SolutionStep]);
103 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Correct],
"Correct", m_timers[Timers::SolutionStep]);
105 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::Communication],
"Communication", m_timers[Timers::SolutionStep]);
106 NEW_SUB_TIMER_NOCREATE(m_timers[Timers::UpdateCommunication],
"Update Communication", m_timers[Timers::SolutionStep]);
112 if(!grid().isActive())
return;
115 m_timerType = Context::getSolverProperty<MString>(
"timerType", m_solverId, AT_, &m_timerType);
119 const MInt noTimers = m_timers.size();
122 std::vector<MFloat> timerValues_;
123 timerValues_.reserve(noTimers);
124 for(
MInt i = 0; i < noTimers; i++) {
125 timerValues_.emplace_back(RETURN_TIMER_TIME(m_timers[i]));
129 if(m_timerType ==
"average") {
131 AT_,
"MPI_IN_PLACE",
"timerValues_");
134 AT_,
"MPI_IN_PLACE",
"timerValues_");
138 if(m_timerType ==
"average") {
139 const MInt noDomains_ = noDomains();
140 for(
MInt i = 0; i < noTimers; i++) {
141 const MFloat meanValue = timerValues_[i] / noDomains_;
142 SET_RECORD(m_timers[i], meanValue);
145 for(
MInt i = 0; i < noTimers; i++) {
146 SET_RECORD(m_timers[i], timerValues_[i]);
162 m_outputDir = Context::getSolverProperty<MString>(
"outputDir", m_solverId, AT_, &m_outputDir);
164 m_printKineticEnergy =
false;
165 Context::getSolverProperty<MBool>(
"printKineticEnergy", m_solverId, AT_, &m_printKineticEnergy);
167 m_intervalBodyLog = 1;
168 m_intervalBodyLog = Context::getSolverProperty<MInt>(
"intervalBodyLog", m_solverId, AT_, &m_intervalBodyLog);
172 m_restart = Context::getSolverProperty<MBool>(
"restartFile", m_solverId, AT_, &m_restart);
174 m_restartTimeStep = 0;
175 m_restartTimeStep = Context::getSolverProperty<MInt>(
"restartTimeStep", m_solverId, AT_, &m_restartTimeStep);
177 m_restartDir = Context::getSolverProperty<MString>(
"restartDir", m_solverId, AT_, &m_outputDir);
179 m_bodyCenterInitMethod =
"POINT";
180 m_bodyCenterInitMethod =
181 Context::getSolverProperty<MString>(
"bodyCenterInitMethod", m_solverId, AT_, &m_bodyCenterInitMethod);
184 if(m_bodyCenterInitMethod ==
"BOX_SEED") {
186 }
else if(m_bodyCenterInitMethod ==
"POINT") {
187 m_noEmbeddedBodies = Context::getSolverProperty<MInt>(
"noEmbeddedBodies", m_solverId, AT_, &m_noEmbeddedBodies);
190 for(
MInt i = 0; i < num_initialBodyCenters; i++) {
191 m_initialBodyCenters.emplace_back(Context::getSolverProperty<MFloat>(
"initialBodyCenters", m_solverId, AT_, i));
196 m_maxNoBodies = m_noEmbeddedBodies;
197 m_maxNoBodies = Context::getSolverProperty<MInt>(
"maxNoBodies", m_solverId, AT_, &m_maxNoBodies);
199 m_forcedMotion = Context::getSolverProperty<MBool>(
"forcedMotion", m_solverId, AT_, &m_forcedMotion);
202 m_bodyType = Context::getSolverProperty<MInt>(
"bodyTypeMb", m_solverId, AT_, &m_bodyType);
205 for(
MInt i = 0; i < num_initBodyRadius; i++) {
206 m_initBodyRadius.emplace_back(Context::getSolverProperty<MFloat>(
"bodyRadius", m_solverId, AT_, i));
210 for(
MInt i = 0; i < num_initBodyRadii; i++) {
211 m_initBodyRadii.emplace_back(Context::getSolverProperty<MFloat>(
"bodyRadii", m_solverId, AT_, i));
215 m_bodyHeight = Context::getSolverProperty<MFloat>(
"bodyHeight", m_solverId, AT_, &m_bodyHeight);
218 m_uRef = Context::getSolverProperty<MFloat>(
"uRef", m_solverId, AT_, &m_uRef);
220 m_logBodyData =
false;
221 m_logBodyData = Context::getSolverProperty<MBool>(
"logBodyData", m_solverId, AT_, &m_logBodyData);
225 for(
MInt i = 0; i < num_initBodyDensityRatios; i++) {
226 m_initBodyDensityRatios.emplace_back(Context::getSolverProperty<MFloat>(
"bodyDensityRatio", m_solverId, AT_, i));
230 for(
MInt n = 0; n < nDim; n++) {
231 gravity[n] = Context::getSolverProperty<MFloat>(
"gravity", m_solverId, AT_, n);
232 gravity[n] /=
POW2(m_uRef);
237 m_uniformBodyTemperature = F1;
238 m_uniformBodyTemperature =
239 Context::getSolverProperty<MFloat>(
"uniformBodyTemperature", m_solverId, AT_, &m_uniformBodyTemperature);
242 m_translation =
true;
243 m_translation = Context::getSolverProperty<MBool>(
"translation", m_solverId, AT_, &m_translation);
247 m_rotation = Context::getSolverProperty<MBool>(
"integrateRotation", m_solverId, AT_, &m_rotation);
251 m_rotXYaxis = Context::getSolverProperty<MBool>(
"rotXYaxis", m_solverId, AT_, &m_rotXYaxis);
265 loadBodiesSizeAndPosition();
270 m_bodies.reset(m_maxNoBodies);
273 for(
MInt i = 0; i < noNeighborDomains(); i++) {
274 MInt globDomain = neighborDomain(i);
275 m_remoteDomainLocalBodies[globDomain] = std::vector<MInt>();
276 m_homeDomainRemoteBodies[globDomain] = std::vector<MInt>();
279 m_bodies.append(m_noLocalBodies);
281 if(m_noLocalBodies == 0 && !m_restart)
return;
284 if(!m_initBodyRadius.empty()) {
286 if(m_initBodyRadius.size() == 1) {
287 const MFloat defaultRadius = m_initBodyRadius[0];
288 std::fill_n(&a_bodyRadius(0), m_noLocalBodies, defaultRadius);
289 std::fill_n(&a_bodyRadii(0, 0), m_noLocalBodies * nDim, defaultRadius);
291 for(
MUint bodyId = 0; bodyId < m_initBodyRadius.size(); bodyId++) {
292 a_bodyRadius(bodyId) = m_initBodyRadius[getGlobalBodyId(bodyId)];
293 std::fill_n(&a_bodyRadii(bodyId, 0), nDim, m_initBodyRadius[getGlobalBodyId(bodyId)]);
299 if(!m_initBodyRadii.empty()) {
300 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
302 if(m_initBodyRadii.size() == nDim) {
303 for(
MInt n = 0; n < nDim; n++) {
304 a_bodyRadii(bodyId, n) = m_initBodyRadii[n];
307 for(
MInt n = 0; n < nDim; n++) {
308 a_bodyRadii(bodyId, n) = m_initBodyRadii[getGlobalBodyId(bodyId) * nDim + n];
314 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
315 for(
MInt n = 0; n < nRot; n++) {
316 a_angularVelocityT1(bodyId, n) = 0.0;
317 a_angularAccelerationT1(bodyId, n) = 0.0;
321 if(!m_forcedMotion) {
322 if(m_initBodyDensityRatios.size() > 1) {
323 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
324 a_bodyDensityRatio(bodyId) = m_initBodyDensityRatios[getGlobalBodyId(bodyId)];
326 }
else if(m_initBodyDensityRatios.size() == 1) {
327 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
328 a_bodyDensityRatio(bodyId) = m_initBodyDensityRatios[0];
331 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
332 a_bodyDensityRatio(bodyId) = 1.0;
337 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
338 for(
MInt n = 0; n < nRot; n++) {
339 a_bodyInertia(bodyId, n) = 1.0;
340 a_angularVelocityT1B2(bodyId, n) = 0.0;
341 a_angularVelocityBodyT1(bodyId, n) = 0.0;
342 a_angularVelocityBodyT1B2(bodyId, n) = 0.0;
343 a_angularAccelerationBody(bodyId, n) = 0.0;
344 a_torqueT1(bodyId, n) = 0.0;
349 IF_CONSTEXPR(nDim == 3) {
350 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
351 for(
MInt n = 0; n < nQuat - 1; n++) {
352 a_bodyQuaternionT1B2(bodyId, n) = 0;
353 a_bodyQuaternionT1(bodyId, n) = 0;
355 a_bodyQuaternionT1B2(bodyId, nQuat - 1) = 1.0;
356 a_bodyQuaternionT1(bodyId, nQuat - 1) = 1.0;
357 a_bodyInertia(bodyId, 0) =
358 (
POW2(a_bodyRadii(bodyId, 1)) +
POW2(a_bodyRadii(bodyId, 2))) / 5.0 * a_bodyMass(bodyId);
359 a_bodyInertia(bodyId, 1) =
360 (
POW2(a_bodyRadii(bodyId, 0)) +
POW2(a_bodyRadii(bodyId, 2))) / 5.0 * a_bodyMass(bodyId);
361 a_bodyInertia(bodyId, 2) =
362 (
POW2(a_bodyRadii(bodyId, 0)) +
POW2(a_bodyRadii(bodyId, 1))) / 5.0 * a_bodyMass(bodyId);
368 loadBodyRestartFile();
370 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
371 a_bodyHeatFlux(bodyId) = 0.0;
372 const MInt tmpGlobalId = getGlobalBodyId(bodyId);
374 a_bodyTemperature(bodyId) = m_bResFile.bodyTemperature(tmpGlobalId);
375 for(
MInt n = 0; n < nDim; n++) {
376 a_bodyCenter(bodyId, n) = m_bResFile.bodyCenter(tmpGlobalId, n);
377 a_bodyVelocity(bodyId, n) = m_bResFile.bodyVelocity(tmpGlobalId, n);
378 a_bodyAcceleration(bodyId, n) = m_bResFile.bodyAcceleration(tmpGlobalId, n);
380 for(
MInt r = 0; r < nRot; r++) {
381 a_angularVelocityBodyT1B2(bodyId, r) = m_bResFile.angularVelocityBodyT1B2(tmpGlobalId, r);
382 a_angularAccelerationBody(bodyId, r) = m_bResFile.angularAccelerationBody(tmpGlobalId, r);
384 for(
MInt q = 0; q < nQuat; q++) {
385 a_bodyQuaternionT1B2(bodyId, q) = m_bResFile.bodyQuaternionT1B2(tmpGlobalId, q);
386 a_bodyQuaternionT1(bodyId, q) = m_bResFile.bodyQuaternionT1(tmpGlobalId, q);
391 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
392 for(
MInt n = 0; n < nDim; n++) {
393 a_bodyCenter(bodyId, n) = m_initialBodyCenters[getGlobalBodyId(bodyId) * nDim + n];
394 a_bodyVelocity(bodyId, n) = 0.0;
395 a_bodyAcceleration(bodyId, n) = 0.0;
396 a_bodyForce(bodyId, n) = 0.0;
398 a_bodyTemperature(bodyId) = 1.0;
399 a_bodyHeatFlux(bodyId) = 0.0;
404 if(!m_forcedMotion) {
424 std::remove(
"bodies.log");
425 m_log <<
"replaced body log";
429 std::remove(
"angvel.log");
430 m_log <<
"replaced angular body log";
434 m_anglog.open(
"angvel.log", std::ios::app);
438 std::stringstream logEntry;
439 std::stringstream logEntryAng;
441 logEntry <<
">>> enable body log by using: 'logBodyData = true' "
443 logEntryAng <<
">>> enable body log by using: 'logBodyData = true' "
446 m_log << logEntry.str();
449 m_anglog << logEntryAng.str();
456 m_logVars.insert(m_logVars.end(), {
"t",
"body",
"x",
"y",
"z",
"u",
"v",
"w",
"c_x",
"c_y",
"c_z"});
458 m_logAngVars.insert(m_logAngVars.end(),
459 {
"t",
"body",
"ang_vel_x",
"ang_vel_y",
"ang_vel_z",
"tourque_x",
"tourque_y",
"tourque_z"});
461 IF_CONSTEXPR(nDim == 2) {
462 std::vector<MString> removeList{
"z",
"w",
"c_z"};
463 std::vector<MString> removeListAng{
"ang_vel_z",
"tourque_z"};
464 for(
const MString& r : removeList) {
465 m_logVars.erase(std::remove(m_logVars.begin(), m_logVars.end(), r), m_logVars.end());
468 for(
const MString& r : removeListAng) {
469 m_logAngVars.erase(std::remove(m_logAngVars.begin(), m_logAngVars.end(), r), m_logAngVars.end());
473 for(
const MString& var : m_logVars) {
474 m_log << var << delimiter;
477 for(
const MString& var : m_logAngVars) {
478 m_anglog << var << delimiter;
492 std::map<MString, MInt> scalingVars;
493 scalingVars[
"localBodies"] = m_noLocalBodies;
494 scalingVars[
"connectedBodies"] = noConnectingBodies();
495 scalingVars[
"neighborDomains"] = noNeighborDomains();
497 std::vector<MInt> recvBuffer;
498 recvBuffer.resize(noDomains());
499 for(
const auto& [name, value] : scalingVars) {
501 0, mpiComm(), AT_,
"send",
"recv");
506 avgValue = std::accumulate(recvBuffer.begin(), recvBuffer.end(), avgValue);
507 avgValue /= noDomains();
508 std::cout <<
"Average " + name +
" per Domain are: " << avgValue << std::endl;
511 const MInt maxValue = *std::max_element(recvBuffer.begin(), recvBuffer.end());
512 std::cout <<
"Max " + name +
" per Domain are: " << maxValue << std::endl;
515 const MInt minValue = *std::min_element(recvBuffer.begin(), recvBuffer.end());
516 std::cout <<
"Min " + name +
" per Domain are: " << minValue << std::endl;
526 if(!(
globalTimeStep % m_solutionInterval == 0) || !m_printKineticEnergy)
return;
527 std::vector<MFloat> recvBuffer;
528 recvBuffer.resize(noDomains());
530 MFloat summedKineticEnergy = 0.0;
531 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
532 summedKineticEnergy += F1B2 * a_bodyDensityRatio(bodyId) * a_volume(bodyId) *
POW2(a_bodyVelocityMag(bodyId));
538 MFloat totalKineticEnergy = 0.0;
540 totalKineticEnergy = std::accumulate(recvBuffer.begin(), recvBuffer.end(), totalKineticEnergy);
541 std::cout <<
"Total Kinetic Energy of Bodies is: " << totalKineticEnergy << std::endl;
550 std::array<MFloat, nDim> bMin{};
551 std::array<MFloat, nDim> bMax{};
553 for(
MInt n = 0; n < nDim; n++) {
554 bMin[n] = Context::getSolverProperty<MFloat>(
"seedBoxMin", m_solverId, AT_, n);
555 bMax[n] = Context::getSolverProperty<MFloat>(
"seedBoxMax", m_solverId, AT_, n);
558 MInt bodiesPerEdge = Context::getSolverProperty<MInt>(
"bodiesPerEdge", m_solverId, AT_, &bodiesPerEdge);
559 m_noEmbeddedBodies = pow(bodiesPerEdge, nDim);
561 std::array<std::vector<MFloat>, nDim> bodyGrid;
562 for(
MInt n = 0; n < nDim; n++) {
566 m_initialBodyCenters.resize(
MLong(m_noEmbeddedBodies * nDim), F0);
567 for(
MInt i = 0; i < bodiesPerEdge; i++) {
568 MFloat x = bodyGrid[0][i];
569 for(
MInt j = 0; j < bodiesPerEdge; j++) {
571 for(
MInt k = 0; k < bodiesPerEdge; k++) {
572 MFloat z = bodyGrid[2][k];
573 m_initialBodyCenters[i * nDim * pow(bodiesPerEdge, 2) + j * nDim * bodiesPerEdge + k * nDim] = x;
574 m_initialBodyCenters[i * nDim * pow(bodiesPerEdge, 2) + j * nDim * bodiesPerEdge + k * nDim + 1] =
y;
575 m_initialBodyCenters[i * nDim * pow(bodiesPerEdge, 2) + j * nDim * bodiesPerEdge + k * nDim + 2] = z;
588 m_newTimeStep =
true;
604 <<
" -----------------------------------------------------------------------------------------------"
608 RECORD_TIMER_START(m_timers[Timers::SolutionStep]);
610 RECORD_TIMER_START(m_timers[Timers::Predict]);
612 RECORD_TIMER_STOP(m_timers[Timers::Predict]);
614 RECORD_TIMER_START(m_timers[Timers::Communication]);
615 exchangeKinematicData();
616 RECORD_TIMER_STOP(m_timers[Timers::Communication]);
618 m_newTimeStep =
false;
620 RECORD_TIMER_STOP(m_timers[Timers::SolutionStep]);
624 RECORD_TIMER_START(m_timers[Timers::SolutionStep]);
626 RECORD_TIMER_START(m_timers[Timers::Communication]);
628 RECORD_TIMER_STOP(m_timers[Timers::Communication]);
630 RECORD_TIMER_START(m_timers[Timers::Correct]);
632 RECORD_TIMER_STOP(m_timers[Timers::Correct]);
634 RECORD_TIMER_START(m_timers[Timers::Communication]);
635 exchangeKinematicData();
636 RECORD_TIMER_STOP(m_timers[Timers::Communication]);
638 RECORD_TIMER_START(m_timers[Timers::UpdateCommunication]);
640 RECORD_TIMER_STOP(m_timers[Timers::UpdateCommunication]);
643 RECORD_TIMER_STOP(m_timers[Timers::SolutionStep]);
664 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
665 computeBodyPropertiesForced(1, &m_bodies.bodyCenter(bodyId, 0), bodyId, time);
666 computeBodyPropertiesForced(2, &m_bodies.bodyVelocity(bodyId, 0), bodyId, time);
667 computeBodyPropertiesForced(3, &m_bodies.bodyAcceleration(bodyId, 0), bodyId, time);
687 MInt noRemoteDomains = m_remoteDomainLocalBodies.size();
688 MInt noHomeDomains = m_homeDomainRemoteBodies.size();
690 std::vector<MPI_Request> mpi_send_req(noRemoteDomains, MPI_REQUEST_NULL);
691 std::vector<MPI_Request> mpi_recv_req(noHomeDomains, MPI_REQUEST_NULL);
693 MInt bufSizePerBody = nDim * 3 + nRot * 2 + nQuat;
695 std::vector<std::vector<MFloat>> rcvBufferAll(noHomeDomains);
697 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
698 rcvBufferAll[idx].resize(bodies.size() * bufSizePerBody);
704 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
706 mpiComm(), &mpi_recv_req[idx], AT_,
"recv predict");
713 std::vector<std::vector<MFloat>> sendBufferAll(noRemoteDomains);
715 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
717 auto& sendBuffer = sendBufferAll[idx];
718 sendBuffer.resize(bufSizePerBody * bodies.size());
720 for(
const auto& body : bodies) {
722 for(
MInt n = 0; n < nDim; n++) {
723 sendBuffer[bodyCount + n] = a_bodyCenter(body, n);
726 sendBuffer[bodyCount + n] += m_periodicShift[remoteDomain][body][n];
728 sendBuffer[bodyCount + nDim + n] = a_bodyVelocity(body, n);
729 sendBuffer[bodyCount + 2 * nDim + n] = a_bodyAcceleration(body, n);
731 paraCount += 3 * nDim;
732 for(
MInt r = 0; r < nRot; r++) {
733 sendBuffer[bodyCount + paraCount + r] = a_angularVelocity(body, r);
734 sendBuffer[bodyCount + paraCount + nRot + r] = a_angularVelocityBody(body, r);
736 paraCount += 2 * nRot;
737 for(
MInt q = 0; q < nQuat; q++) {
738 sendBuffer[bodyCount + paraCount + q] = a_bodyQuaternionT1(body, q);
740 bodyCount += bufSizePerBody;
744 &mpi_send_req[idx], AT_,
"send predict");
749 for(
MInt i = 0; i < noRemoteDomains; i++) {
750 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
753 for(
MInt i = 0; i < noHomeDomains; i++) {
754 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
759 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
761 for(
const auto& body : bodies) {
763 for(
MInt n = 0; n < nDim; n++) {
764 a_bodyCenter(body, n) = rcvBufferAll[idx][bodyCount + n];
765 a_bodyVelocity(body, n) = rcvBufferAll[idx][bodyCount + nDim + n];
766 a_bodyAcceleration(body, n) = rcvBufferAll[idx][bodyCount + nDim * 2 + n];
768 paraCount += 3 * nDim;
769 for(
MInt r = 0; r < nRot; r++) {
770 a_angularVelocity(body, r) = rcvBufferAll[idx][bodyCount + paraCount + r];
771 a_angularVelocityBody(body, r) = rcvBufferAll[idx][bodyCount + paraCount + nRot + r];
773 paraCount += 2 * nRot;
774 for(
MInt q = 0; q < nQuat; q++) {
775 a_bodyQuaternionT1(body, q) = rcvBufferAll[idx][bodyCount + paraCount + q];
777 bodyCount += bufSizePerBody;
783 auto aDBCopy = m_associatedDummyBodies;
784 for(
const auto& [body, dummyId] : aDBCopy) {
787 const MInt intersectingCellId =
788 grid().raw().intersectingWithHaloCells(&a_bodyCenter(body, 0), m_infoDiameter / 2.0, 0,
true);
789 if(intersectingCellId == -1) {
790 deleteDummyBody(body);
793 for(
MInt n = 0; n < nDim; n++) {
795 m_periodicShift[domainId()][body][n] = calculatePeriodicShift(intersectingCellId, n);
796 a_bodyCenter(dummyId, n) = a_bodyCenter(body, n) + m_periodicShift[domainId()][body][n];
797 a_bodyVelocity(dummyId, n) = a_bodyVelocity(body, n);
798 a_bodyAcceleration(dummyId, n) = a_bodyAcceleration(body, n);
800 for(
MInt r = 0; r < nRot; r++) {
801 a_angularVelocity(dummyId, r) = a_angularVelocity(body, r);
802 a_angularVelocityBody(dummyId, r) = a_angularVelocityBody(body, r);
804 for(
MInt q = 0; q < nQuat; q++) {
805 a_bodyQuaternionT1(dummyId, q) = a_bodyQuaternionT1(body, q);
825 std::vector<MPI_Request> mpi_send_req(noHomeDomains(), MPI_REQUEST_NULL);
826 std::vector<MPI_Request> mpi_recv_req(noRemoteDomains(), MPI_REQUEST_NULL);
828 MInt noRemoteDomains = m_remoteDomainLocalBodies.size();
829 MInt noHomeDomains = m_homeDomainRemoteBodies.size();
831 MInt bufSizePerBody = nDim * 2;
833 std::vector<std::vector<MFloat>> rcvBufferAll(noRemoteDomains);
835 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
836 rcvBufferAll[idx].resize(bodies.size() * bufSizePerBody);
842 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
844 mpiComm(), &mpi_recv_req[idx], AT_,
"recv predict");
850 std::vector<std::vector<MFloat>> sendBufferAll(noHomeDomains);
852 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
854 auto& sendBuffer = sendBufferAll[idx];
855 sendBuffer.resize(bufSizePerBody * bodies.size());
857 for(
const auto& body : bodies) {
858 for(
MInt n = 0; n < nDim; n++) {
861 if(hasAssociatedDummyBody(body)) {
862 a_bodyForce(body, n) += a_bodyForce(m_associatedDummyBodies[body], n);
863 a_bodyTorque(body, n) += a_bodyTorque(m_associatedDummyBodies[body], n);
865 sendBuffer[bodyCount + n] = a_bodyForce(body)[n];
866 sendBuffer[bodyCount + nDim + n] = a_bodyTorque(body)[n];
868 bodyCount += bufSizePerBody;
872 &mpi_send_req[idx], AT_,
"send predict");
877 for(
MInt i = 0; i < noHomeDomains; i++) {
878 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
881 for(
MInt i = 0; i < noRemoteDomains; i++) {
882 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
887 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
889 for(
const auto& body : bodies) {
890 for(
MInt n = 0; n < nDim; n++) {
891 a_bodyForce(body)[n] += rcvBufferAll[idx][bodyCount + n];
892 a_bodyTorque(body)[n] += rcvBufferAll[idx][bodyCount + nDim + n];
894 bodyCount += bufSizePerBody;
900 for(
const auto& [body, dummyId] : m_associatedDummyBodies) {
901 for(
MInt n = 0; n < nDim; n++) {
902 a_bodyForce(body, n) += a_bodyForce(dummyId, n);
903 a_bodyTorque(body, n) += a_bodyTorque(dummyId, n);
911 findTransferBodies();
912 exchangeTransferBodies();
913 checkDummyBodiesForSwap();
914 updateInfoDiameter();
915 updateBodyDomainConnections(
false);
916 exchangeEdgeBodyData();
919 printBodyDomainConnections();
921 totalKineticEnergy();
933 if(!m_forcedMotion) {
949 if(!m_logBodyData || !(
globalTimeStep % m_intervalBodyLog == 0))
return;
952 const MInt bufSizePerBody = 1 + nDim * 5;
953 std::vector<MFloat> sendBuffer(
MLong(bufSizePerBody * m_noLocalBodies));
954 for(
MInt i = 0; i < m_noLocalBodies; i++) {
956 sendBuffer[
MLong(i * bufSizePerBody)] = (
MFloat)bodyId;
957 for(
MInt n = 0; n < nDim; n++) {
958 sendBuffer[i * bufSizePerBody + 1 + n] = a_bodyCenter(bodyId, n);
959 sendBuffer[i * bufSizePerBody + 1 + 1 * nDim + n] = a_bodyVelocity(bodyId, n);
960 sendBuffer[i * bufSizePerBody + 1 + 2 * nDim + n] = a_bodyAcceleration(bodyId, n);
961 sendBuffer[i * bufSizePerBody + 1 + 3 * nDim + n] = a_angularVelocity(bodyId, n);
962 sendBuffer[i * bufSizePerBody + 1 + 4 * nDim + n] = a_bodyTorque(bodyId, n);
966 std::vector<MInt> noToRecv(noDomains());
967 const MUint noToSend = sendBuffer.size();
968 exchangeBufferLengthsAllToRoot(noToRecv, noToSend);
971 std::vector<MInt> displacements(noDomains());
972 for(
MInt n = 0; n < noDomains(); n++) {
974 displacements[n] = count;
975 count += noToRecv[n];
979 std::vector<MFloat> rcvBuffer(
MLong(m_noEmbeddedBodies * bufSizePerBody));
984 if(domainId() != 0)
return;
987 std::stringstream logEntry;
988 std::stringstream logEntryAng;
990 for(
MInt b = 0;
b < m_noEmbeddedBodies;
b++) {
994 logEntry << bodyId << delimiter;
997 logEntryAng << bodyId << delimiter;
999 std::array<MFloat, nDim> center{};
1000 std::array<MFloat, nDim> velocity{};
1001 std::array<MFloat, nDim> acceleration{};
1002 std::array<MFloat, nDim> ang_vel{};
1003 std::array<MFloat, nDim> torque{};
1005 for(
MInt n = 0; n < nDim; n++) {
1006 center[n] = rcvBuffer[
b * bufSizePerBody + 1 + n];
1007 velocity[n] = rcvBuffer[
b * bufSizePerBody + 1 + nDim + n];
1008 acceleration[n] = rcvBuffer[
b * bufSizePerBody + 1 + 2 * nDim + n];
1009 ang_vel[n] = rcvBuffer[
b * bufSizePerBody + 1 + 3 * nDim + n];
1010 torque[n] = rcvBuffer[
b * bufSizePerBody + 1 + 4 * nDim + n];
1014 for(
MInt n = 0; n < nDim; n++) {
1015 logEntry << std::scientific << center[n] << delimiter;
1018 for(
MInt n = 0; n < nDim; n++) {
1019 logEntry << std::scientific << velocity[n] << delimiter;
1022 for(
MInt n = 0; n < nDim; n++) {
1023 logEntry << std::scientific << acceleration[n] << delimiter;
1027 for(
MInt n = 0; n < nDim; n++) {
1028 logEntryAng << std::scientific << ang_vel[n] << delimiter;
1031 for(
MInt n = 0; n < nDim; n++) {
1032 logEntryAng << std::scientific << torque[n] << delimiter;
1036 logEntryAng <<
"\n";
1039 m_log.
open(
"bodies.log", std::ios::app);
1040 m_log << logEntry.str();
1043 m_anglog.open(
"angvel.log", std::ios::app);
1044 m_anglog << logEntryAng.str();
1057 m_bodies.advanceBodies();
1069 const MFloat dt = m_timestep;
1072 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
1074 for(
MInt n = 0; n < nDim; n++) {
1076 a_bodyAcceleration(bodyId, n) = a_bodyAccelerationOld(bodyId, n);
1079 a_bodyVelocity(bodyId, n) = a_bodyVelocityOld(bodyId, n)
1080 + 0.5 * dt * (a_bodyAcceleration(bodyId, n) + a_bodyAccelerationOld(bodyId, n));
1083 a_bodyCenter(bodyId, n) =
1084 a_bodyCenterOld(bodyId, n) + dt * a_bodyVelocityOld(bodyId, n)
1085 + 0.25 *
POW2(dt) * (a_bodyAcceleration(bodyId, n) + a_bodyAccelerationOld(bodyId, n));
1089 predictRotation(bodyId);
1094 a_bodyTemperature(bodyId) =
1095 a_bodyTemperatureOld(bodyId) + dt * a_bodyHeatFlux(bodyId) / (m_bodyHeatCapacity * a_bodyMass(bodyId));
1099 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
1100 predictRotation(bodyId);
1110 std::vector<MPI_Request> mpi_send_req(noHomeDomains(), MPI_REQUEST_NULL);
1111 std::vector<MPI_Request> mpi_recv_req(noRemoteDomains(), MPI_REQUEST_NULL);
1115 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
1116 MPI_Irecv(&noToRecv[count], 1, MPI_INT, remoteDomain, 2, mpiComm(), &mpi_recv_req[count], AT_,
"recv from remote");
1122 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
1123 MPI_Isend(&noToSend[count], 1, MPI_INT, homeDomain, 2, mpiComm(), &mpi_send_req[count], AT_,
"send to home");
1128 for(
MInt n = 0; n < noHomeDomains(); n++) {
1129 MPI_Wait(&mpi_send_req[n], MPI_STATUS_IGNORE, AT_);
1132 for(
MInt n = 0; n < noRemoteDomains(); n++) {
1133 MPI_Wait(&mpi_recv_req[n], MPI_STATUS_IGNORE, AT_);
1146 std::vector<std::vector<MInt>>& bodyList) {
1150 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
1151 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
1154 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1155 MPI_Irecv(&noToRecv[n], 1, MPI_INT, neighborDomain(n), 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv predict");
1159 std::vector<MUint> sendBuffer(noNeighborDomains(), 0);
1160 for(
MInt d = 0; d < noNeighborDomains(); d++) {
1161 sendBuffer[d] = bodyList[d].size();
1165 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1166 MPI_Isend(&sendBuffer[i], 1, MPI_INT, neighborDomain(i), 2, mpiComm(), &mpi_send_req[i], AT_,
"send predict");
1170 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1171 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
1172 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
1189 std::map<
MInt, std::vector<MInt>>& bodyList) {
1193 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
1194 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
1197 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1198 MPI_Irecv(&noToRecv[n], 1, MPI_INT, neighborDomain(n), 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv predict");
1202 std::vector<MUint> sendBuffer(noNeighborDomains(), 0);
1203 for(
MInt d = 0; d < noNeighborDomains(); d++) {
1204 MInt globDomain = neighborDomain(d);
1205 sendBuffer[d] = bodyList[globDomain].size();
1209 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1210 MPI_Isend(&sendBuffer[i], 1, MPI_INT, neighborDomain(i), 2, mpiComm(), &mpi_send_req[i], AT_,
"send predict");
1214 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1215 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
1216 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
1231 MPI_Request mpi_send_req = MPI_REQUEST_NULL;
1232 std::vector<MPI_Request> mpi_recv_req(noDomains(), MPI_REQUEST_NULL);
1236 for(
MInt n = 0; n < noDomains(); n++) {
1237 MPI_Irecv(&noToRecv[n], 1, MPI_INT, n, 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv buffer length");
1242 MPI_Isend(&noToSend, 1, MPI_INT, 0, 2, mpiComm(), &mpi_send_req, AT_,
"send buffer length");
1245 MPI_Waitall(noDomains(), mpi_recv_req.data(), MPI_STATUS_IGNORE, AT_);
1248 MPI_Wait(&mpi_send_req, MPI_STATUS_IGNORE, AT_);
1262 std::vector<MPI_Request> mpi_send_req(noDomains(), MPI_REQUEST_NULL);
1263 std::vector<MPI_Request> mpi_recv_req(noDomains(), MPI_REQUEST_NULL);
1266 for(
MInt n = 0; n < noDomains(); n++) {
1267 MPI_Irecv(&noToRecv[n], 1, MPI_INT, n, 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv buffer length");
1271 for(
MInt n = 0; n < noDomains(); n++) {
1272 MPI_Isend(&noToSend, 1, MPI_INT, n, 2, mpiComm(), &mpi_send_req[n], AT_,
"send buffer length");
1275 MPI_Waitall(noDomains(), mpi_send_req.data(), MPI_STATUSES_IGNORE, AT_);
1276 MPI_Waitall(noDomains(), mpi_recv_req.data(), MPI_STATUSES_IGNORE, AT_);
1286 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
1287 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
1290 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1291 MPI_Irecv(&noToRecv[n], 1, MPI_INT, neighborDomain(n), 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv buffer length");
1295 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1296 MPI_Isend(&noToSend, 1, MPI_INT, neighborDomain(n), 2, mpiComm(), &mpi_send_req[n], AT_,
"send buffer length");
1299 MPI_Waitall(noNeighborDomains(), mpi_send_req.data(), MPI_STATUSES_IGNORE, AT_);
1300 MPI_Waitall(noNeighborDomains(), mpi_recv_req.data(), MPI_STATUSES_IGNORE, AT_);
1314 std::vector<MInt> noLocalBodiesPerPartition(noDomains());
1315 exchangeBufferLengthsAllToAll(noLocalBodiesPerPartition, m_noLocalBodies);
1318 for(
MInt i = 0; i < domainId(); i++) {
1319 offset += noLocalBodiesPerPartition[i];
1337 m_bResFile.reset(noEmbeddedBodies());
1338 m_bResFile.append(noEmbeddedBodies());
1341 std::vector<MFloat*> transVarsRcv{&m_bResFile.bodyCenter(0, 0), &m_bResFile.bodyVelocity(0, 0),
1342 &m_bResFile.bodyAcceleration(0, 0)};
1344 std::vector<MFloat*> rotVarsRcv{&m_bResFile.angularVelocityBodyT1B2(0, 0), &m_bResFile.angularAccelerationBody(0, 0)};
1346 std::vector<MFloat*> quatVarsRcv{&m_bResFile.bodyQuaternionT1B2(0, 0), &m_bResFile.bodyQuaternionT1(0, 0)};
1349 const MInt noTransVars = 3;
1350 const MInt noRotVars = 2;
1351 const MInt noQuatVars = 2;
1352 const MInt bufSizePerBody = 1 + 1 + noTransVars * nDim + noRotVars * nRot + noQuatVars * nQuat;
1353 MInt varSizeCount = 0;
1354 MInt bodySizeCount = 0;
1356 std::vector<MFloat> sendBuffer(
MLong(m_noLocalBodies * bufSizePerBody));
1357 const MUint noToSend = sendBuffer.size();
1360 if(m_bodies.size() > 0) {
1362 std::vector<MFloat*> transVars{&a_bodyCenter(0, 0), &a_bodyVelocity(0, 0), &a_bodyAcceleration(0, 0)};
1365 std::vector<MFloat*> rotVars{&a_angularVelocityBodyT1B2(0, 0), &a_angularAccelerationBody(0, 0)};
1368 std::vector<MFloat*> quatVars{&a_bodyQuaternionT1B2(0, 0), &a_bodyQuaternionT1(0, 0)};
1371 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
1372 sendBuffer[bodySizeCount] = (
MFloat)getGlobalBodyId(bodyId);
1376 sendBuffer[bodySizeCount + varSizeCount] = a_bodyTemperature(bodyId);
1380 for(
MInt v = 0; v < noTransVars; v++) {
1381 for(
MInt n = 0; n < nDim; n++) {
1382 sendBuffer[bodySizeCount + varSizeCount + n] = transVars[v][nDim * bodyId + n];
1384 varSizeCount += nDim;
1387 for(
MInt v = 0; v < noRotVars; v++) {
1388 for(
MInt r = 0; r < nRot; r++) {
1389 sendBuffer[bodySizeCount + varSizeCount + r] = rotVars[v][nRot * bodyId + r];
1391 varSizeCount += nRot;
1395 for(
MInt v = 0; v < noQuatVars; v++) {
1396 for(
MInt q = 0; q < nQuat; q++) {
1397 sendBuffer[bodySizeCount + varSizeCount + q] = quatVars[v][nQuat * bodyId + q];
1399 varSizeCount += nQuat;
1401 bodySizeCount += bufSizePerBody;
1407 std::vector<MInt> noToRecv(noDomains());
1408 exchangeBufferLengthsAllToAll(noToRecv, noToSend);
1409 std::vector<MFloat> rcvBuffer(noEmbeddedBodies() * bufSizePerBody);
1413 std::vector<MInt> displacements(noDomains());
1414 for(
MInt n = 0; n < noDomains(); n++) {
1415 displacements[n] = count;
1416 count += noToRecv[n];
1427 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
1428 const MInt bodyId = (
MInt)rcvBuffer[bodySizeCount];
1432 m_bResFile.bodyTemperature(bodyId) = rcvBuffer[bodySizeCount + varSizeCount];
1436 for(
MInt v = 0; v < noTransVars; v++) {
1437 for(
MInt n = 0; n < nDim; n++) {
1438 transVarsRcv[v][nDim * bodyId + n] = rcvBuffer[bodySizeCount + varSizeCount + n];
1440 varSizeCount += nDim;
1443 for(
MInt v = 0; v < noRotVars; v++) {
1444 for(
MInt r = 0; r < nRot; r++) {
1445 rotVarsRcv[v][nRot * bodyId + r] = rcvBuffer[bodySizeCount + varSizeCount + r];
1447 varSizeCount += nRot;
1451 for(
MInt v = 0; v < noQuatVars; v++) {
1452 for(
MInt q = 0; q < nQuat; q++) {
1453 quatVarsRcv[v][nQuat * bodyId + q] = rcvBuffer[bodySizeCount + varSizeCount + q];
1455 varSizeCount += nQuat;
1457 bodySizeCount += bufSizePerBody;
1473 for(
MInt globalBodyId = 0; globalBodyId < noEmbeddedBodies(); globalBodyId++) {
1474 std::array<MFloat, nDim> tmpCenter{};
1475 for(
MInt n = 0; n < nDim; n++) {
1477 tmpCenter[n] = m_bResFile.bodyCenter(globalBodyId, n);
1479 tmpCenter[n] = m_initialBodyCenters[globalBodyId * nDim + n];
1482 MBool insideLocalBbox = grid().raw().pointInLocalBoundingBox(tmpCenter.data());
1483 if(insideLocalBbox) {
1484 MInt localPCellId = grid().raw().findContainingPartitionCell(tmpCenter.data(), -1,
nullptr);
1485 if(localPCellId != -1) {
1486 m_globalBodyIds.emplace_back(globalBodyId);
1498 for(
MInt n = 0; n < nDim; n++) {
1499 m_globDomainLength[n] = globBBox(nDim + n) - globBBox(n);
1500 periodic += grid().raw().periodicCartesianDir(n);
1504 m_periodicBC =
true;
1506 constexpr MFloat eps = 1e-9;
1507 MBool domainIsCube =
true;
1508 for(
MInt n = 0; n < nDim; n++) {
1509 domainIsCube = domainIsCube && (m_globDomainLength[0] - m_globDomainLength[n]) < eps;
1513 std::cerr <<
"\033[0;31m Warning:\033[0m Domain is not a cube - periodic BCs only work on cube domains"
1518 updateMaxLevel(maxLevel());
1524 std::vector<MInt> l_Bodies;
1525 MFloat maxBodyExtension = F0;
1528 for(
MInt i = 0; i < m_noLocalBodies; i++) {
1529 l_Bodies.push_back(i);
1532 for(
MInt bodyId = 0; bodyId < noCollectorBodies(); bodyId++) {
1533 l_Bodies.push_back(bodyId);
1537 if(m_initBodyRadii.empty()) {
1538 for(
const MInt& bodyId : l_Bodies) {
1539 maxBodyExtension = std::max(maxBodyExtension, 2 * a_bodyRadius(bodyId));
1542 for(
const MInt& bodyId : l_Bodies) {
1543 for(
MInt n = 0; n < nDim; n++) {
1544 maxBodyExtension = std::max(maxBodyExtension, 2 * a_bodyRadii(bodyId, n));
1549 constexpr const MInt noCellsClearance = 4.0;
1550 m_infoDiameter = maxBodyExtension + noCellsClearance * c_cellLengthAtMaxLevel();
1564 m_transferBodies.clear();
1565 m_transferBodies.resize(noNeighborDomains());
1567 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1571 for(
const MInt& bodyId : m_remoteDomainLocalBodies[neighborDomain(i)]) {
1572 MBool outside = -1 != grid().raw().findContainingHaloCell(&a_bodyCenter(bodyId, 0), -1, i,
true,
nullptr);
1575 m_transferBodies[i].push_back(bodyId);
1577 m_debugFileStream <<
"Found transfer body with globalId " << getGlobalBodyId(bodyId)
1578 <<
" will be sent to domain " << i << std::endl;
1602 std::vector<MInt> noToRecv(noNeighborDomains());
1603 MInt totalBufferLength = 0;
1604 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1605 totalBufferLength += m_transferBodies[i].size();
1608 exchangeBufferLengthsNeighbors(noToRecv, totalBufferLength);
1611 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
1612 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
1615 std::vector<std::vector<MFloat>> rcvBufferAll(noNeighborDomains());
1616 MInt bufSizePerBody = 2;
1618 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1619 rcvBufferAll[n].resize(
MLong(noToRecv[n] * bufSizePerBody));
1623 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1629 2, mpiComm(), &mpi_recv_req[i], AT_,
"recv predict");
1634 std::vector<MFloat> sendBufferAll(
MLong(totalBufferLength * bufSizePerBody));
1635 std::list<std::pair<MInt, MInt>> localBodyRemoveList;
1636 for(
MUint i = 0; i < m_transferBodies.size(); i++) {
1638 MUint newHomeDomain = neighborDomain(domain);
1639 for(
const auto& body : m_transferBodies[i]) {
1640 sendBufferAll[
MLong(idx * bufSizePerBody)] = (
MFloat)getGlobalBodyId(body);
1641 sendBufferAll[idx * bufSizePerBody + 1] = (
MFloat)newHomeDomain;
1644 auto it = std::find_if(localBodyRemoveList.cbegin(), localBodyRemoveList.cend(),
1645 [&body](
const std::pair<MInt, MInt>& localB) { return localB.second == body; });
1646 if(it == localBodyRemoveList.cend()) {
1647 localBodyRemoveList.push_front(std::make_pair(newHomeDomain, body));
1653 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1654 if(sendBufferAll.empty()) {
1659 mpiComm(), &mpi_send_req[i], AT_,
"send predict");
1663 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1664 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
1667 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1668 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
1677 std::map<MInt, MInt> tmpMapping;
1678 for(
const auto& [newDomainId, body] : localBodyRemoveList) {
1679 tmpMapping[body] = body;
1681 for(
const auto& [newDomainId, body] : localBodyRemoveList) {
1682 const MInt tmpCollectorId = tmpMapping[body];
1683 const MInt remoteBodyId = localToRemoteBody(tmpCollectorId, body, newDomainId);
1686 for(
auto& [newDomainId_, body_] : localBodyRemoveList) {
1687 if(body_ == remoteBodyId) {
1688 tmpMapping[body_] = tmpCollectorId;
1696 std::vector<std::pair<MInt, MInt>> remoteBodiesToLocal;
1697 std::vector<std::array<MInt, 2>> remoteBodiesNeighDomain;
1698 for(
MInt n = 0; n < noNeighborDomains(); n++) {
1699 for(
MInt b = 0;
b < noToRecv[n];
b++) {
1700 MInt globalBodyId =
MInt(rcvBufferAll[n][
MLong(
b * bufSizePerBody)]);
1701 MInt newHomeDomain =
MInt(rcvBufferAll[n][
MLong(
b * bufSizePerBody + 1)]);
1702 const MInt localId = getLocalBodyId(globalBodyId);
1705 m_debugFileStream <<
"received: " << globalBodyId <<
" with localId " << localId <<
" and new homeDomain "
1706 << newHomeDomain <<
"from " << neighborDomain(n) << std::endl;
1709 if(newHomeDomain == domainId()) {
1712 "ERROR: Body " + std::to_string(globalBodyId) +
" has not been on domain " + std::to_string(domainId())
1715 MInt oldHomeDomainId = neighborDomain(n);
1716 remoteBodiesToLocal.emplace_back(oldHomeDomainId, globalBodyId);
1717 }
else if(localId != -1) {
1718 remoteBodiesNeighDomain.push_back({newHomeDomain, globalBodyId});
1726 for(
MUint i = 0; i < remoteBodiesToLocal.size(); i++) {
1727 if(m_noRemoteBodies <= 0) {
1728 mTerm(1, AT_,
"Domain: " + std::to_string(domainId()) +
" has no remote bodies that can change to local status!");
1730 MInt oldHomeDomainId = remoteBodiesToLocal[i].first;
1731 MInt globalId = remoteBodiesToLocal[i].second;
1732 MInt localId = getLocalBodyId(globalId);
1734 const MInt newIdx = m_noLocalBodies;
1737 m_debugFileStream <<
"B localId: " << localId <<
" globalId " << globalId <<
" newIdx " << newIdx
1738 <<
" globalIdNewIdx: " << getGlobalBodyId(newIdx) <<
" oldHomeDomain " << oldHomeDomainId
1742 if(noConnectingBodies() > 1) {
1743 m_bodies.swap(localId, newIdx);
1744 iter_swap(m_globalBodyIds.begin() + localId, m_globalBodyIds.begin() + newIdx);
1750 m_remoteDomainLocalBodies[oldHomeDomainId].push_back(newIdx);
1753 std::map<MInt, std::vector<MInt>> oldMapping(m_homeDomainRemoteBodies);
1754 for(
auto& [domain, bodies] : oldMapping) {
1756 for(
const MInt& body : bodies) {
1757 if(body == localId) {
1759 m_debugFileStream <<
"delete body " << body <<
" domain " << domain << std::endl;
1761 std::vector<MInt>* c = &m_homeDomainRemoteBodies[domain];
1762 c->erase(std::remove(c->begin(), c->end(), localId), c->end());
1768 for(
MInt& body : m_homeDomainRemoteBodies[domain]) {
1769 if(body < localId) {
1777 printBodyDomainConnections();
1783 MBool found =
false;
1784 for(
const auto& arr : remoteBodiesNeighDomain) {
1785 const MInt newHomeDomain = arr[0];
1786 const MInt globalId = arr[1];
1788 const MInt NewLocalId = getLocalBodyId(globalId);
1790 for(
const auto& [domain, bodies] : m_homeDomainRemoteBodies) {
1791 if(domain == domainId())
continue;
1792 for(
const auto& bodyId : bodies) {
1793 if(getGlobalBodyId(bodyId) == globalId) {
1796 if(domain != newHomeDomain) {
1797 std::vector<MInt>* c = &m_homeDomainRemoteBodies[domain];
1798 c->erase(std::remove(c->begin(), c->end(), NewLocalId), c->end());
1800 m_homeDomainRemoteBodies[newHomeDomain].push_back(NewLocalId);
1805 <<
"something went wrong, domain should be diff from newHomeDomain in remoteBodiesNeighDomain! "
1806 <<
"Domain is " << domain <<
" newHomeDomain is " << newHomeDomain << std::endl;
1814 m_debugFileStream <<
"end of exchange: " << std::endl;
1815 printBodyDomainConnections();
1830 if(m_associatedDummyBodies.empty())
return;
1832 for(
const auto& [bodyId, dummyId] : m_associatedDummyBodies) {
1833 MBool outside = -1 != grid().raw().findContainingHaloCell(&a_bodyCenter(bodyId, 0), -1, domainId(),
true,
nullptr);
1836 m_bodies.swap(bodyId, dummyId);
1838 m_debugFileStream <<
"body " << bodyId <<
" and associated dummyBody " << dummyId <<
" were swapped!"
1860 m_debugFileStream <<
"entering updateBodyDomainConnections on domain " << domainId() << std::endl;
1861 printBodyDomainConnections();
1864 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1868 MInt globDomain = neighborDomain(i);
1869 for(
MInt bodyId = 0; bodyId < noConnectingBodies(); bodyId++) {
1870 MBool alreadyInside = std::binary_search(m_remoteDomainLocalBodies[globDomain].begin(),
1871 m_remoteDomainLocalBodies[globDomain].end(), bodyId);
1873 MBool alreadySelfMapped = m_periodicBC && hasAssociatedDummyBody(bodyId);
1876 m_debugFileStream <<
"D" << globDomain <<
" lBody " << bodyId <<
" already in mapping " << alreadyInside
1877 <<
" selfmapped " << alreadySelfMapped << std::endl;
1878 for(
auto&&
b : m_remoteDomainLocalBodies[globDomain]) {
1879 m_debugFileStream <<
"[" << globDomain <<
"," <<
b <<
"]" << std::endl;
1881 m_debugFileStream << std::endl;
1883 if(alreadyInside || alreadySelfMapped) {
1887 MInt intersectingCellId =
1888 grid().raw().intersectingWithHaloCells(&a_bodyCenter(bodyId, 0), m_infoDiameter / 2.0, i,
true);
1889 if(intersectingCellId != -1) {
1890 if(domainId() == globDomain && m_periodicBC
1891 && grid().raw().a_hasProperty(intersectingCellId, Cell::IsPeriodic)) {
1895 createDummyBody(bodyId);
1896 }
else if(isLocalBody(bodyId)) {
1898 std::vector<MInt>* bodyIds = &(m_remoteDomainLocalBodies[globDomain]);
1899 if(!std::binary_search(bodyIds->begin(), bodyIds->end(), bodyId)) {
1901 bodyIds->insert(std::upper_bound(bodyIds->begin(), bodyIds->end(), bodyId), bodyId);
1911 std::vector<MInt> removeList;
1912 for(
const MInt& bodyId : m_remoteDomainLocalBodies[globDomain]) {
1914 MInt intersectingCellId =
1915 grid().raw().intersectingWithHaloCells(&a_bodyCenter(bodyId, 0), m_infoDiameter / 2.0, i,
true);
1916 if(intersectingCellId == -1) {
1919 removeList.push_back(bodyId);
1924 if(!removeList.empty()) {
1926 for(
const MInt& body : removeList) {
1927 removeListS += std::to_string(body) +
", ";
1929 removeListS +=
"] ";
1930 m_debugFileStream <<
"RemoveList for domain " << domainId() <<
" " << removeListS
1931 <<
" neighborDomain: " << neighborDomain(i) << std::endl;
1935 for(
const auto& body : removeList) {
1937 std::vector<MInt>* bodies = &m_remoteDomainLocalBodies[neighborDomain(i)];
1938 bodies->erase(std::remove(bodies->begin(), bodies->end(), body), bodies->end());
1946 m_periodicShift.clear();
1948 for(
MInt i = 0; i < noNeighborDomains(); i++) {
1949 MInt globDomain = neighborDomain(i);
1951 if(globDomain == domainId())
continue;
1953 for(
const auto& bodyId : m_remoteDomainLocalBodies[globDomain]) {
1954 std::array<MFloat, nDim> center{};
1955 for(
MInt n = 0; n < nDim; n++) {
1956 center[n] = a_bodyCenter(bodyId, n);
1958 const MInt intersectingCellId =
1959 grid().raw().intersectingWithHaloCells(center.data(), m_infoDiameter / 2.0, i,
true);
1960 std::array<MFloat, nDim> tmpShift{};
1961 for(
MInt n = 0; n < nDim; n++) {
1962 tmpShift[n] = calculatePeriodicShift(intersectingCellId, n);
1964 const MInt globalDomain = neighborDomain(i);
1965 m_periodicShift[globalDomain][bodyId] = tmpShift;
1970 for(
const auto& [localBodyId, dummyBodyId] : m_associatedDummyBodies) {
1971 std::array<MFloat, nDim> center{};
1972 for(
MInt n = 0; n < nDim; n++) {
1973 center[n] = a_bodyCenter(localBodyId, n);
1975 const MInt intersectingCellId =
1976 grid().raw().intersectingWithHaloCells(center.data(), m_infoDiameter / 2.0, 0,
true);
1977 std::array<MFloat, nDim> tmpShift{};
1978 for(
MInt n = 0; n < nDim; n++) {
1979 tmpShift[n] = calculatePeriodicShift(intersectingCellId, n);
1981 m_periodicShift[domainId()][localBodyId] = tmpShift;
1986 for(
const auto& [domain, bodies] : m_periodicShift) {
1987 periodicShiftS +=
"on domain " + std::to_string(domain) +
" periodic Shifts are: \n";
1988 for(
const auto& [bodyId, shift] : bodies) {
1989 periodicShiftS +=
" bodyId: " + std::to_string(bodyId) +
" [";
1990 for(
MInt n = 0; n < nDim; n++) {
1991 periodicShiftS += std::to_string(shift[n]) +
" ";
1993 periodicShiftS +=
"] \n";
1996 m_debugFileStream << periodicShiftS;
2010 MInt newBodyId = noCollectorBodies();
2012 m_associatedDummyBodies[bodyId] = newBodyId;
2013 m_globalBodyIds.push_back(getGlobalBodyId(bodyId));
2016 m_debugFileStream <<
"Self-mapping case, adding dummy body to collector at " << newBodyId
2017 <<
" associated with bodyId " << bodyId << std::endl;
2020 a_bodyRadius(newBodyId) = a_bodyRadius(bodyId);
2021 a_bodyDensityRatio(newBodyId) = a_bodyDensityRatio(bodyId);
2022 a_bodyTemperature(newBodyId) = a_bodyTemperature(bodyId);
2023 a_bodyHeatFlux(newBodyId) = a_bodyHeatFlux(bodyId);
2024 for(
MInt n = 0; n < nDim; n++) {
2025 a_bodyRadii(newBodyId, n) = a_bodyRadii(bodyId, n);
2026 a_bodyInertia(newBodyId, n) = a_bodyInertia(bodyId, n);
2046 const MInt n = direction;
2047 const MBool periodicDir = grid().raw().periodicCartesianDir(n);
2048 const MBool periodicCell = grid().raw().a_hasProperty(intersectingCellId, Cell::IsPeriodic);
2049 if(m_periodicBC && periodicDir && periodicCell) {
2050 if(grid().raw().periodicCartesianDir(n)) {
2051 const MFloat cellCoordinate = grid().raw().a_coordinate(intersectingCellId, n);
2055 if(sign1 == 1 && sign2 == 1) {
2057 }
else if(sign1 == -1 && sign2 == -1) {
2060 shift = m_globDomainLength[n] * sign;
2078 std::vector<MInt> noToRecv(noNeighborDomains());
2079 exchangeBufferLengthsNeighbor(noToRecv, m_remoteDomainLocalBodies);
2081 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
2082 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
2085 std::vector<std::vector<MFloat>> rcvBufferAll(noNeighborDomains());
2086 MInt bufSizePerBody = 1 + nDim * 1 + nRot * 2 + nQuat * 2 + 3;
2089 if(a_bodyType() != Shapes::Sphere) {
2090 bufSizePerBody += nDim;
2093 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2094 rcvBufferAll[n].resize(noToRecv[n] * bufSizePerBody);
2098 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2104 2, mpiComm(), &mpi_recv_req[i], AT_,
"recv predict");
2110 std::vector<std::vector<MFloat>> sendBufferAll(noNeighborDomains());
2111 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2112 MInt globDomain = neighborDomain(i);
2113 if(domainId() == globDomain)
continue;
2115 auto& tmpSendBuffer = sendBufferAll[i];
2116 tmpSendBuffer.resize(bufSizePerBody * m_remoteDomainLocalBodies[globDomain].size());
2118 for(
const auto& body : m_remoteDomainLocalBodies[globDomain]) {
2121 tmpSendBuffer[idx * bufSizePerBody] = (
MFloat)getGlobalBodyId(body);
2124 for(
MInt n = 0; n < nDim; n++) {
2125 tmpSendBuffer[idx * bufSizePerBody + paraCount + n] = a_bodyCenter(body, n);
2130 for(
MInt r = 0; r < nRot; r++) {
2131 tmpSendBuffer[idx * bufSizePerBody + paraCount + r] = a_angularAccelerationBody(body, r);
2132 tmpSendBuffer[idx * bufSizePerBody + paraCount + nRot + r] = a_angularVelocityBodyT1B2(body, r);
2134 paraCount += 2 * nRot;
2136 for(
MInt q = 0; q < nQuat; q++) {
2137 tmpSendBuffer[idx * bufSizePerBody + paraCount + q] = a_bodyQuaternionT1(body, q);
2138 tmpSendBuffer[idx * bufSizePerBody + paraCount + nQuat + q] = a_bodyQuaternionT1B2(body, q);
2140 paraCount += 2 * nQuat;
2142 tmpSendBuffer[idx * bufSizePerBody + paraCount] = a_bodyRadius(body);
2144 if(a_bodyType() != Shapes::Sphere) {
2145 for(
MInt n = 0; n < nDim; n++) {
2146 tmpSendBuffer[idx * bufSizePerBody + paraCount + n] = a_bodyRadii(body, n);
2151 tmpSendBuffer[idx * bufSizePerBody + paraCount] = a_bodyDensityRatio(body);
2153 tmpSendBuffer[idx * bufSizePerBody + paraCount] = a_bodyTemperature(body);
2160 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2161 MInt globDomain = neighborDomain(i);
2162 if(m_remoteDomainLocalBodies[globDomain].empty()) {
2167 2, mpiComm(), &mpi_send_req[i], AT_,
"send predict");
2171 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2172 MInt globDomain = neighborDomain(i);
2173 if(!m_remoteDomainLocalBodies[globDomain].empty()) {
2174 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
2178 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
2185 std::list<std::pair<MInt, MInt>> remoteBodyRemoveList;
2186 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
2187 for(
const MInt rBody : bodies) {
2188 remoteBodyRemoveList.push_back(std::make_pair(homeDomain, rBody));
2194 for(
const auto& body : remoteBodyRemoveList) {
2195 removeListS +=
"[" + std::to_string(body.first) +
"," + std::to_string(body.second) +
"]";
2197 removeListS +=
"] ";
2198 m_debugFileStream <<
"Before: RemoveList for domain " << domainId() <<
" " << removeListS << std::endl;
2199 printBodyDomainConnections();
2203 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2204 MInt globalDomain = neighborDomain(n);
2206 for(
MInt b = 0;
b < noToRecv[n];
b++) {
2208 MInt remoteBodyId = rcvBufferAll[n][
b * bufSizePerBody];
2212 m_debugFileStream <<
"domain: " << domainId() <<
" receives remoteBodyId: " << remoteBodyId <<
" from "
2213 << globalDomain <<
" with locId " << getLocalBodyId(remoteBodyId) << std::endl;
2216 MInt localBodyId = getLocalBodyId(remoteBodyId);
2217 if(localBodyId != -1) {
2219 std::list<std::pair<MInt, MInt>>*
a = &remoteBodyRemoveList;
2220 a->erase(std::remove_if(
a->begin(),
a->end(),
2221 [&localBodyId](std::pair<MInt, MInt> x) { return x.second == localBodyId; }),
2224 for(
const auto& [domain, bodies] : m_homeDomainRemoteBodies) {
2225 if(bodies.empty())
continue;
2227 for(
const auto& bodyId : bodies) {
2230 if(domain != globalDomain && localBodyId == bodyId) {
2232 std::vector<MInt>* c = &m_homeDomainRemoteBodies[domain];
2233 c->erase(std::remove(c->begin(), c->end(), localBodyId), c->end());
2234 m_homeDomainRemoteBodies[globalDomain].push_back(localBodyId);
2242 std::vector<MInt>& remoteBodies = m_homeDomainRemoteBodies[globalDomain];
2243 auto actualPos = std::find(remoteBodies.begin(), remoteBodies.end(), localBodyId);
2244 auto wantedPos = remoteBodies.begin() + mapIdx;
2245 std::iter_swap(actualPos, wantedPos);
2247 m_debugFileStream <<
"SWAP SWAP";
2248 for(
auto&& r : remoteBodies) {
2249 m_debugFileStream << r <<
",";
2251 m_debugFileStream << std::endl;
2257 if(m_associatedDummyBodies.empty()) {
2259 m_globalBodyIds.push_back(remoteBodyId);
2261 m_homeDomainRemoteBodies[globalDomain].push_back(m_globalBodyIds.size() - 1);
2266 MInt newIdx = noConnectingBodies();
2267 m_bodies.insert(newIdx);
2268 m_globalBodyIds.insert(m_globalBodyIds.begin() + newIdx, remoteBodyId);
2270 m_homeDomainRemoteBodies[globalDomain].push_back(newIdx);
2272 for(
auto& [bodyId, dummyId] : m_associatedDummyBodies) {
2278 const MInt newLocalBodyId = getLocalBodyId(remoteBodyId);
2280 for(
MInt d = 0; d < nDim; d++) {
2281 a_bodyCenter(newLocalBodyId, d) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + d];
2285 for(
MInt r = 0; r < nRot; r++) {
2286 a_angularAccelerationBody(newLocalBodyId, r) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + r];
2287 a_angularVelocityBodyT1B2(newLocalBodyId, r) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + nRot + r];
2289 paraCount += 2 * nRot;
2291 for(
MInt q = 0; q < nQuat; q++) {
2292 a_bodyQuaternionT1(newLocalBodyId, q) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + q];
2293 a_bodyQuaternionT1B2(newLocalBodyId, q) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + nQuat + q];
2295 paraCount += 2 * nQuat;
2297 a_bodyRadius(newLocalBodyId) = rcvBufferAll[n][
b * bufSizePerBody + paraCount];
2299 if(a_bodyType() != Shapes::Sphere) {
2300 for(
MInt d = 0; d < nDim; d++) {
2301 a_bodyRadii(newLocalBodyId, d) = rcvBufferAll[n][
b * bufSizePerBody + paraCount + d];
2305 std::fill_n(&a_bodyRadii(newLocalBodyId, 0), nDim, a_bodyRadius(newLocalBodyId));
2308 a_bodyDensityRatio(newLocalBodyId) = rcvBufferAll[n][
b * bufSizePerBody + paraCount];
2310 a_bodyTemperature(newLocalBodyId) = rcvBufferAll[n][
b * bufSizePerBody + paraCount];
2312 a_bodyHeatFlux(newLocalBodyId) = 0.0;
2315 const MInt remoteBodyIntersectsWithDomainId =
2316 grid().raw().intersectingWithHaloCells(&a_bodyCenter(newLocalBodyId, 0), m_infoDiameter / 2.0, 0,
true);
2317 if(m_periodicBC && !hasAssociatedDummyBody(newLocalBodyId) && remoteBodyIntersectsWithDomainId != -1
2318 && grid().raw().a_hasProperty(remoteBodyIntersectsWithDomainId, Cell::IsPeriodic)) {
2319 createDummyBody(newLocalBodyId);
2321 std::array<MFloat, nDim> center{};
2322 for(
MInt d = 0; d < nDim; d++) {
2323 center[n] = a_bodyCenter(newLocalBodyId, n);
2326 for(
MInt d = 0; d < nDim; d++) {
2327 m_periodicShift[domainId()][newLocalBodyId][d] = calculatePeriodicShift(remoteBodyIntersectsWithDomainId, d);
2330 initRemoteDummyBodyData(newLocalBodyId);
2336 if(!remoteBodyRemoveList.empty()) {
2338 for(
const auto& body : remoteBodyRemoveList) {
2339 removeListS +=
"[" + std::to_string(body.first) +
"," + std::to_string(body.second) +
"]";
2341 removeListS +=
"] ";
2342 m_debugFileStream <<
"After: RemoveList for domain " << domainId() <<
" " << removeListS << std::endl;
2346 deleteIrrelevantBodies(remoteBodyRemoveList);
2360 const MInt dummyId = m_associatedDummyBodies[bodyId];
2361 if(isRemoteBody(bodyId)) {
2363 for(
MInt n = 0; n < nDim; n++) {
2364 a_bodyCenter(dummyId, n) = a_bodyCenter(bodyId, n) + m_periodicShift[domainId()][bodyId][n];
2365 a_bodyVelocity(dummyId, n) = a_bodyVelocity(bodyId, n);
2366 a_bodyAcceleration(dummyId, n) = a_bodyAcceleration(bodyId, n);
2367 a_bodyForce(dummyId, n) = -a_bodyForce(bodyId, n);
2368 a_bodyTorque(dummyId, n) = a_bodyTorque(bodyId, n);
2370 for(
MInt r = 0; r < nRot; r++) {
2371 a_angularVelocity(dummyId, r) = a_angularVelocity(bodyId, r);
2372 a_angularVelocityBody(dummyId, r) = a_angularVelocityBody(bodyId, r);
2374 for(
MInt q = 0; q < nQuat; q++) {
2375 a_bodyQuaternionT1(dummyId, q) = a_bodyQuaternionT1(bodyId, q);
2379 m_debugFileStream <<
"Something went wrong, body with localId: " << bodyId
2380 <<
" is not a remoteBody -> dummyBodyData cannot be initialized!" << std::endl;
2398 if(m_noLocalBodies <= 0) {
2399 mTerm(1, AT_,
"Domain: " + std::to_string(domainId()) +
" has no local bodies that can change to remote status!");
2402 const MInt newIdx = m_noLocalBodies - 1;
2404 if(hasAssociatedDummyBody(oldBodyId)) {
2405 deleteDummyBody(oldBodyId);
2409 if(noConnectingBodies() > 0) {
2410 m_bodies.swap(collectorId, newIdx);
2411 iter_swap(m_globalBodyIds.begin() + collectorId, m_globalBodyIds.begin() + newIdx);
2422 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2423 MInt globDomain = neighborDomain(n);
2424 std::vector<MInt>* bodies = &m_remoteDomainLocalBodies[globDomain];
2427 auto swappedIt = std::find(bodies->begin(), bodies->end(), newIdx);
2428 if(swappedIt != bodies->end()) {
2430 bodies->erase(std::remove(bodies->begin(), bodies->end(), newIdx), bodies->end());
2433 bodies->erase(std::remove(bodies->begin(), bodies->end(), collectorId), bodies->end());
2436 if(hasAssociatedDummyBody(newIdx)) {
2437 m_associatedDummyBodies.erase(newIdx);
2438 m_associatedDummyBodies[newIdx] = collectorId;
2442 m_homeDomainRemoteBodies[domain].push_back(newIdx);
2459 removeList.sort([](
const std::pair<MInt, MInt>&
a,
const std::pair<MInt, MInt>&
b) {
return a.second >
b.second; });
2461 std::vector<MInt> removeListGlobIds;
2462 for(
const auto& [homeDomain, body] : removeList) {
2463 removeListGlobIds.push_back(getGlobalBodyId(body));
2466 MInt collectorShiftIdx = 0;
2467 for(
const auto& [homeDomain, body] : removeList) {
2468 m_bodyWasDeleted =
true;
2470 m_debugFileStream <<
"Deleting remotebody " << body <<
" on domain " << domainId() << std::endl;
2473 m_globalBodyIds.erase(
2474 std::remove(m_globalBodyIds.begin(), m_globalBodyIds.end(), removeListGlobIds[collectorShiftIdx]),
2475 m_globalBodyIds.end());
2477 m_bodies.removeAndShift(body);
2480 m_homeDomainRemoteBodies[homeDomain].erase(
2481 std::remove(m_homeDomainRemoteBodies[homeDomain].begin(), m_homeDomainRemoteBodies[homeDomain].end(), body),
2482 m_homeDomainRemoteBodies[homeDomain].end());
2484 collectorShiftIdx++;
2486 auto aDBCopy = m_associatedDummyBodies;
2487 for(
auto& [bodyId, dummyId] : aDBCopy) {
2488 if(bodyId == body) {
2489 deleteDummyBody(bodyId, collectorShiftIdx);
2495 m_debugFileStream <<
"after deletion: " << std::endl;
2496 printBodyDomainConnections();
2500 for(std::list<std::pair<MInt, MInt>>::const_iterator it = removeList.cbegin(); it != removeList.cend(); it++) {
2501 for(
auto& [domain, bodies] : m_homeDomainRemoteBodies) {
2503 for(
MInt& body : bodies) {
2505 m_debugFileStream <<
"body " << body <<
" it " << it->second << std::endl;
2507 if(body > it->second) {
2512 for(
auto& [bodyId, dummyId] : m_associatedDummyBodies) {
2514 m_debugFileStream <<
"body " << bodyId <<
" with Dummybody " << dummyId <<
" it " << it->second << std::endl;
2516 if(dummyId > it->second) {
2523 m_debugFileStream <<
"after deletion and update of mappings: " << std::endl;
2524 printBodyDomainConnections();
2540 const MInt dummyBodyId = m_associatedDummyBodies[bodyId] - collectorShift;
2543 m_debugFileStream <<
"Deleting Dummy Body " << m_associatedDummyBodies[bodyId] <<
" with corresponding bodyId "
2544 << bodyId << std::endl;
2547 m_associatedDummyBodies.erase(bodyId);
2548 m_globalBodyIds.erase(std::remove(m_globalBodyIds.begin(), m_globalBodyIds.end(), dummyBodyId),
2549 m_globalBodyIds.end());
2551 m_bodies.removeAndShift(dummyBodyId);
2554 m_bodyWasDeleted =
true;
2557 printBodyDomainConnections();
2567 std::vector<std::vector<MInt>> bodyIdsForRemoteDomain;
2568 std::vector<std::vector<MInt>> homeDomainIdsForRemoteDomain;
2571 std::vector<std::vector<MInt>> bodyIdsForHomeDomain;
2572 std::vector<std::vector<MInt>> remoteDomainIdsForHomeDomain;
2573 std::vector<std::vector<std::array<MFloat, nDim>>> shiftForHomeDomain;
2576 bodyIdsForRemoteDomain.clear();
2577 bodyIdsForRemoteDomain.resize(noNeighborDomains());
2579 homeDomainIdsForRemoteDomain.clear();
2580 homeDomainIdsForRemoteDomain.resize(noNeighborDomains());
2583 bodyIdsForHomeDomain.clear();
2584 bodyIdsForHomeDomain.resize(noHomeDomains());
2586 remoteDomainIdsForHomeDomain.clear();
2587 remoteDomainIdsForHomeDomain.resize(noHomeDomains());
2589 shiftForHomeDomain.clear();
2590 shiftForHomeDomain.resize(noHomeDomains());
2593 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2595 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
2596 for(
const auto& body : bodies) {
2598 std::array<MFloat, nDim> center{};
2599 for(
MInt n = 0; n < nDim; n++) {
2600 center[n] = a_bodyCenter(body, n);
2602 const MInt intersectingCellId =
2603 grid().raw().intersectingWithHaloCells(center.data(), m_infoDiameter / 2.0, i,
true);
2604 if(intersectingCellId != -1) {
2606 bodyIdsForRemoteDomain[i].push_back(getGlobalBodyId(body));
2607 homeDomainIdsForRemoteDomain[i].push_back(homeDomain);
2610 const MInt remoteDomain = neighborDomain(i);
2612 if(homeDomain == remoteDomain) {
2615 bodyIdsForHomeDomain[count].push_back(getGlobalBodyId(body));
2616 remoteDomainIdsForHomeDomain[count].push_back(remoteDomain);
2618 std::array<MFloat, nDim> shiftVector{};
2619 for(
MInt n = 0; n < nDim; n++) {
2620 const MFloat shift = calculatePeriodicShift(intersectingCellId, n);
2621 shiftVector[n] = shift;
2623 shiftForHomeDomain[count].push_back(shiftVector);
2630 std::map<MInt, std::vector<MInt>> tmpRemoteMap;
2632 exchangeNeighborNeighborRemote(bodyIdsForRemoteDomain, homeDomainIdsForRemoteDomain, tmpRemoteMap);
2633 exchangeNeighborNeighborHome(bodyIdsForHomeDomain, remoteDomainIdsForHomeDomain, shiftForHomeDomain);
2636 for(
auto [homeDomainId, remoteBodyIds] : tmpRemoteMap) {
2637 for(
auto remoteBodyId : remoteBodyIds) {
2638 if(homeDomainId == domainId())
continue;
2639 const std::vector<MInt>* bodyIds = &(m_homeDomainRemoteBodies[homeDomainId]);
2641 if(!std::binary_search(bodyIds->begin(), bodyIds->end(), remoteBodyId)) {
2642 std::cout <<
"In Timestep " <<
globalTimeStep <<
"indirect Neighborstuff" << std::endl;
2645 m_homeDomainRemoteBodies[homeDomainId].push_back(remoteBodyId);
2653 std::vector<std::vector<MInt>>& homeDomainIdsForRemoteDomain,
2654 std::map<
MInt, std::vector<MInt>>& tmpRemoteMap) {
2656 std::vector<MPI_Request> mpi_send_req(noNeighborDomains(), MPI_REQUEST_NULL);
2657 std::vector<MPI_Request> mpi_recv_req(noNeighborDomains(), MPI_REQUEST_NULL);
2660 const MInt bufSizePerBody = 1 + 1;
2661 std::vector<MInt> noToSend(noNeighborDomains());
2662 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2663 noToSend[n] = bodyIdsForRemoteDomain[n].size();
2666 std::vector<std::vector<MInt>> sendBufferAll(noNeighborDomains());
2667 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2668 sendBufferAll[n].resize(noToSend[n] * bufSizePerBody);
2669 for(
MInt b = 0;
b < noToSend[n];
b++) {
2670 sendBufferAll[n][
b * bufSizePerBody] = bodyIdsForRemoteDomain[n][
b];
2671 sendBufferAll[n][
b * bufSizePerBody + 1] = homeDomainIdsForRemoteDomain[n][
b];
2675 std::vector<MInt> noToRecv(noNeighborDomains());
2676 exchangeBufferLengthsNeighbor(noToRecv, bodyIdsForRemoteDomain);
2679 std::vector<std::vector<MInt>> recvBufferAll(noNeighborDomains());
2680 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2681 recvBufferAll[n].resize(noToRecv[n] * bufSizePerBody);
2685 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2687 2, mpiComm(), &mpi_recv_req[n], AT_,
"recv neighbor-neighbor exchange");
2691 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2693 2, mpiComm(), &mpi_send_req[n], AT_,
"send neighbor-neighbor exchange");
2697 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2698 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
2699 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
2703 for(
MInt n = 0; n < noNeighborDomains(); n++) {
2704 for(
MInt b = 0;
b < noToRecv[n];
b++) {
2705 const MInt remoteBodyId = getLocalBodyId(recvBufferAll[n][
b * bufSizePerBody]);
2706 const MInt homeDomain = recvBufferAll[n][
b * bufSizePerBody + 1];
2707 const std::vector<MInt>* bodyIds = &(tmpRemoteMap[homeDomain]);
2709 if(!std::binary_search(bodyIds->begin(), bodyIds->end(), remoteBodyId)) {
2710 tmpRemoteMap[homeDomain].push_back(remoteBodyId);
2718 std::vector<std::vector<MInt>>& bodyIdsForHomeDomain,
2719 std::vector<std::vector<MInt>>& remoteDomainIdsForHomeDomain,
2720 std::vector<std::vector<std::array<MFloat, nDim>>>& shiftForHomeDomain) {
2722 std::vector<MPI_Request> mpi_send_req(noHomeDomains(), MPI_REQUEST_NULL);
2723 std::vector<MPI_Request> mpi_recv_req(noRemoteDomains(), MPI_REQUEST_NULL);
2726 std::vector<MInt> noToRecv(noRemoteDomains());
2729 const MInt bufSizePerBody = 1 + 1 + nDim;
2730 std::vector<MInt> noToSend(noHomeDomains());
2731 for(
MInt n = 0; n < noHomeDomains(); n++) {
2732 noToSend[n] = bodyIdsForHomeDomain[n].size();
2735 exchangeBufferLengthsRemoteToHome(noToRecv, noToSend);
2738 std::vector<std::vector<MFloat>> recvBufferAll(noRemoteDomains());
2739 for(
MInt n = 0; n < noRemoteDomains(); n++) {
2740 recvBufferAll[n].resize(noToRecv[n] * bufSizePerBody);
2744 std::vector<std::vector<MFloat>> sendBufferAll(noHomeDomains());
2745 for(
MInt n = 0; n < noHomeDomains(); n++) {
2746 sendBufferAll[n].resize(noToSend[n] * bufSizePerBody);
2747 for(
MInt b = 0;
b < noToSend[n];
b++) {
2748 sendBufferAll[n][
b * bufSizePerBody] = bodyIdsForHomeDomain[n][
b];
2749 sendBufferAll[n][
b * bufSizePerBody + 1] = remoteDomainIdsForHomeDomain[n][
b];
2750 for(
MInt i = 0; i < nDim; i++) {
2751 sendBufferAll[n][
b * bufSizePerBody + 2 + i] = shiftForHomeDomain[n][
b][i];
2758 for(
const auto& [remoteDomain, bodies] : m_remoteDomainLocalBodies) {
2759 if(noToRecv[count]) {
2761 remoteDomain, 2, mpiComm(), &mpi_recv_req[count], AT_,
"recv neighbor-neighbor exchange");
2768 for(
const auto& [homeDomain, bodies] : m_homeDomainRemoteBodies) {
2769 if(noToSend[count]) {
2771 homeDomain, 2, mpiComm(), &mpi_send_req[count], AT_,
"send neighbor-neighbor exchange");
2777 for(
MInt i = 0; i < noHomeDomains(); i++) {
2779 MPI_Wait(&mpi_send_req[i], MPI_STATUS_IGNORE, AT_);
2783 for(
MInt i = 0; i < noRemoteDomains(); i++) {
2785 MPI_Wait(&mpi_recv_req[i], MPI_STATUS_IGNORE, AT_);
2790 const MInt currNoRemoteDomains = noRemoteDomains();
2791 for(
MInt n = 0; n < currNoRemoteDomains; n++) {
2792 for(
MInt b = 0;
b < noToRecv[n];
b++) {
2793 const MInt localBodyId = getLocalBodyId((
MInt)recvBufferAll[n][
b * bufSizePerBody]);
2794 const MInt remoteDomainId = (
MInt)recvBufferAll[n][
b * bufSizePerBody + 1];
2796 std::array<MFloat, nDim> shift{};
2797 for(
MInt i = 0; i < nDim; i++) {
2798 shift[i] = recvBufferAll[n][
b * bufSizePerBody + 2 + i];
2801 if(m_remoteDomainLocalBodies.find(remoteDomainId) != m_remoteDomainLocalBodies.end()) {
2802 std::vector<MInt>* bodyIds = &(m_remoteDomainLocalBodies[remoteDomainId]);
2803 if(std::binary_search(bodyIds->begin(), bodyIds->end(), localBodyId)) {
2807 m_remoteDomainLocalBodies[remoteDomainId].push_back(localBodyId);
2808 m_periodicShift[remoteDomainId][localBodyId] = shift;
2823 std::vector<MString> sBodies;
2826 sBodies.emplace_back(
"");
2827 if(m_noLocalBodies != 0) {
2828 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
2829 sBodies[idx] += std::to_string(bodyId) +
" ";
2834 sBodies.emplace_back(
"");
2835 if(m_noRemoteBodies > 0) {
2836 for(
MInt bodyId = m_noLocalBodies; bodyId < noConnectingBodies(); bodyId++) {
2837 sBodies[idx] += std::to_string(bodyId) +
" ";
2842 sBodies.emplace_back(
"");
2843 if(m_noDummyBodies > 0) {
2844 for(
MInt bodyId = noConnectingBodies(); bodyId < noCollectorBodies(); bodyId++) {
2845 sBodies[idx] += std::to_string(bodyId) +
" ";
2850 sBodies.emplace_back(
"");
2851 if(!m_transferBodies.empty()) {
2852 for(
MInt i = 0; i < noNeighborDomains(); i++) {
2853 if(!m_transferBodies[i].empty()) {
2855 for(
MInt body : m_transferBodies[i]) {
2856 sTmp += std::to_string(body) +
" ";
2858 sBodies[idx] += std::to_string(neighborDomain(i)) +
": [" + sTmp +
" ] | ";
2864 sBodies.emplace_back(
"");
2865 if(!m_globalBodyIds.empty()) {
2866 for(
MUint localBodyId = 0; localBodyId < m_globalBodyIds.size(); localBodyId++) {
2868 "| localId: " + std::to_string(localBodyId) +
" globalId: " + std::to_string(m_globalBodyIds[localBodyId]);
2873 sBodies.emplace_back(
"");
2874 if(!m_remoteDomainLocalBodies.empty()) {
2875 for(
const auto& [domain, bodies] : m_remoteDomainLocalBodies) {
2876 for(
const auto& body : bodies) {
2877 sBodies[idx] += std::string(
" ") +
"[" + std::to_string(domain) +
", " + std::to_string(body) +
"]";
2883 sBodies.emplace_back(
"");
2884 if(!m_homeDomainRemoteBodies.empty()) {
2885 for(
const auto& [domain, bodies] : m_homeDomainRemoteBodies) {
2886 for(
const auto& body : bodies) {
2887 sBodies[idx] += std::string(
" ") +
"[" + std::to_string(domain) +
", " + std::to_string(body) +
"]";
2893 sBodies.emplace_back(
"");
2894 if(!m_associatedDummyBodies.empty()) {
2895 for(
const auto& [body, dummy] : m_associatedDummyBodies) {
2896 sBodies[idx] += std::string(
" ") +
"[" + std::to_string(body) +
", " + std::to_string(dummy) +
"]";
2901 m_debugFileStream <<
"--------------BODY INFO for domain: " << domainId() <<
"---------------------" << std::endl
2902 <<
" contains bodyIds [ " << sBodies[0] <<
" ]" << std::endl
2903 <<
" contains remoteBodyIds [ " << sBodies[1] <<
" ]" << std::endl
2904 <<
" contains dummyBodyIds [ " << sBodies[2] <<
" ]" << std::endl
2905 <<
" has transferBodies for neighbourdomain " << sBodies[3] << std::endl
2906 <<
" has following pairings: " << sBodies[4] << std::endl
2907 <<
" remote domain - local body pairings: " << sBodies[5] << std::endl
2908 <<
" home domain - remote body pairings: " << sBodies[6] << std::endl
2909 <<
" body - associated dummy pairings: " << sBodies[7] << std::endl
2910 <<
" collector has capacity: " << m_bodies.capacity() <<
" and size " << m_bodies.size()
2911 <<
" MaxNoBodies is " << m_maxNoBodies << std::endl;
2926 const MFloat dt = m_timestep;
2928 MFloat angularVelocityBodyT3B4[nRot]{};
2930 for(
MInt n = 0; n < nRot; n++) {
2931 angularVelocityBodyT3B4[n] =
2932 a_angularVelocityBodyT1B2(bodyId, n) + 0.25 * dt * a_angularAccelerationBody(bodyId, n);
2935 MFloat angularVelocityT3B4[nRot]{};
2936 transformToWorldFrame(&a_bodyQuaternionT1B2(bodyId, 0), angularVelocityBodyT3B4, angularVelocityT3B4);
2939 advanceQuaternion(angularVelocityT3B4, dt / 2, &a_bodyQuaternionT1B2(bodyId, 0), &a_bodyQuaternionT1(bodyId, 0));
2942 for(
MInt n = 0; n < nRot; n++) {
2943 a_angularVelocityBodyT1(bodyId, n) =
2944 a_angularVelocityBodyT1B2(bodyId, n) + 0.5 * dt * a_angularAccelerationBody(bodyId, n);
2946 transformToWorldFrame(&a_bodyQuaternionT1(bodyId, 0), &a_angularVelocityBodyT1(bodyId, 0),
2947 &a_angularVelocityT1(bodyId, 0));
2959 std::cerr <<
"predictRotation: No implementation for 2D!" << std::endl;
2971 const MFloat dt = m_timestep;
2973 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
2975 for(
MInt n = 0; n < nDim; n++) {
2977 a_bodyAcceleration(bodyId, n) =
2978 a_bodyForce(bodyId, n) / a_bodyMass(bodyId)
2979 + gravity[n] * (1.0 - 1.0 / a_bodyDensityRatio(bodyId));
2982 a_bodyVelocity(bodyId, n) = a_bodyVelocityOld(bodyId, n)
2983 + 0.5 * dt * (a_bodyAcceleration(bodyId, n) + a_bodyAccelerationOld(bodyId, n));
2986 a_bodyCenter(bodyId, n) =
2987 a_bodyCenterOld(bodyId, n) + dt * a_bodyVelocityOld(bodyId, n)
2988 + 0.25 *
POW2(dt) * (a_bodyAcceleration(bodyId, n) + a_bodyAccelerationOld(bodyId, n));
2992 correctRotation(bodyId);
2997 a_bodyTemperature(bodyId) = F1B2
2998 * (a_bodyTemperature(bodyId) + a_bodyTemperatureOld(bodyId)
2999 + dt * a_bodyHeatFlux(bodyId) / (m_bodyHeatCapacity * a_bodyMass(bodyId)));
3004 for(
MInt bodyId = 0; bodyId < m_noLocalBodies; bodyId++) {
3005 correctRotation(bodyId);
3023 const MFloat dt = m_timestep;
3025 MFloat torqueBodyT1[nRot];
3027 transformToBodyFrame(&a_bodyQuaternionT1(bodyId, 0), &a_torqueT1(bodyId, 0), torqueBodyT1);
3030 MFloat angularMomentumBody[nRot]{};
3031 for(
MInt n = 0; n < nRot; n++) {
3032 angularMomentumBody[n] = a_bodyInertia(bodyId, n) * a_angularVelocityBodyT1(bodyId, n);
3036 MFloat convectiveTerm[nRot]{};
3037 maia::math::cross(&a_angularVelocityBodyT1(bodyId, 0), &angularMomentumBody[0], &convectiveTerm[0]);
3040 MFloat angularAccelerationBodyT1[nRot]{};
3041 for(
MInt n = 0; n < nRot; n++) {
3042 angularAccelerationBodyT1[n] = 1 / a_bodyInertia(bodyId, n) * (torqueBodyT1[n] - convectiveTerm[n]);
3044 transformToWorldFrame(&a_bodyQuaternionT1(bodyId, 0), angularAccelerationBodyT1, &a_angularAccelerationT1(bodyId, 0));
3047 MFloat angularVelocityBodyT3B2[nRot]{};
3048 for(
MInt n = 0; n < nRot; n++) {
3049 angularVelocityBodyT3B2[n] = a_angularVelocityBodyT1B2(bodyId, n) + dt * angularAccelerationBodyT1[n];
3053 MFloat bodyQuaternionT3B2[nQuat]{};
3054 advanceQuaternion(&a_angularVelocityT1(bodyId, 0), dt, &a_bodyQuaternionT1B2(bodyId, 0), bodyQuaternionT3B2);
3057 MFloat angularVelocityT3B2[nRot]{};
3058 transformToWorldFrame(bodyQuaternionT3B2, angularVelocityBodyT3B2, angularVelocityT3B2);
3062 constexpr MLong size_quat = nQuat *
sizeof(
MFloat);
3064 memcpy(&a_angularAccelerationBody(bodyId, 0), angularAccelerationBodyT1, size_rot);
3065 memcpy(&a_angularVelocityBodyT1B2(bodyId, 0), angularVelocityBodyT3B2, size_rot);
3066 memcpy(&a_angularVelocityT1B2(bodyId, 0), angularVelocityT3B2, size_rot);
3067 memcpy(&a_bodyQuaternionT1B2(bodyId, 0), bodyQuaternionT3B2, size_quat);
3079 std::cerr <<
"correctRotation: No implementation for 2D!" << std::endl;
3096 const MFloat*
const vectorBody,
3097 MFloat*
const vectorWorld) {
3098 const MFloat uv = std::inner_product(bodyQuaternion, &bodyQuaternion[3], vectorBody, 0.0);
3099 const MFloat uu = std::inner_product(bodyQuaternion, &bodyQuaternion[3], bodyQuaternion, 0.0);
3100 const MFloat ss = bodyQuaternion[3] * bodyQuaternion[3];
3102 IF_CONSTEXPR(nDim == 3) {
maia::math::cross(bodyQuaternion, vectorBody, &ucv[0]); }
3106 for(
MInt n = 0; n < nRot; n++) {
3107 vectorWorld[n] = 2.0 * uv * bodyQuaternion[n] + (ss - uu) * vectorBody[n] + 2.0 * bodyQuaternion[3] * -(ucv[n]);
3125 const MFloat*
const vectorWorld,
3126 MFloat*
const vectorBody) {
3127 const MFloat uv = std::inner_product(bodyQuaternion, &bodyQuaternion[3], vectorWorld, 0.0);
3128 const MFloat uu = std::inner_product(bodyQuaternion, &bodyQuaternion[3], bodyQuaternion, 0.0);
3129 const MFloat ss = bodyQuaternion[3] * bodyQuaternion[3];
3131 IF_CONSTEXPR(nDim == 3) {
maia::math::cross(bodyQuaternion, vectorWorld, &ucv[0]); }
3135 for(
MInt n = 0; n < nRot; n++) {
3136 vectorBody[n] = 2.0 * uv * bodyQuaternion[n] + (ss - uu) * vectorWorld[n] + 2.0 * bodyQuaternion[3] * ucv[n];
3155 const MFloat vectorWorld[3]{vec[0], vec[1], vec[2]};
3156 transformToBodyFrame(bodyQuaternion, vectorWorld, vec);
3174 const MFloat angularVelMag = sqrt(std::inner_product(angularVelocity, &angularVelocity[nRot], angularVelocity, 0.0));
3176 MFloat qIncrement[4]{0.0, 0.0, 0.0, 1.0};
3178 if(angularVelMag > 0.0) {
3179 const MFloat angle = 0.5 * angularVelMag * dt;
3180 const MFloat tmp = sin(angle) / angularVelMag;
3181 qIncrement[0] = tmp * angularVelocity[0];
3182 qIncrement[1] = tmp * angularVelocity[1];
3183 qIncrement[2] = tmp * angularVelocity[2];
3184 qIncrement[3] = cos(angle);
3201 const MFloat& x = quaternion[0];
3202 const MFloat&
y = quaternion[1];
3203 const MFloat& z = quaternion[2];
3204 const MFloat& w = quaternion[3];
3206 MFloat& roll = angles[0];
3207 MFloat& pitch = angles[1];
3211 MFloat sinr_cosp = 2 * (w * x +
y * z);
3212 MFloat cosr_cosp = 1 - 2 * (x * x +
y *
y);
3213 roll = std::atan2(sinr_cosp, cosr_cosp);
3216 MFloat sinp = 2 * (w *
y - z * x);
3217 if(std::abs(sinp) >= 1) {
3218 pitch = std::copysign(M_PI / 2, sinp);
3220 pitch = std::asin(sinp);
3224 MFloat siny_cosp = 2 * (w * z + x *
y);
3225 MFloat cosy_cosp = 1 - 2 * (
y *
y + z * z);
3226 yaw = std::atan2(siny_cosp, cosy_cosp);
3243 MFloat elapsedTime = time;
3245 MBool& first = m_static_computeBodyProperties_first;
3246 MFloat*& amplitude = m_static_computeBodyProperties_amplitude;
3247 MFloat*& freqFactor = m_static_computeBodyProperties_freqFactor;
3248 MFloat*& initialBodyCenter = m_static_computeBodyProperties_initialBodyCenter;
3249 MFloat*& Strouhal = m_static_computeBodyProperties_Strouhal;
3250 MFloat*& mu2 = m_static_computeBodyProperties_mu2;
3251 MFloat*& liftStartAngle1 = m_static_computeBodyProperties_liftStartAngle1;
3252 MFloat*& liftEndAngle1 = m_static_computeBodyProperties_liftEndAngle1;
3253 MFloat*& liftStartAngle2 = m_static_computeBodyProperties_liftStartAngle2;
3254 MFloat*& liftEndAngle2 = m_static_computeBodyProperties_liftEndAngle2;
3255 MFloat*& circleStartAngle = m_static_computeBodyProperties_circleStartAngle;
3256 MFloat*& normal = m_static_computeBodyProperties_normal;
3257 MInt*& bodyToFunction = m_static_computeBodyProperties_bodyToFunction;
3258 MFloat*& rotAngle = m_static_computeBodyProperties_rotAngle;
3264 mAlloc(m_static_computeBodyProperties_amplitude, noEmbeddedBodies(),
"m_static_computeBodyProperties_amplitude",
3266 m_static_computeBodyProperties_amplitude[0] = F0;
3267 mAlloc(m_static_computeBodyProperties_freqFactor, noEmbeddedBodies(),
"m_static_computeBodyProperties_freqFactor",
3269 mAlloc(m_static_computeBodyProperties_initialBodyCenter,
3270 noEmbeddedBodies() * nDim,
3271 "m_static_computeBodyProperties_initialBodyCenter",
3273 mAlloc(m_static_computeBodyProperties_Strouhal, noEmbeddedBodies(),
"m_static_computeBodyProperties_Strouhal", AT_);
3274 mAlloc(m_static_computeBodyProperties_mu2, noEmbeddedBodies(),
"m_static_computeBodyProperties_mu2", AT_);
3275 mAlloc(m_static_computeBodyProperties_liftStartAngle1,
3277 "m_static_computeBodyProperties_liftStartAngle1",
3279 mAlloc(m_static_computeBodyProperties_liftEndAngle1, noEmbeddedBodies(),
3280 "m_static_computeBodyProperties_liftEndAngle1", AT_);
3281 mAlloc(m_static_computeBodyProperties_liftStartAngle2,
3283 "m_static_computeBodyProperties_liftStartAngle2",
3285 mAlloc(m_static_computeBodyProperties_liftEndAngle2, noEmbeddedBodies(),
3286 "m_static_computeBodyProperties_liftEndAngle2", AT_);
3287 mAlloc(m_static_computeBodyProperties_circleStartAngle,
3289 "m_static_computeBodyProperties_circleStartAngle",
3291 mAlloc(m_static_computeBodyProperties_normal, noEmbeddedBodies() * nDim,
"m_static_computeBodyProperties_normal",
3293 mAlloc(m_static_computeBodyProperties_bodyToFunction,
3295 "m_static_computeBodyProperties_bodyToFunction",
3297 mAlloc(m_static_computeBodyProperties_rotAngle, noEmbeddedBodies(),
"m_static_computeBodyProperties_rotAngle", AT_);
3300 for(
MInt k = 0; k < noEmbeddedBodies(); k++) {
3303 freqFactor[k] = 1.0;
3304 bodyToFunction[k] = 0;
3305 for(
MInt i = 0; i < nDim; i++) {
3306 initialBodyCenter[k * nDim + i] = F0;
3307 normal[k * nDim + i] = F0;
3309 normal[k * nDim + 0] = 1.0;
3310 liftStartAngle1[k] = F0;
3311 liftEndAngle1[k] = PI;
3312 liftStartAngle2[k] = 3.0 * PI;
3313 liftEndAngle2[k] = 4.0 * PI;
3314 circleStartAngle[k] = F0;
3331 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3332 amplitude[i] = Context::getSolverProperty<MFloat>(
"amplitudes", m_solverId, AT_, &litude[i], i);
3346 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3347 freqFactor[i] = Context::getSolverProperty<MFloat>(
"freqFactors", m_solverId, AT_, &freqFactor[i], i);
3362 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3364 Context::getSolverProperty<MInt>(
"bodyMovementFunctions", m_solverId, AT_, &bodyToFunction[i], i);
3367 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3368 Strouhal[i] = Context::getSolverProperty<MFloat>(
"Strouhal", m_solverId, AT_, &Strouhal[i], i);
3382 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3383 for(
MInt j = 0; j < nDim; j++) {
3384 initialBodyCenter[i * nDim + j] = Context::getSolverProperty<MFloat>(
3385 "initialBodyCenters", m_solverId, AT_, &initialBodyCenter[i * nDim + j], i * nDim + j);
3389 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3390 for(
MInt j = 0; j < nDim; j++) {
3391 normal[i * nDim + j] = Context::getSolverProperty<MFloat>(
"bodyMotionNormals", m_solverId, AT_,
3392 &normal[i * nDim + j], i * nDim + j);
3409 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3410 liftStartAngle1[i] =
3411 Context::getSolverProperty<MFloat>(
"liftStartAngles1", m_solverId, AT_, &liftStartAngle1[i], i);
3426 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3427 liftStartAngle2[i] =
3428 Context::getSolverProperty<MFloat>(
"liftStartAngles2", m_solverId, AT_, &liftStartAngle2[i], i);
3441 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3442 liftEndAngle1[i] = Context::getSolverProperty<MFloat>(
"liftEndAngles1", m_solverId, AT_, &liftEndAngle1[i], i);
3455 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3456 liftEndAngle2[i] = Context::getSolverProperty<MFloat>(
"liftEndAngles2", m_solverId, AT_, &liftEndAngle2[i], i);
3470 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3471 circleStartAngle[i] =
3472 Context::getSolverProperty<MFloat>(
"circleStartAngles", m_solverId, AT_, &circleStartAngle[i], i);
3485 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3486 rotAngle[i] = Context::getSolverProperty<MFloat>(
"rotAngle", m_solverId, AT_, &rotAngle[i], i);
3487 rotAngle[i] *= -PI / 180;
3491 for(
MInt k = 0; k < noEmbeddedBodies(); k++) {
3494 mu2[k] = freqFactor[k] * Strouhal[k] * F2 * PI;
3498 for(
MInt i = 0; i < noEmbeddedBodies(); i++) {
3499 if(bodyToFunction[i] == 6 || bodyToFunction[i] == 7 || bodyToFunction[i] == 9) {
3500 liftStartAngle1[i] = liftStartAngle1[i] * 2 * PI;
3501 liftEndAngle1[i] = liftEndAngle1[i] * 2 * PI;
3511 switch(bodyToFunction[bodyId]) {
3514 for(
MInt n = 0; n < nDim; n++) {
3521 switch(returnMode) {
3523 for(
MInt n = 0; n < nDim; n++) {
3524 bodyData[n] = amplitude[bodyId] * elapsedTime * normal[bodyId * nDim + n];
3528 for(
MInt n = 0; n < nDim; n++) {
3529 bodyData[n] = amplitude[bodyId] * normal[bodyId * nDim + n];
3533 for(
MInt n = 0; n < nDim; n++) {
3539 for(
MInt n = 0; n < nDim; n++) {
3547 angle = mu2[bodyId] * elapsedTime;
3548 switch(returnMode) {
3550 if(angle >= liftStartAngle1[bodyId] && angle <= liftEndAngle1[bodyId]) {
3551 for(
MInt n = 0; n < nDim; n++) {
3552 bodyData[n] = amplitude[bodyId] / mu2[bodyId] * sin(angle) * normal[bodyId * nDim + n];
3554 }
else if(angle < liftStartAngle1[bodyId]) {
3555 for(
MInt n = 0; n < nDim; n++) {
3558 }
else if(angle > liftEndAngle1[bodyId]) {
3559 for(
MInt n = 0; n < nDim; n++) {
3560 bodyData[n] = amplitude[bodyId] / mu2[bodyId] * sin(liftEndAngle1[bodyId]) * normal[bodyId * nDim + n];
3565 if(angle > liftStartAngle1[bodyId] && angle <= liftEndAngle1[bodyId]) {
3566 for(
MInt n = 0; n < nDim; n++) {
3567 bodyData[n] = amplitude[bodyId] *
cos(angle) * normal[bodyId * nDim + n];
3570 for(
MInt n = 0; n < nDim; n++) {
3576 if(angle > liftStartAngle1[bodyId] && angle <= liftEndAngle1[bodyId]) {
3577 for(
MInt n = 0; n < nDim; n++) {
3578 bodyData[n] = -amplitude[bodyId] * mu2[bodyId] * sin(angle) * normal[bodyId * nDim + n];
3581 for(
MInt n = 0; n < nDim; n++) {
3587 for(
MInt n = 0; n < nDim; n++) {
3595 mTerm(1, AT_,
"function type not implemented. Please check bodyMovementFunctions property!");
3599 if(returnMode == 1) {
3600 for(
MInt dir = 0; dir < nDim; dir++) {
3601 bodyData[dir] += initialBodyCenter[bodyId * nDim + dir];
3606 if(rotAngle[bodyId] > 0 || rotAngle[bodyId] < 0) {
3607 MFloat tmp0 = bodyData[0] *
cos(rotAngle[bodyId]) + bodyData[1] * sin(rotAngle[bodyId]);
3608 MFloat tmp1 = bodyData[1] *
cos(rotAngle[bodyId]) - bodyData[0] * sin(rotAngle[bodyId]);
3611 bodyData[2] = bodyData[2];
3630 for(
MInt n = 0; n < nDim; n++) {
3631 dist +=
POW2(coordinates[n] - a_bodyCenter(bodyId, n));
3634 dist = sqrt(
dist) - a_bodyRadius(bodyId);
3652 const MFloat x = coordinates[0] - a_bodyCenter(bodyId, 0);
3653 const MFloat y = coordinates[1] - a_bodyCenter(bodyId, 1);
3654 const MFloat z = coordinates[2] - a_bodyCenter(bodyId, 2);
3656 MFloat dist_cylinder = sqrt(
POW2(x) +
POW2(z)) - a_bodyRadius(bodyId);
3657 MFloat dist_caps = -
y - m_bodyHeight / 2;
3659 return std::max(dist_cylinder, dist_caps);
3675 const MFloat x = coordinates[0] - a_bodyCenter(bodyId, 0);
3676 const MFloat y = coordinates[1] - a_bodyCenter(bodyId, 1);
3678 const MFloat lim_x = std::max(x, -x);
3679 const MFloat lim_y = std::max(
y, -
y);
3683 IF_CONSTEXPR(nDim == 3) {
3684 const MFloat z = coordinates[2] - a_bodyCenter(bodyId, 2);
3685 const MFloat lim_z = std::max(z, -z);
3689 return dist - a_bodyRadius(bodyId);
3706 for(
MInt n = 0; n < nDim; n++) {
3707 relPos[n] = coordinates[n] - a_bodyCenter(bodyId, n);
3710 const MFloat*
const bodyQuaternion = &a_bodyQuaternionT1(bodyId, 0);
3711 transformToBodyFrame(bodyQuaternion, relPos);
3713 MFloat dist = findClosestPointEllipsoid(&relPos[0], bodyId);
3732 std::cerr <<
"Find Ellipse closest point 2D needs to be implemented! " << std::endl;
3751 std::ignore = bodyId;
3752 MFloat e[3] = {a_bodyRadii(bodyId, 0), a_bodyRadii(bodyId, 1), a_bodyRadii(bodyId, 2)};
3753 MFloat y[3] = {relPos[0], relPos[1], relPos[2]};
3760 for(i = 0; i < 3; ++i) {
3761 reflect[i] = (
y[i] < .0);
3771 }
else if(e[2] < e[1]) {
3785 }
else if(e[2] < e[0]) {
3796 std::array<MInt, 3> invpermute{};
3797 for(i = 0; i < 3; ++i) {
3798 invpermute[permute[i]] = i;
3801 std::array<MFloat, 3> locE{};
3802 std::array<MFloat, 3> locY{};
3803 for(i = 0; i < 3; ++i) {
3812 std::array<MFloat, 3> locX{};
3813 for(i = 0; i < 3; ++i) {
3814 ASSERT(!(locY[i] < F0),
"");
3815 locY[i] =
mMax(MFloatEps, locY[i]);
3817 MFloat distance = distancePointEllipsoid(locE, locY, locX);
3820 for(i = 0; i < 3; ++i) {
3830 if((
POW2(
y[0] / e[0]) +
POW2(
y[1] / e[1]) +
POW2(
y[2] / e[2])) < F1) {
3831 distance = -distance;
3852 std::array<MFloat, 3> x) {
3853 constexpr MFloat eps0 = 1e-12;
3854 constexpr MFloat eps1 = 1e-6;
3855 const MFloat dist0 = c_cellLengthAtMaxLevel();
3856 const MFloat dist1 = 10.0 * dist0;
3859 MFloat esqr[3] = {e[0] * e[0], e[1] * e[1], e[2] * e[2]};
3860 MFloat ey[3] = {e[0] *
y[0], e[1] *
y[1], e[2] *
y[2]};
3862 MFloat t0 = -esqr[2] + ey[2];
3863 MFloat t1 = -esqr[2] + sqrt(ey[0] * ey[0] + ey[1] * ey[1] + ey[2] * ey[2]);
3865 const int imax = 2 * std::numeric_limits<MFloat>::max_exponent;
3867 if(fabs(t1 - t0) < eps) t1 = t0 + F2 * eps;
3870 while(fabs(t1 - t0) > eps && i < imax) {
3871 while(fabs(t1 - t0) > eps && i < imax) {
3873 t = F1B2 * (t0 + t1);
3874 r[0] = ey[0] / (t + esqr[0]);
3875 r[1] = ey[1] / (t + esqr[1]);
3876 r[2] = ey[2] / (t + esqr[2]);
3877 MFloat f = r[0] * r[0] + r[1] * r[1] + r[2] * r[2] - F1;
3886 x[0] = esqr[0] *
y[0] / (t + esqr[0]);
3887 x[1] = esqr[1] *
y[1] / (t + esqr[1]);
3888 x[2] = esqr[2] *
y[2] / (t + esqr[2]);
3889 distance = sqrt(
POW2(x[0] -
y[0]) +
POW2(x[1] -
y[1]) +
POW2(x[2] -
y[2]));
3891 eps = eps0 +
mMin(F1,
mMax(F0, (distance - dist0) / (dist1 - dist0))) * (eps1 - eps0);
3894 if(fabs(t0 - t1) > eps) {
3895 std::cerr << std::setprecision(16) <<
"ellipsoid dist not converged! " << i <<
" " << t1 - t0 << std::endl;
3918 saveBodyRestartFile(writeBackup);
3935 const MLong noLocal = m_noLocalBodies;
3936 const MLong noGlobal = noEmbeddedBodies();
3940 std::vector<MInt> localPartitionCellOfBody(noLocal, -1);
3941 for(
MUint i = 0; i < noLocal; i++) {
3942 localPartitionCellOfBody[i] = grid().raw().findContainingPartitionCell(&a_bodyCenter(i, 0), -1,
nullptr);
3944 std::vector<int> indices(noLocal);
3946 std::iota(indices.begin(), indices.end(), 0);
3948 std::sort(indices.begin(), indices.end(),
3949 [&](
int a,
int b) ->
bool { return localPartitionCellOfBody[a] < localPartitionCellOfBody[b]; });
3951 if(domainId() == 0) {
3952 std::cerr <<
"writing body-restart-data ... (rigid bodies) ";
3955 static constexpr MLong DOF_SCALAR = 1;
3956 static constexpr MLong DOF_TRANS = nDim;
3957 static constexpr MLong DOF_ROT = nRot;
3958 static constexpr MLong DOF_QUAT = nDim + 1;
3960 const MLong offset = getDomainOffset();
3962 std::cout <<
"Domain " << domainId() <<
" has " << noLocal <<
" and offset " << offset << std::endl;
3964 std::stringstream fileNameStream;
3965 fileNameStream << outputDir() <<
"restartBodyData_" <<
globalTimeStep;
3966 fileNameStream << ParallelIo::fileExt();
3968 const MString fileName = fileNameStream.str();
3970 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
3973 parallelIo.defineScalar(PIO_INT,
"noBodies");
3976 parallelIo.defineArray(PIO_FLOAT,
"bodyTemperature", noGlobal * DOF_SCALAR);
3979 parallelIo.defineArray(PIO_FLOAT,
"bodyCenter", noGlobal * DOF_TRANS);
3980 parallelIo.defineArray(PIO_FLOAT,
"bodyVelocity", noGlobal * DOF_TRANS);
3981 parallelIo.defineArray(PIO_FLOAT,
"bodyAcceleration", noGlobal * DOF_TRANS);
3984 parallelIo.defineArray(PIO_FLOAT,
"angularVelocityBodyT1B2", noGlobal * DOF_ROT);
3985 parallelIo.defineArray(PIO_FLOAT,
"angularAccelerationBody", noGlobal * DOF_ROT);
3988 parallelIo.defineArray(PIO_FLOAT,
"bodyQuaternionT1B2", noGlobal * DOF_QUAT);
3989 parallelIo.defineArray(PIO_FLOAT,
"bodyQuaternionT1", noGlobal * DOF_QUAT);
3992 parallelIo.writeScalar(noEmbeddedBodies(),
"noBodies");
3995 parallelIo.setOffset(noLocal * DOF_SCALAR, offset * DOF_SCALAR);
3998 for(
MInt i = 0; i < noLocal; i++) {
3999 bufTemperature[i] = a_bodyTemperature(indices[i]);
4001 parallelIo.writeArray(bufTemperature.
data(),
"bodyTemperature");
4005 parallelIo.setOffset(noLocal * DOF_TRANS, offset * DOF_TRANS);
4008 for(
MInt i = 0; i < noLocal; i++) {
4009 for(
MInt n = 0; n < DOF_TRANS; n++) {
4010 writeBuffer[i * DOF_TRANS + n] = a_bodyCenter(indices[i], n);
4013 parallelIo.writeArray(writeBuffer.
data(),
"bodyCenter");
4017 for(
MInt i = 0; i < noLocal; i++) {
4018 for(
MInt n = 0; n < DOF_TRANS; n++) {
4019 writeBuffer[i * DOF_TRANS + n] = a_bodyVelocity(indices[i], n);
4022 parallelIo.writeArray(writeBuffer.
data(),
"bodyVelocity");
4026 for(
MInt i = 0; i < noLocal; i++) {
4027 for(
MInt n = 0; n < DOF_TRANS; n++) {
4028 writeBuffer[i * DOF_TRANS + n] = a_bodyAcceleration(indices[i], n);
4031 parallelIo.writeArray(writeBuffer.
data(),
"bodyAcceleration");
4035 parallelIo.setOffset(noLocal * DOF_ROT, offset * DOF_ROT);
4038 for(
MInt i = 0; i < noLocal; i++) {
4039 for(
MInt n = 0; n < DOF_ROT; n++) {
4040 writeBuffer[i * DOF_ROT + n] = a_angularVelocityBodyT1B2(indices[i], n);
4043 parallelIo.writeArray(writeBuffer.
data(),
"angularVelocityBodyT1B2");
4047 for(
MInt i = 0; i < noLocal; i++) {
4048 for(
MInt n = 0; n < DOF_ROT; n++) {
4049 writeBuffer[i * DOF_ROT + n] = a_angularAccelerationBody(indices[i], n);
4052 parallelIo.writeArray(writeBuffer.
data(),
"angularAccelerationBody");
4056 parallelIo.setOffset(noLocal * DOF_QUAT, offset * DOF_QUAT);
4059 for(
MInt i = 0; i < noLocal; i++) {
4060 for(
MInt n = 0; n < DOF_QUAT; n++) {
4061 writeBuffer[i * DOF_QUAT + n] = a_bodyQuaternionT1B2(indices[i], n);
4064 parallelIo.writeArray(writeBuffer.
data(),
"bodyQuaternionT1B2");
4068 for(
MInt i = 0; i < noLocal; i++) {
4069 for(
MInt n = 0; n < DOF_QUAT; n++) {
4070 writeBuffer[i * DOF_QUAT + n] = a_bodyQuaternionT1(indices[i], n);
4073 parallelIo.writeArray(writeBuffer.
data(),
"bodyQuaternionT1");
4076 if(domainId() == 0) {
4077 std::cerr <<
"ok" << std::endl;
4093 std::stringstream fileNameStream;
4094 fileNameStream.clear();
4096 fileNameStream << m_restartDir <<
"restartBodyData_" << m_restartTimeStep;
4097 fileNameStream << ParallelIo::fileExt();
4099 const MString fileName = fileNameStream.str();
4101 if(domainId() == 0) {
4102 std::cerr <<
"loading noBodies and positions " << fileNameStream.str() <<
" at " <<
globalTimeStep <<
"...";
4105 ParallelIo parallelIo(fileName, PIO_READ, mpiComm());
4107 parallelIo.setOffset(1, 0);
4108 parallelIo.readScalar(&m_noEmbeddedBodies,
"noBodies");
4109 m_maxNoBodies = m_noEmbeddedBodies;
4111 m_bResFile.reset(noEmbeddedBodies());
4112 m_bResFile.append(noEmbeddedBodies());
4113 parallelIo.setOffset(noEmbeddedBodies() * nDim, 0);
4114 parallelIo.readArray(&m_bResFile.bodyCenter(0, 0),
"bodyCenter");
4116 if(domainId() == 0) {
4117 std::cerr <<
"reading noBodies and initial position from restart-file done" << std::endl;
4132 std::stringstream fileNameStream;
4133 fileNameStream.clear();
4135 fileNameStream << m_restartDir <<
"restartBodyData_" << m_restartTimeStep;
4136 fileNameStream << ParallelIo::fileExt();
4138 const MString fileName = fileNameStream.str();
4140 const MLong DOF = noEmbeddedBodies();
4141 const MLong DOF_TRANS = DOF * nDim;
4142 const MLong DOF_ROT = DOF * nDim;
4143 const MLong DOF_QUAT = DOF * (nDim + 1);
4145 if(domainId() == 0) {
4146 std::cerr <<
"loading body restart file " << fileNameStream.str() <<
" at " <<
globalTimeStep <<
"...";
4149 ParallelIo parallelIo(fileName, PIO_READ, mpiComm());
4151 parallelIo.setOffset(DOF, 0);
4152 parallelIo.readArray(&m_bResFile.bodyTemperature(0),
"bodyTemperature");
4154 parallelIo.setOffset(DOF_TRANS, 0);
4155 parallelIo.readArray(&m_bResFile.bodyVelocity(0, 0),
"bodyVelocity");
4156 parallelIo.readArray(&m_bResFile.bodyAcceleration(0, 0),
"bodyAcceleration");
4158 parallelIo.setOffset(DOF_ROT, 0);
4159 parallelIo.readArray(&m_bResFile.angularVelocityBodyT1B2(0, 0),
"angularVelocityBodyT1B2");
4160 parallelIo.readArray(&m_bResFile.angularAccelerationBody(0, 0),
"angularAccelerationBody");
4162 parallelIo.setOffset(DOF_QUAT, 0);
4163 parallelIo.readArray(&m_bResFile.bodyQuaternionT1B2(0, 0),
"bodyQuaternionT1B2");
4164 parallelIo.readArray(&m_bResFile.bodyQuaternionT1(0, 0),
"bodyQuaternionT1");
4166 if(domainId() == 0) {
4167 std::cerr <<
"reading bodyRestartFile done" << std::endl;
4179 for(
MInt bodyA = 0; bodyA < noConnectingBodies(); bodyA++) {
4181 for(
MInt bodyB = 0; bodyB < noConnectingBodies(); bodyB++) {
4182 if(bodyA == bodyB) {
4185 collideSpheres(bodyA, bodyB);
4202 const MFloat S = 2.0 * c_cellLengthAtMaxLevel();
4203 const MFloat D = a_bodyRadius(bodyA) + a_bodyRadius(bodyB);
4207 for(
MInt n = 0; n < nDim; n++) {
4208 delta +=
POW2(a_bodyCenter(bodyA, n) - a_bodyCenter(bodyB, n));
4210 delta = sqrt(delta);
4219 std::cerr <<
"\033[0;31m Warning:\033[0m potential overlap for bodies" << bodyA <<
" " << bodyB << std::endl;
4222 const MFloat M = F1B2 * (a_bodyDensityRatio(bodyA) * a_volume(bodyA) + a_bodyDensityRatio(bodyB) * a_volume(bodyB));
4223 const MFloat C0 = 8.0 * M *
POW2(2.0) / c_cellLengthAtMaxLevel();
4226 std::array<MFloat, nDim> debug{};
4228 for(
MInt i = 0; i < nDim; i++) {
4229 const MFloat df = C0 *
POW2(
mMax(F0, -(
dist - S) / S)) * (a_bodyCenter(bodyA, i) - a_bodyCenter(bodyB, i)) /
dist;
4233 a_bodyForce(bodyA, i) += df;
4237 std::cerr <<
"Contact force applied " << debug[0] <<
" " << debug[1] <<
" " <<
dist <<
" " << S << std::endl;
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
static MInt propertyLength(const MString &name, MInt solverId=m_noSolvers)
Returns the number of elements of a property.
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
void open(const MString &filename, const MString &projectName, MInt fileType=0, MPI_Comm mpiComm=MPI_COMM_WORLD, MBool rootOnlyHardwired=false)
Opens a file by passing the parameters to InfoOut_<xyz>FileBuffer::open(...).
void close(MBool forceClose=false)
Pass the close call to the respective internal buffer.
void transformToBodyFrame(const MFloat *const quaternion, const MFloat *const vectorWorld, MFloat *const vectorBody)
Transform a vector form the world frame to the body frame.
MFloat getDistancePiston(const MFloat *coordinates, const MInt bodyId)
Calculates the closest distance between a given point and a piston.
std::ofstream m_debugFileStream
void initBodyLog()
Initalize log-file.
void exchangeBufferLengthsAllToAll(std::vector< MInt > &noToRecv, const MInt noToSend)
exchange of Buffer lengths all to all
void correctRotation(const MInt bodyId)
void exchangeNeighborConnectionInfo()
void preTimeStep() override
Resetting the 2-Step predictor-corrector cycle.
void correctorStep()
Correct the state of all bodies using external forces/fluxes/torques.
void checkDummyBodiesForSwap()
void loadBodyRestartFile()
Loads restart file for the RigidBodies solver.
MFloat getDistanceEllipsoid(const MFloat *coordinates, const MInt bodyId)
Calculates the closest distance between a given point and a ellipsoid.
RigidBodies(const MInt solverId, GridProxy &gridProxy, Geom &geometry, MPI_Comm comm)
C'tor for the RigidBodies solver.
MBool solutionStep() override
void collideSpheres(const MInt bodyA, const MInt bodyB)
Calculate collision force between two spheres.
MFloat findClosestPointEllipsoid(const MFloat *const relPos, const MInt bodyId)
void initGridProperties()
void exchangeNeighborNeighborRemote(std::vector< std::vector< MInt > > &bodyIdsForRemoteDomain, std::vector< std::vector< MInt > > &homeDomainIdsForRemoteDomain, std::map< MInt, std::vector< MInt > > &tmpRemoteMap)
void exchangeBufferLengthsNeighbors(std::vector< MInt > &noToRecv, const MInt noToSend)
exchange of Buffer lengths all to all in direct neighborhood
void transformToWorldFrame(const MFloat *const quaternion, const MFloat *const vectorBody, MFloat *const vectorWorld)
Transform a vector form the body frame to the world frame.
typename maia::CartesianSolver< nDim, RigidBodies > CartesianSolver
void deleteDummyBody(const MInt bodyId, const MInt collectorShift=0)
Delete dummy bodies from collector that are not relevant anymore.
void correctBodies()
Correcting the state of all bodies using all available external forces/fluxes.
void predictorStep()
Peform a prediction for all bodies.
void createDummyBody(MInt bodyId)
appends new DummyBody to collector
void loadBodiesSizeAndPosition()
loadind no of embedded bodies and it's position from restart file
MFloat calculatePeriodicShift(MInt intersectingCellId, MInt direction)
periodic shift for position for further data exchange
void printBodyDomainConnections()
debugging: print all necessary mappings for each partition in specific file
void readProperties()
Reading all necessary properties for the RigidBodies solver.
void deleteIrrelevantBodies(std::list< std::pair< MInt, MInt > > &removeList)
Delete remote bodies from collector that are not relevant anymore.
void collideBodies()
Calculate collisions forces for all bodies.
void saveBodyRestartFile(const MBool backup)
Write restart file for the RigidBody solver.
MFloat getDistanceCube(const MFloat *coordinates, const MInt bodyId)
Calculates the closest distance between a given point and a cube.
void exchangeBufferLengthsRemoteToHome(std::vector< MInt > &noToRecv, std::vector< MInt > &noToSend)
void exchangeFsiData()
exchange of summed forces and torques
void exchangeBufferLengthsNeighbor(std::vector< MInt > &noToRecv, std::vector< std::vector< MInt > > &bodyList)
exchange of Buffer legnths for further exchanges
void findLocalBodies()
searches in all initial Bodies for local bodies
void logBodyData()
Writing a simple log file containing the current state for all bodies.
void advanceBodies()
Copy the body data for time t to t-1 to prepare the next timestep.
void writeRestartFile(const MBool writeRestart, const MBool writeBackup, const MString, MInt *) override
Write restart file for the RigidBody solver.
~RigidBodies()
D'tor for the RigidBodies solver.
MFloat getDistanceSphere(const MFloat *coordinates, const MInt bodyId)
Calculates the closest distance between a given point and a sphere.
void findTransferBodies()
creates list with all edge bodies that are no longer contained within local domain
void initRemoteDummyBodyData(const MInt bodyId)
initalize kinematic data of dummyBody that is associated with a remoteBody
void exchangeNeighborNeighborHome(std::vector< std::vector< MInt > > &bodyIdsForHomeDomain, std::vector< std::vector< MInt > > &remoteDomainIdsForHomeDomain, std::vector< std::vector< std::array< MFloat, nDim > > > &shiftForHomeDomain)
void exchangeBodyVariablesAllToAll()
exchange of Body Variables all to all
void computeBodies()
Calculates the new state for all bodies.
void updateInfoDiameter(const MBool initCall=false)
MInt localToRemoteBody(const MInt collectorId, const MInt oldBodyId, const MInt domain)
this function transforms a localBody to a remoteBody on the current domain, necessary if a body cross...
void exchangeTransferBodies()
exchanges transfer bodies
void updateBodyDomainConnections(MBool initCall)
updates local/ edge body domain connections
MFloat distancePointEllipsoid(const std::array< MFloat, 3 > e, const std::array< MFloat, 3 > y, std::array< MFloat, 3 > x)
Calculates the closest distance between a given point and a ellipsoid in 3D.
MLong getDomainOffset()
for new restartFile format
void quaternionToEuler(const MFloat *const quaternion, MFloat *const angles)
Transform the quaternion to Euler angles.
void computeBodyPropertiesForced(MInt returnMode, MFloat *bodyData, MInt bodyId, MFloat time)
typename CartesianSolver::GridProxy GridProxy
void advanceQuaternion(const MFloat *const angularVelocity, const MFloat dt, const MFloat *const qIn, MFloat *const qOut)
Advance the rotational state by one timestep for a given angular velocity.
void initBodyData()
Allocating and initializing body data necessary for the solver run.
void exchangeKinematicData()
exchange of predictor & corrector step output
void exchangeBufferLengthsAllToRoot(std::vector< MInt > &noToRecv, const MInt noToSend)
exchange of Buffer lengths all to root
void exchangeEdgeBodyData()
exchanges relevant body connections with new neighbor domains
void totalKineticEnergy()
std::array< MInt, Timers::_count > m_timers
void predictRotation(const MInt bodyId)
void printScalingVariables()
This class is a ScratchSpace.
virtual MInt domainId() const
Return the domainId (rank)
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool fileExists(const MString &fileName)
Returns true if the file fileName exists, false otherwise.
constexpr Real POW2(const Real x)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
std::basic_string< char > MString
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_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgatherv
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_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Gatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gatherv
int MPI_Waitall(int count, MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Waitall
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_Gather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Gather
T cos(const T a, const T b, const T x)
Cosine slope filter.
void cross(const T *const u, const T *const v, T *const c)
std::vector< MFloat > linSpace(const MFloat start, const MFloat end, const MInt num)
void quatMult(const MFloat *const qA, const MFloat *const qB, MFloat *const qC)
Namespace for auxiliary functions/classes.
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)