24#ifndef PARTICLESYSTEM_3D_HH
25#define PARTICLESYSTEM_3D_HH
32#include <unordered_map>
43#define M_PI 3.14159265358979323846
50 template<
typename T,
template<
typename U>
class PARTICLETYPE>
53 : clout(std::cout,
"ParticleSystem3D"),
54 _iGeometry(iGeometry),
55 _superGeometry(superGeometry),
61 template<
typename T,
template<
typename U>
class PARTICLETYPE>
64 : clout(std::cout,
"ParticleSystem3D"),
65 _iGeometry(pS._iGeometry),
66 _superGeometry(pS._superGeometry),
69 _physPos(pS._physPos),
70 _physExtend(pS._physExtend)
76 template<
typename T,
template<
typename U>
class PARTICLETYPE>
79 : clout(std::cout,
"ParticleSystem3D"),
80 _iGeometry(pS._iGeometry),
81 _superGeometry(pS._superGeometry),
84 _physPos(pS._physPos),
85 _physExtend(pS._physExtend)
87 _particles = std::move(pS._particles);
88 _forces = std::move(pS._forces);
91 template<
typename T,
template<
typename U>
class PARTICLETYPE>
94 return _contactDetection;
97 template<
typename T,
template<
typename U>
class PARTICLETYPE>
100 std::deque<PARTICLETYPE<T>*> allParticles = this->getAllParticlesPointer();
101 for (
auto p : allParticles) {
106 template<
typename T,
template<
typename U>
class PARTICLETYPE>
109 delete _contactDetection;
110 _contactDetection = contactDetection.
generate(*
this);
113 template<
typename T,
template<
typename U>
class PARTICLETYPE>
115 std::vector<T> physExtend)
118 _physExtend = physExtend;
121 template<
typename T,
template<
typename U>
class PARTICLETYPE>
127 template<
typename T,
template<
typename U>
class PARTICLETYPE>
133 template<
typename T,
template<
typename U>
class PARTICLETYPE>
136 if (i < (
int) _particles.size()) {
137 return _particles[i];
139 else if (i < (
int) (_particles.size() + _shadowParticles.size())) {
140 return _shadowParticles[i - _particles.size()];
143 std::ostringstream os;
145 std::string err =
"Cannot access element: " + os.str()
147 throw std::runtime_error(err);
151 template<
typename T,
template<
typename U>
class PARTICLETYPE>
155 if ((
unsigned)i < _particles.size()) {
156 return _particles[i];
158 else if (i - _particles.size() < _shadowParticles.size()) {
159 return _shadowParticles[i - _particles.size()];
162 std::ostringstream os;
164 std::string err =
"Cannot access element: " + os.str()
166 throw std::runtime_error(err);
170 template<
typename T,
template<
typename U>
class PARTICLETYPE>
173 return _particles.size();
176 template<
typename T,
template<
typename U>
class PARTICLETYPE>
179 return _particles.size() + _shadowParticles.size();
182 template<
typename T,
template<
typename U>
class PARTICLETYPE>
185 int activeParticles = 0;
186 for (
auto p : _particles) {
191 return activeParticles;
214 template<
typename T,
template<
typename U>
class PARTICLETYPE>
217 return _forces.size();
220 template<
typename T,
template<
typename U>
class PARTICLETYPE>
223 _particles.push_back(p);
226 template<
typename T,
template<
typename U>
class PARTICLETYPE>
232 template<
typename T,
template<
typename U>
class PARTICLETYPE>
235 _shadowParticles.push_back(p);
238 template<
typename T,
template<
typename U>
class PARTICLETYPE>
242 _forces.push_back(pF);
245 template<
typename T,
template<
typename U>
class PARTICLETYPE>
249 _boundaries.push_back(pB);
252 template<
typename T,
template<
typename U>
class PARTICLETYPE>
256 _particleOperations.push_back(pO);
259 template<
typename T,
template<
typename U>
class PARTICLETYPE>
260 template<
typename DESCRIPTOR>
264 for (
auto& p : _particles) {
266 fVel(&p.getVel()[0], &p.getPos()[0], p.getCuboid());
271 template<
typename T,
template<
typename U>
class PARTICLETYPE>
275 for (
auto& p : _particles) {
277 std::vector<T> vel(3, T());
278 aVel(&p.getVel()[0], &p.getPos()[0]);
283 template<
typename T,
template<
typename U>
class PARTICLETYPE>
286 typename std::deque<PARTICLETYPE<T> >::iterator p;
288 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
289 if (p->getActive()) {
291 for (
auto f : _forces) {
292 f->applyForce(p, pInt, *
this);
298 template<
typename T,
template<
typename U>
class PARTICLETYPE>
299 void ParticleSystem3D<T, PARTICLETYPE>::eraseInactiveParticles()
301 std::deque<PARTICLETYPE<T> > activeParticles;
302 for (
auto p = _particles.begin(); p != _particles.end(); ++p) {
303 if (p-> getActive()) {
304 PARTICLETYPE<T> particle = *p;
305 activeParticles.push_back(particle);
308 _particles = std::move(activeParticles);
311 template<
typename T,
template<
typename U>
class PARTICLETYPE>
314 typename std::deque<PARTICLETYPE<T> >::iterator p;
315 for (
auto f : _boundaries) {
316 for (p = _particles.begin(); p != _particles.end(); ++p) {
317 if (p->getActive()) {
318 f->applyBoundary(p, *
this);
324 template<
typename T,
template<
typename U>
class PARTICLETYPE>
327 typename std::deque<PARTICLETYPE<T> >::iterator p;
328 for (
auto o : _particleOperations) {
329 for (p = _particles.begin(); p != _particles.end(); ++p) {
330 if (p->getActive()) {
331 o->applyParticleOperation(p, *
this);
337 template<
typename T,
template<
typename U>
class PARTICLETYPE>
340 _sim.simulate(dT, scale);
343 template<
typename T,
template<
typename U>
class PARTICLETYPE>
347 int material,
int subSteps,
bool scale )
349 _sim.simulateWithTwoWayCoupling_Mathias(dT, forwardCoupling, backCoupling, material, subSteps, scale);
352 template<
typename T,
template<
typename U>
class PARTICLETYPE>
356 int material,
int subSteps,
bool scale )
358 _sim.simulateWithTwoWayCoupling_Davide(dT, forwardCoupling, backCoupling, material, subSteps, scale);
365 _sim.simulate(dT, sActivity, scale);
368 template<
typename T,
template<
typename U>
class PARTICLETYPE>
372 int locLatCoords[3] = {0};
373 for (
auto& p : _particles) {
374 _superGeometry.getCuboidGeometry().get(p.getCuboid()).getFloorLatticeR(
375 locLatCoords, &p.getPos()[0]);
376 const BlockGeometry<T,3>& bg = _superGeometry.getBlockGeometry(_superGeometry.getLoadBalancer().loc(p.getCuboid()));
377 int iX = locLatCoords[0];
378 int iY = locLatCoords[1];
379 int iZ = locLatCoords[2];
380 if (bg.
get(iX, iY, iZ) == mat
381 || bg.
get(iX, iY + 1, iZ) == mat
382 || bg.
get(iX, iY, iZ + 1) == mat
383 || bg.
get(iX, iY + 1, iZ + 1) == mat
384 || bg.
get(iX + 1, iY, iZ) == mat
385 || bg.
get(iX + 1, iY + 1, iZ) == mat
386 || bg.
get(iX + 1, iY, iZ + 1) == mat
387 || bg.
get(iX + 1, iY + 1, iZ + 1) == mat) {
394 template<
typename T,
template<
typename U>
class PARTICLETYPE>
397 for (
auto& p : _particles) {
399 if (! forwardCoupling(&p, _iGeometry) ) {
400 std::cout <<
"ERROR: ForwardCoupling functional failed on particle " << p.getID();
408 template<
typename T,
template<
typename U>
class PARTICLETYPE>
411 for (
auto& p : _particles) {
413 if (! backCoupling(&p, _iGeometry, material, subSteps) ) {
414 std::cout <<
"ERROR: BackwardCoupling functional failed on particle " << p.getID();
422 template<
typename T,
template<
typename U>
class PARTICLETYPE>
427 T maxDeltaR = _superGeometry.getCuboidGeometry().getMaxDeltaR();
430 for (
auto& p : _particles) {
434 for (
int i = 0; i < 3; i++) {
436 p.getVel()[i] += p.getForce()[i] * p.getInvEffectiveMass() * dT;
438 p.getPos()[i] += p.getVel()[i] * dT;
450 std::cout <<
"particle velocity is scaled because of reached limit"
452 for (
int i = 0; i < 3; i++) {
453 p.getPos()[i] -= p.getVel()[i] * dT;
454 p.getVel()[i] /= maxFactor;
455 p.getPos()[i] += p.getVel()[i] * dT;
479 double maxDeltaR = _superGeometry.getCuboidGeometry().getMaxDeltaR();
480 double maxFactor = double();
482 for (
auto& p : _particles) {
486 if (p.getSActivity() == 3) {
490 for (
int i = 0; i < 3; i++) {
491 p.getVel()[i] += p.getForce()[i] * p.getInvEffectiveMass() * dT;
492 p.getPos()[i] += p.getVel()[i] * dT;
503 std::cout <<
"particle velocity is scaled because of reached limit"
505 for (
int i = 0; i < 3; i++) {
506 p.getPos()[i] -= p.getVel()[i] * dT;
507 p.getVel()[i] /= maxFactor;
508 p.getPos()[i] += p.getVel()[i] * dT;
539 double maxDeltaR = _superGeometry.getCuboidGeometry().getMaxDeltaR();
540 double maxFactor = double();
542 for (
auto& p : _particles) {
546 if (p.getSActivity() == 3) {
551 for (
auto sA : sActivityOfParticle) {
552 if (p.getSActivity() == sA) {
561 for (
int i = 0; i < 3; i++) {
562 p.getVel()[i] += p.getForce()[i] * p.getInvEffectiveMass() * dT;
563 p.getPos()[i] += p.getVel()[i] * dT;
574 std::cout <<
"particle velocity is scaled because of reached limit"
576 for (
int i = 0; i < 3; i++) {
577 p.getPos()[i] -= p.getVel()[i] * dT;
578 p.getVel()[i] /= maxFactor;
579 p.getPos()[i] += p.getVel()[i] * dT;
758 template<
typename T,
template<
typename U>
class PARTICLETYPE>
761 for (
auto& p : _particles) {
763 std::vector<T> pos = p.getPos();
764 for (
int i = 0; i < 3; i++) {
765 pos[i] += p.getVel()[i] * dT
766 + .5 * p.getForce()[i] / p.getMass() *
util::pow(dT, 2);
773 template<
typename T,
template<
typename U>
class PARTICLETYPE>
778 typename std::deque<PARTICLETYPE<T> >::iterator p;
780 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
782 if (p->getActive()) {
786 for (
auto f : _forces) {
787 f->applyForce(p, pInt, *
this);
789 for (
int i = 0; i < 3; i++) {
790 vel[i] += .5 * (p->getForce()[i] + frc[i]) / p->getMass() * dT;
916 template<
typename T,
template<
typename U>
class PARTICLETYPE>
920 std::deque<PARTICLETYPE<T>*> pointerParticles;
921 for (
int i = 0; i < (int) _particles.size(); i++) {
922 pointerParticles.push_back(&_particles[i]);
924 return pointerParticles;
927 template<
typename T,
template<
typename U>
class PARTICLETYPE>
928 std::list<std::shared_ptr<Force3D<T, PARTICLETYPE> > >
934 template<
typename T,
template<
typename U>
class PARTICLETYPE>
938 std::deque<PARTICLETYPE<T>*> pointerParticles;
940 for (; i < (int) _particles.size(); i++) {
941 pointerParticles.push_back(&_particles[i]);
943 for (; i < (int) (_particles.size() + _shadowParticles.size()); i++) {
944 pointerParticles.push_back(&_shadowParticles[i - _particles.size()]);
946 return pointerParticles;
949 template<
typename T,
template<
typename U>
class PARTICLETYPE>
953 std::deque<PARTICLETYPE<T>*> pointerParticles;
954 for (
int i = 0; i < (int) (_shadowParticles.size()); i++) {
955 pointerParticles.push_back(&_shadowParticles[i]);
957 return pointerParticles;
960 template<
typename T,
template<
typename U>
class PARTICLETYPE>
963 std::ofstream fout(fullName.c_str(), std::ios::app);
965 clout <<
"Error: could not open " << fullName << std::endl;
967 std::vector<T> serPar(PARTICLETYPE<T>::serialPartSize, 0);
968 for (
auto& p : _particles) {
969 p.serialize(&serPar[0]);
970 typename std::vector<T>::iterator it = serPar.begin();
971 for (; it != serPar.end(); ++it) {
1082 typename std::deque<MagneticParticle3D<double> >::iterator p;
1084 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1086 if (p->getActive()) {
1098 typename std::deque<MagneticParticle3D<double> >::iterator p;
1100 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1102 if (p->getSActivity() == 3) {
1106 if (p->getActive()) {
1108 for (
auto sA : sActivityOfParticle) {
1109 if (p->getSActivity() == sA) {
1127 typename std::deque<MagneticParticle3D<double> >::iterator p;
1129 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1130 if (p->getActive()) {
1132 for (
auto f : _forces) {
1133 f->applyForce(p, pInt, *
this);
1143 typename std::deque<MagneticParticle3D<double> >::iterator p;
1145 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1147 if (p->getActive()) {
1149 if (p->getSActivity() == 3) {
1154 for (
auto sA : sActivityOfParticle) {
1155 if (p->getSActivity() == sA) {
1164 for (
auto f : _forces) {
1166 f->applyForce(p, pInt, *
this);
1213 for (
auto& p : _particles) {
1217 double epsilon = std::numeric_limits<double>::epsilon();
1218 for (
int i = 0; i < 3; i++) {
1219 p.getAVel()[i] += (5. * (p.getTorque()[i]) * dT) / (2. * p.getMass() *
util::pow(p.getRad(), 2));
1220 deltaAngle[i] = p.getAVel()[i] * dT;
1221 angle =
norm(deltaAngle);
1223 if (angle > epsilon) {
1224 std::vector<double> null(3,
double());
1226 double input[3] = {p.getMoment()[0], p.getMoment()[1], p.getMoment()[2]};
1228 double output[3] = {double(), double(), double()};
1229 rotRAxis(output, input);
1232 if (
norm(out) > epsilon) {
1236 p.getMoment()[0] = out[0];
1237 p.getMoment()[1] = out[1];
1238 p.getMoment()[2] = out[2];
1249 for (
auto& p : _particles) {
1251 if (p.getSActivity() == 3) {
1256 for (
auto sA : sActivityOfParticle) {
1257 if (p.getSActivity() == sA) {
1268 double epsilon = std::numeric_limits<double>::epsilon();
1269 for (
int i = 0; i < 3; i++) {
1270 p.getAVel()[i] += (5. * (p.getTorque()[i]) * dT) / (2. * p.getMass() *
util::pow(p.getRad(), 2));
1271 deltaAngle[i] = p.getAVel()[i] * dT;
1272 angle =
norm(deltaAngle);
1274 if (angle > epsilon) {
1275 std::vector<double> null(3,
double());
1277 double input[3] = {p.getMoment()[0], p.getMoment()[1], p.getMoment()[2]};
1279 double output[3] = {double(), double(), double()};
1280 rotRAxis(output, input);
1283 if (
norm(out) > epsilon) {
1287 p.getMoment()[0] = out[0];
1288 p.getMoment()[1] = out[1];
1289 p.getMoment()[2] = out[2];
1295 template<
typename T,
template<
typename U>
class PARTICLETYPE>
1299 typename std::deque<PARTICLETYPE<T> >::iterator p;
1301 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1303 p->setStoredPos(p->getPos());
1313 typename std::deque<MagneticParticle3D<double> >::iterator p;
1315 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1317 std::vector<std::pair<size_t, double>> ret_matches;
1319 getContactDetection()->getMatches(pInt, ret_matches);
1324 for (
const auto& it : ret_matches) {
1327 p2 = &(_particles.at(it.first));
1336 for (
int i = 0; i <= 2; i++) {
1338 conVec[i] = p2->
getPos()[i] - p->getPos()[i];
1343 double dpos[3] = {double(0), double(0), double(0) } ;
1346 if ((p->getSActivity() != 3) && (p2->
getSActivity() != 3)) {
1348 for (
int i = 0; i <= 2; i++) {
1350 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1351 p->getPos()[i] -= 1.* dpos[i];
1352 p2->
getPos()[i] += 1.* dpos[i];
1354 if ((p->getSActivity() == 2) || (p->getSActivity() == 2)) {
1362 if ((p->getSActivity() != 3) && (p2->
getSActivity() == 3)) {
1364 for (
int i = 0; i <= 2; i++) {
1366 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1367 p->getPos()[i] -= 2. * dpos[i];
1369 p->setSActivity(2) ;
1373 if ((p->getSActivity() == 3) && (p2->
getSActivity() != 3)) {
1375 for (
int i = 0; i <= 2; i++) {
1377 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1378 p2->
getPos()[i] += 2. * dpos[i];
1384 if ((p->getSActivity() == 3) && (p2->
getSActivity() == 3)) {
1386 for (
int i = 0; i <= 2; i++) {
1388 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1389 p->getPos()[i] -= dpos[i];
1390 p2->
getPos()[i] += dpos[i];
1403 typename std::deque<MagneticParticle3D<double> >::iterator p;
1406 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1408 if (p->getSActivity() > 1) {
1412 std::vector<std::pair<size_t, double>> ret_matches;
1414 getContactDetection()->getMatches(pInt, ret_matches);
1418 for (
const auto& it : ret_matches) {
1420 p2 = &(_particles.at(it.first));
1428 for (
int i = 0; i <= 2; i++) {
1430 conVec[i] = p2->
getPos()[i] - p->getPos()[i];
1435 double dpos[3] = {double(0), double(0), double(0) } ;
1438 if (overlap > p2->
getRad() + p->getRad()) {
1442 for (
int i = 0; i <= 2; i++) {
1444 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1445 p->getPos()[i] -= dpos[i] * 1. ;
1446 p2->
getPos()[i] += dpos[i] * 1. ;
1455 for (
int i = 0; i <= 2; i++) {
1457 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1458 p->getPos()[i] -= 2 * dpos[i];
1469 template<
typename T,
template<
typename U>
class PARTICLETYPE>
1472 std::sort(ret_matches.begin(), ret_matches.end(), getMinDistPartObj);
1478 typename std::deque<MagneticParticle3D<double> >::iterator p;
1481 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1483 std::vector<std::pair<size_t, double>> ret_matches;
1485 getContactDetection()->getMatches(pInt, ret_matches);
1490 for (
const auto& it : ret_matches) {
1493 p2 = &(_particles.at(it.first));
1502 for (
int i = 0; i <= 2; i++) {
1504 conVec[i] = p2->
getPos()[i] - p->getPos()[i];
1524 double Cr = restitutionCoeff;
1526 velN1 = (conVecNormalized * vel1bc) * conVecNormalized;
1527 velN2 = (conVecNormalized * vel2bc) * conVecNormalized;
1528 velT1 = vel1bc - velN1;
1529 velT2 = vel2bc - velN2;
1530 vel1ac = (Cr * p2->
getMass() * ( velN2 - velN1) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1531 vel2ac = (Cr * p->getMass() * ( velN1 - velN2) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1533 double dpos[3] = {double(0), double(0), double(0) } ;
1536 if ((p->getSActivity() != 3) && (p2->
getSActivity() != 3)) {
1538 for (
int i = 0; i <= 2; i++) {
1540 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1541 p->getPos()[i] -= dpos[i] * 1. ;
1542 p->getVel()[i] = vel1ac[i] + velT1[i] ;
1543 p2->
getPos()[i] += dpos[i] * 1. ;
1544 p2->
getVel()[i] = vel2ac[i] + velT2[i] ;
1546 if ((p->getSActivity() == 2) || (p->getSActivity() == 2)) {
1554 if ((p->getSActivity() != 3) && (p2->
getSActivity() == 3)) {
1556 for (
int i = 0; i <= 2; i++) {
1558 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1559 p->getPos()[i] -= 2. * dpos[i];
1560 p->getVel()[i] = -1. * p->getVel()[i];
1562 p->setSActivity(2) ;
1567 if ((p->getSActivity() == 3) && (p2->
getSActivity() != 3)) {
1569 for (
int i = 0; i <= 2; i++) {
1571 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1572 p2->
getPos()[i] += 2. * dpos[i];
1580 if ((p->getSActivity() == 3) && (p2->
getSActivity() == 3)) {
1582 for (
int i = 0; i <= 2; i++) {
1584 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1585 p->getPos()[i] -= dpos[i];
1586 p2->
getPos()[i] += dpos[i];
1599 typename std::deque<MagneticParticle3D<double> >::iterator p;
1602 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1604 std::vector<std::pair<size_t, double>> ret_matches;
1606 getContactDetection()->getMatches(pInt, ret_matches);
1611 if (ret_matches.size() == 1) {
1614 double minDist = 0. ;
1617 for (
auto a : ret_matches) {
1626 if (a.second < minDist) {
1634 p2 = &(_particles.at(xPInt));
1643 for (
int i = 0; i <= 2; i++) {
1645 conVec[i] = p2->
getPos()[i] - p->getPos()[i];
1665 double Cr = restitutionCoeff;
1667 velN1 = (conVecNormalized * vel1bc) * conVecNormalized;
1668 velN2 = (conVecNormalized * vel2bc) * conVecNormalized;
1669 velT1 = vel1bc - velN1;
1670 velT2 = vel2bc - velN2;
1671 vel1ac = (Cr * p2->
getMass() * ( velN2 - velN1) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1672 vel2ac = (Cr * p->getMass() * ( velN1 - velN2) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1674 double dpos[3] = {double(0), double(0), double(0) } ;
1677 if ((p->getSActivity() != 3) && (p2->
getSActivity() != 3)) {
1679 for (
int i = 0; i <= 2; i++) {
1681 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1682 p->getPos()[i] -= dpos[i] * 1. ;
1683 p->getVel()[i] = vel1ac[i] + velT1[i] ;
1684 p2->
getPos()[i] += dpos[i] * 1. ;
1685 p2->
getVel()[i] = vel2ac[i] + velT2[i] ;
1687 if ((p->getSActivity() == 2) || (p->getSActivity() == 2)) {
1695 if ((p->getSActivity() != 3) && (p2->
getSActivity() == 3)) {
1697 for (
int i = 0; i <= 2; i++) {
1699 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1700 p->getPos()[i] -= 2. * dpos[i];
1701 p->getVel()[i] = -1. * p->getVel()[i];
1703 p->setSActivity(2) ;
1708 if ((p->getSActivity() == 3) && (p2->
getSActivity() != 3)) {
1710 for (
int i = 0; i <= 2; i++) {
1712 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1713 p2->
getPos()[i] += 2. * dpos[i];
1721 if ((p->getSActivity() == 3) && (p2->
getSActivity() == 3)) {
1723 for (
int i = 0; i <= 2; i++) {
1725 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1726 p->getPos()[i] -= dpos[i];
1727 p2->
getPos()[i] += dpos[i];
1738 typename std::deque<MagneticParticle3D<double> >::iterator p;
1741 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1743 if (p->getSActivity() > 1) {
1747 std::vector<std::pair<size_t, double>> ret_matches;
1749 getContactDetection()->getMatches(pInt, ret_matches);
1754 for (
const auto& it : ret_matches) {
1757 p2 = &(_particles.at(it.first));
1766 for (
int i = 0; i <= 2; i++) {
1768 conVec[i] = p2->
getPos()[i] - p->getPos()[i];
1789 double Cr = restitutionCoeff;
1791 velN1 = (conVecNormalized * vel1bc) * conVecNormalized;
1792 velN2 = (conVecNormalized * vel2bc) * conVecNormalized;
1793 velT1 = vel1bc - velN1;
1794 velT2 = vel2bc - velN2;
1795 vel1ac = (Cr * p2->
getMass() * ( velN2 - velN1) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1796 vel2ac = (Cr * p->getMass() * ( velN1 - velN2) + (p2->
getMass() * velN2) + (p->getMass() * velN1)) * (1. / (p->getMass() + p2->
getMass())) ;
1798 double dpos[3] = {double(0), double(0), double(0) } ;
1801 if ((p->getSActivity() != 3) && (p2->
getSActivity() != 3)) {
1803 for (
int i = 0; i <= 2; i++) {
1805 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1806 p->getPos()[i] -= dpos[i] * 1. ;
1807 p->getVel()[i] = vel1ac[i] + velT1[i] ;
1808 p2->
getPos()[i] += dpos[i] * 1. ;
1809 p2->
getVel()[i] = vel2ac[i] + velT2[i] ;
1811 if ((p->getSActivity() == 2) || (p->getSActivity() == 2)) {
1819 if ((p->getSActivity() != 3) && (p2->
getSActivity() == 3)) {
1821 for (
int i = 0; i <= 2; i++) {
1823 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1824 p->getPos()[i] -= 2. * dpos[i];
1825 p->getVel()[i] = -1. * p->getVel()[i];
1827 p->setSActivity(2) ;
1832 if ((p->getSActivity() == 3) && (p2->
getSActivity() != 3)) {
1834 for (
int i = 0; i <= 2; i++) {
1836 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1837 p2->
getPos()[i] += 2. * dpos[i];
1845 if ((p->getSActivity() == 3) && (p2->
getSActivity() == 3)) {
1847 for (
int i = 0; i <= 2; i++) {
1849 dpos[i] = conVecNormalized[i] * 0.5 * overlap ;
1850 p->getPos()[i] -= dpos[i];
1851 p2->
getPos()[i] += dpos[i];
1864 typename std::deque<MagneticParticle3D<double> >::iterator p;
1867 for (p = _particles.begin(); p != _particles.end(); ++p, ++pInt) {
1870 std::vector<std::pair<size_t, double>> ret_matches;
1872 getContactDetection()->getMatches(pInt, ret_matches);
1876 for (
const auto& it : ret_matches) {
1880 p2 = &(_particles.at(it.first));
1886 if ((p1->getAggloItr() == _Agglomerates.begin()) && (p2->
getAggloItr() == _Agglomerates.begin())) {
1888 std::list<MagneticParticle3D<double>*> aggloList{p1, p2} ;
1890 typename std::list<MagneticParticle3D<double>*>::iterator x1;
1891 typename std::list<MagneticParticle3D<double>*>::iterator x2;
1893 _Agglomerates.push_back(aggloList);
1897 for (
auto x = _Agglomerates[0].begin(); x != _Agglomerates[0].end(); ++x) {
1907 _Agglomerates[0].erase(x1);
1908 _Agglomerates[0].erase(x2);
1915 if ((p1->getAggloItr() == _Agglomerates.begin()) && (p2->
getAggloItr() != _Agglomerates.begin())) {
1919 typename std::list<MagneticParticle3D<double>*>::iterator x1;
1921 for (
auto x = _Agglomerates[0].begin(); x != _Agglomerates[0].end(); ++x) {
1926 _Agglomerates[0].erase(x1);
1933 if ((p1->getAggloItr() != _Agglomerates.begin()) && (p2->
getAggloItr() == _Agglomerates.begin())) {
1935 (p1->getAggloItr())->push_back(p2) ;
1937 typename std::list<MagneticParticle3D<double>*>::iterator x2;
1939 for (
auto x = _Agglomerates[0].begin(); x != _Agglomerates[0].end(); ++x) {
1945 _Agglomerates[0].erase(x2);
1952 if (((p1->getAggloItr() != _Agglomerates.begin()) && (p2->
getAggloItr() != _Agglomerates.begin())) && ( p1->getAggloItr() != p2->
getAggloItr())) {
1954 typename std::deque<std::list<MagneticParticle3D<double>*>>::iterator x1;
1955 typename std::deque<std::list<MagneticParticle3D<double>*>>::iterator x2;
1959 x1 = p1->getAggloItr() ;
1963 x2 = p1->getAggloItr() ;
1967 x1->splice(x1->end(), *x2) ;
1969 _Agglomerates.erase(x2) ;
1971 for (
auto anew = _Agglomerates.begin(); anew != _Agglomerates.end(); ++anew) {
1973 for (
auto pnew = anew->begin(); pnew != anew->end(); ++pnew) {
1975 (*pnew)->setAggloItr(anew);
1991 typename std::deque<MagneticParticle3D<double> >::iterator p;
1992 static int pInt = 0;
1994 for (p = _particles.begin() + pInt; p != _particles.end(); ++p, ++pInt) {
1995 p->setAggloItr(_Agglomerates.begin());
1997 _Agglomerates.begin()->push_back(pPointer);
AnalyticalConst: DD -> XD, where XD is defined by value.size()
Abstact base class for BaseBackCouplingModel.
Representation of a block geometry.
std::enable_if_t< sizeof...(L)==D, int > get(L... latticeR) const
Read-only access to a material number.
Prototype for all particle boundaries.
Prototype for all particle forces.
Abstact base class for all the forward-coupling models Its raison d'etre consists of not being temple...
void setSActivity(int sActivity)
std::deque< std::list< MagneticParticle3D< T > * > >::iterator & getAggloItr()
void setAggloItr(typename std::deque< std::list< MagneticParticle3D< T > * > >::iterator aggloItr)
std::vector< T > & getVel()
std::vector< T > & getPos()
bool executeBackwardCoupling(BackCouplingModel< T, PARTICLETYPE > &backwardCoupling, int material, int subSteps=1)
void partialElasticImpact(T restitutionCoeff)
Resets existing particle overlaps in the event of a collision and applies the physics of an partial e...
void clearParticles()
Removes all particles from system.
void setPosExt(std::vector< T > physPos, std::vector< T > physExtend)
Set global coordinates and extends of Particlesystem (SI units)
void setVelToFluidVel(SuperLatticeInterpPhysVelocity3D< T, DESCRIPTOR > &)
Set velocity of all particles to fluid velocity.
void computeForce()
Compute all forces on particles.
bool executeForwardCoupling(ForwardCouplingModel< T, PARTICLETYPE > &forwardCoupling)
std::list< std::shared_ptr< Force3D< T, PARTICLETYPE > > > getForcesPointer()
returns shared pointer of forces
int sizeInclShadow() const
Get number of particles including shadow particles in ParticleSystem.
std::deque< PARTICLETYPE< T > * > getShadowParticlesPointer()
returns deque of pointer to all shadow particles contained in a particleSystem3D
void addParticle(PARTICLETYPE< T > &p)
Add a particle to ParticleSystem.
std::deque< PARTICLETYPE< T > * > getParticlesPointer()
returns deque of pointer to particles (not shadow particles) contained in a particleSystem3D
void setVelToAnalyticalVel(AnalyticalConst3D< T, T > &)
Set particle velocity to analytical velocity (e.g. as initial condition.
void explicitEuler(T dT, bool scale=false)
Integration method: explicit Euler if scale = true, velocity is scaled to maximal velocity maximal ve...
virtual void simulate(T deltatime, bool scale=false)
void setOverlapZero()
Collision models: Todo: enable for parallel mode Resets existing particle overlaps in the event of a ...
void addShadowParticle(PARTICLETYPE< T > &p)
std::deque< PARTICLETYPE< T > * > getAllParticlesPointer()
returns deque of pointer to all particles (incl.
int numOfForces()
Get number of linked forces in ParticleSystem.
void printDeep(std::string message="")
virtual void simulateWithTwoWayCoupling_Davide(T dT, ForwardCouplingModel< T, PARTICLETYPE > &forwardCoupling, BackCouplingModel< T, PARTICLETYPE > &backCoupling, int material, int subSteps, bool scale)
void velocityVerlet2(T dT)
int size()
Get number of particles in ParticleSystem.
void saveToFile(std::string name)
Save particle positions to file.
void partialElasticImpactV2(T restitutionCoeff)
Applies the physics of an partial elastic impact while multiple particle overlapping only to the part...
void velocityVerlet1(T dT)
Integration methods, each need a special template particle.
std::deque< PARTICLETYPE< T > > _particles
void computeBoundary()
Compute boundary contact.
std::list< std::shared_ptr< Force3D< T, PARTICLETYPE > > > _forces
virtual void simulateWithTwoWayCoupling_Mathias(T dT, ForwardCouplingModel< T, PARTICLETYPE > &forwardCoupling, BackCouplingModel< T, PARTICLETYPE > &backCoupling, int material, int subSteps, bool scale)
void integrateTorqueMag(T dT)
void addBoundary(std::shared_ptr< Boundary3D< T, PARTICLETYPE > > pB)
Add a boundary to ParticleSystem.
ParticleSystem3D()=default
Default constructor for ParticleSystem.
int numOfActiveParticles()
Get number of active particles in ParticleSystem.
void setOverlapZeroForCombinationWithMechContactForce()
For the combined use of setOverlapZero() and a mechanic contact force.
void computeParticleOperation()
Compute operations on particles.
const std::vector< T > & getPhysPos()
Get global coordinates and extends of Particlesystem (SI units)
void addForce(std::shared_ptr< Force3D< T, PARTICLETYPE > > pF)
Add a force to ParticleSystem.
void getMinDistParticle(std::vector< std::pair< size_t, T > > ret_matches)
int countMaterial(int mat=1)
Get number of particles in vicinity of material number mat.
void initAggloParticles()
Adds new generated particles to the list of non agglomerated Particles.
void findAgglomerates()
Detects and manages particle agglomerates.
void setContactDetection(ContactDetection< T, PARTICLETYPE > &contactDetection)
Set boundary detection algorithm (for future features)
PARTICLETYPE< T > & operator[](const int i)
Get reference to a particle in the ParticleSystem runs over all particles incl.
ContactDetection< T, PARTICLETYPE > * getContactDetection()
void setStoredValues()
Stores old particle positions - is used in ..._ActExt.
const std::vector< T > & getPhysExtend()
void addParticleOperation(std::shared_ptr< ParticleOperation3D< T, PARTICLETYPE > > pO)
Add an operation to ParticleSystem.
void partialElasticImpactForCombinationWithMechContactForce(T restitutionCoeff)
For the combined use of partialElasticImpact() and a mechanic contact force.
This class saves coordinates of the resulting point after rotation in the output field.
Representation of a statistic for a parallel 2D geometry.
This file contains two different classes of functors, in the FIRST part.
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
std::vector< T > fromVector3(const Vector< T, 3 > &vec)
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
cpu::simd::Pack< T > fabs(cpu::simd::Pack< T > value)
bool nearZero(const ADf< T, DIM > &a)
Top level namespace for all of OpenLB.
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
constexpr Vector< T, D > normalize(const ScalarVector< T, D, IMPL > &a, T scale=T{1})