29 const MInt domainId,
const MInt noDomains,
const MPI_Comm comm)
30 : m_collisionModel(collisionModel),
34 m_noDomains(noDomains),
53 m_outputStep = Context::getSolverProperty<MInt>(
"particleCollOutputStep", solverId(), AT_, &m_outputStep);
65 m_offset = Context::getSolverProperty<MFloat>(
"particleCollOffset", solverId(), AT_, &m_offset);
75 MBool ellipsoids =
false;
76 ellipsoids = Context::getSolverProperty<MBool>(
"particleIncludeEllipsoids", solverId(), AT_, &ellipsoids);
79 m_includeEllipsoids =
true;
88 m_ellipsoidCCD = Context::getSolverProperty<MInt>(
"particleEllipsoidCCD", solverId(), AT_, &m_ellipsoidCCD);
99 MInt particleSubDomainFactor[MAX_SPACE_DIMENSIONS];
100 for(
MInt i = 0; i < nDim; i++) {
101 particleSubDomainFactor[i] = 1;
102 particleSubDomainFactor[i] =
103 Context::getSolverProperty<MInt>(
"particleSubDomainFactor", solverId(), AT_, &particleSubDomainFactor[i], i);
114 MFloat maxCoord[MAX_SPACE_DIMENSIONS], halfLength;
115 for(
MInt i = 0; i < nDim; i++) {
116 halfLength = m_lpt->c_cellLengthAtLevel(m_lpt->c_level(0) + 1);
117 m_subDomainCoordOffset[i] = m_lpt->c_coordinate(0, i) - halfLength;
118 maxCoord[i] = m_lpt->c_coordinate(0, i) + halfLength;
121 for(
MInt j = 1; j < m_lpt->a_noCells(); j++) {
122 for(
MInt i = 0; i < nDim; i++) {
123 halfLength = m_lpt->c_cellLengthAtLevel(m_lpt->c_level(j) + 1);
124 if(m_subDomainCoordOffset[i] > m_lpt->c_coordinate(j, i) - halfLength) {
125 m_subDomainCoordOffset[i] = m_lpt->c_coordinate(j, i) - halfLength;
127 if(maxCoord[i] < m_lpt->c_coordinate(j, i) + halfLength) {
128 maxCoord[i] = m_lpt->c_coordinate(j, i) + halfLength;
134 for(
MInt i = 0; i < nDim; i++) {
135 m_subDomainSize[i] = (maxCoord[i] - m_subDomainCoordOffset[i]) / ((
MFloat)particleSubDomainFactor[i]);
136 m_noOfSubDomains[i] = particleSubDomainFactor[i];
137 m_totalSubDomains *= m_noOfSubDomains[i];
139 m_log << m_totalSubDomains <<
" subdomains for collision detection in this solver." << endl;
142 if(m_includeEllipsoids) {
151#ifdef MAIA_GCC_COMPILER
152#pragma GCC diagnostic push
153#pragma GCC diagnostic ignored "-Warray-bounds"
172 m_timeStep = timeStep;
174 MFloat currCollTime = 0.0, outtime;
175 MInt subIndex[3] = {numeric_limits<MInt>::max(), numeric_limits<MInt>::max(), numeric_limits<MInt>::max()};
177 MInt index = 1, index2 = 0;
178 MInt factor[MAX_SPACE_DIMENSIONS] = {numeric_limits<MInt>::max(), numeric_limits<MInt>::max(),
179 numeric_limits<MInt>::max()};
186 factor[1] = m_noOfSubDomains[0];
187 IF_CONSTEXPR(nDim == 3) { factor[2] = m_noOfSubDomains[0] * m_noOfSubDomains[1]; }
191 for(i1 = partList.begin(); i1 != partList.end(); i1++) {
193 if(!(*i1).toBeDeleted()) {
197 for(
MInt i = 0; i < nDim; i++) {
198 index2 =
MInt(floor(((*i1).m_position[i] - m_subDomainCoordOffset[i]) / m_subDomainSize[i]));
199 if((index2 < 0) || (index2 >= m_noOfSubDomains[i]))
204 index += factor[i] * index2;
209 if(!(*i1).isInvalid()) {
210 stringstream errorMessage;
211 errorMessage <<
" ERROR: timestep " <<
globalTimeStep <<
" proc " << domainId() <<
" - particle "
212 << (*i1).m_partId <<
" is lost!"
213 <<
" coord " << (*i1).m_position[0] <<
" " << (*i1).m_position[1] <<
" " << (*i1).m_position[2]
214 <<
" oldcoord " << (*i1).m_oldPos[0] <<
" " << (*i1).m_oldPos[1] <<
" " << (*i1).m_oldPos[2]
215 <<
" cellId " << (*i1).m_cellId <<
" coords " << m_lpt->c_coordinate((*i1).m_cellId, 0) <<
" "
216 << m_lpt->c_coordinate((*i1).m_cellId, 1) <<
" " << m_lpt->c_coordinate((*i1).m_cellId, 2)
217 <<
" halfLength " << m_lpt->c_cellLengthAtLevel(m_lpt->c_level((*i1).m_cellId) + 1) << endl;
218 m_log << errorMessage.str();
220 if(!(*i1).wasSend() && !(*i1).toBeDeleted()) {
221 (*i1).toBeDeleted() =
true;
222 m_log <<
"particle was lost " << endl;
225 subDomainContent[index].subDomain.push_back(i1);
230 if(m_includeEllipsoids) {
233 while(i2 != partListEllipsoid.end()) {
235 if(!(*i2).toBeDeleted()) {
238 for(
MInt i = 0; i < nDim; i++) {
239 index2 =
MInt(floor(((*i2).m_position[i] - m_subDomainCoordOffset[i]) / m_subDomainSize[i]));
240 if((index2 < 0) || (index2 >= m_noOfSubDomains[i])) {
244 index += factor[i] * index2;
249 if(!(*i2).isInvalid()) {
250 stringstream errorMessage;
251 errorMessage <<
" ERROR: timestep " <<
globalTimeStep <<
" proc " << domainId() <<
" - particle "
252 << (*i2).m_partId <<
" is lost!"
253 <<
" coord " << (*i2).m_position[0] <<
" " << (*i2).m_position[1] <<
" " << (*i2).m_position[2]
254 <<
" cellId " << (*i1).m_cellId <<
" coords " << m_lpt->c_coordinate((*i2).m_cellId, 0) <<
" "
255 << m_lpt->c_coordinate((*i2).m_cellId, 1) <<
" " << m_lpt->c_coordinate((*i2).m_cellId, 2)
256 <<
" halfLength " << m_lpt->c_cellLengthAtLevel(m_lpt->c_level((*i2).m_cellId) + 1) << endl;
257 m_log << errorMessage.str();
259 if(!(*i2).toBeDeleted() && !(*i2).wasSend()) {
260 (*i2).toBeDeleted() =
true;
261 (*i2).toBeRespawn() =
true;
262 (*i2).isInvalid() =
true;
263 m_log <<
"particle was lost " << endl;
266 subDomainContentEllipsoid[index].subDomain.push_back(i2);
286 for(
MInt i = 0; i < m_totalSubDomains; i++) {
287 subIndex[0] = i % m_noOfSubDomains[0];
288 subIndex[1] = (i / m_noOfSubDomains[0]) % m_noOfSubDomains[1];
289 subIndex[2] = i / (m_noOfSubDomains[0] * m_noOfSubDomains[1]);
290 auto& currDomain = subDomainContent[i];
292 for(
MInt j = 0; j < (
MInt)currDomain.subDomain.size(); j++) {
295 for(
MInt l = j + 1; l < (
MInt)currDomain.subDomain.size(); l++) {
297 collisionCheck(currDomain.subDomain.at((
MUlong)j), currDomain.subDomain.at((
MUlong)l), currCollTime);
298 if(thisCollTime >= 0.0)
305 collList.push_back(thisColl);
316 if(((subIndex[0] + (k % 2)) < m_noOfSubDomains[0]) && ((subIndex[1] + ((k / 2) % 2)) < m_noOfSubDomains[1])) {
317 IF_CONSTEXPR(nDim == 3) {
318 if(!((subIndex[2] + (k / 4)) < m_noOfSubDomains[2])) {
323 i + (k % 2) + ((k / 2) % 2) * m_noOfSubDomains[0] + (k / 4) * m_noOfSubDomains[0] * m_noOfSubDomains[1];
324 for(
MInt l = 0; l < (
MInt)subDomainContent[index].subDomain.size(); l++) {
325 thisCollTime = collisionCheck(subDomainContent[i].subDomain.at((
MUlong)j),
326 subDomainContent[index].subDomain.at((
MUlong)l),
328 if(thisCollTime >= 0.0)
335 collList.push_back(thisColl);
341 if((subIndex[0] > 0) && (subIndex[1] < (m_noOfSubDomains[1] - 1))) {
342 index = i + m_noOfSubDomains[0] - 1;
343 for(
MInt l = 0; l < (
MInt)subDomainContent[index].subDomain.size(); l++) {
344 thisCollTime = collisionCheck(subDomainContent[i].subDomain.at((
MUlong)j),
345 subDomainContent[index].subDomain.at((
MUlong)l),
347 if(thisCollTime >= 0.0)
354 collList.push_back(thisColl);
358 IF_CONSTEXPR(nDim == 3) {
359 if((subIndex[0] > 0) && (subIndex[2] < (m_noOfSubDomains[2] - 1))) {
360 index = i + m_noOfSubDomains[0] * m_noOfSubDomains[1] - 1;
361 for(
MInt l = 0; l < (
MInt)subDomainContent[index].subDomain.size(); l++) {
362 thisCollTime = collisionCheck(subDomainContent[i].subDomain.at((
MUlong)j),
363 subDomainContent[index].subDomain.at((
MUlong)l),
365 if(thisCollTime >= 0.0)
372 collList.push_back(thisColl);
377 IF_CONSTEXPR(nDim == 3) {
378 if((subIndex[0] > 0) && (subIndex[1] < (m_noOfSubDomains[1] - 1))
379 && (subIndex[2] < (m_noOfSubDomains[2] - 1))) {
380 index = i + m_noOfSubDomains[0] * (1 + m_noOfSubDomains[1]) - 1;
381 for(
MInt l = 0; l < (
MInt)subDomainContent[index].subDomain.size(); l++) {
382 thisCollTime = collisionCheck(subDomainContent[i].subDomain.at((
MUlong)j),
383 subDomainContent[index].subDomain.at((
MUlong)l),
385 if(thisCollTime >= 0.0)
392 collList.push_back(thisColl);
398 if(m_includeEllipsoids) {
402 for(
MInt k = subIndex[0] - 1; k < subIndex[0] + 2; k++) {
403 if((k < 0) || (k >= m_noOfSubDomains[0])) {
406 for(
MInt l = subIndex[1] - 1; l < subIndex[1] + 2; l++) {
407 if((l < 0) || (l >= m_noOfSubDomains[1])) {
410 for(
MInt m = subIndex[2] - 1; m < subIndex[2] + 2; m++) {
411 if((m < 0) || (m >= m_noOfSubDomains[2])) {
414 index = k + m_noOfSubDomains[0] * l + m * m_noOfSubDomains[0] * m_noOfSubDomains[1];
415 for(
MInt n = 0; n < (
MInt)subDomainContentEllipsoid[index].subDomain.size(); n++) {
416 collisionCheckSphereEllipsoid(subDomainContent[i].subDomain.at((
MUlong)j),
417 subDomainContentEllipsoid[index].subDomain.at((
MUlong)n));
426 if(m_includeEllipsoids) {
441 for(
MInt i = 0; i < m_totalSubDomains; i++) {
442 subIndex[0] = i % m_noOfSubDomains[0];
443 subIndex[1] = (i / m_noOfSubDomains[0]) % m_noOfSubDomains[1];
444 subIndex[2] = i / (m_noOfSubDomains[0] * m_noOfSubDomains[1]);
446 for(
MInt j = 0; j < (
MInt)subDomainContentEllipsoid[i].subDomain.size(); j++) {
449 for(
MInt l = j + 1; l < (
MInt)subDomainContentEllipsoid[i].subDomain.size(); l++) {
450 collisionCheckEllipsoidEllipsoid(subDomainContentEllipsoid[i].subDomain.at((
MUlong)j),
451 subDomainContentEllipsoid[i].subDomain.at((
MUlong)l));
459 for(
MInt k = 1; k < 8; k++) {
462 if(((subIndex[0] + (k % 2)) < m_noOfSubDomains[0]) && ((subIndex[1] + ((k / 2) % 2)) < m_noOfSubDomains[1])) {
463 IF_CONSTEXPR(nDim == 3) {
464 if(!((subIndex[2] + (k / 4)) < m_noOfSubDomains[2])) {
469 i + (k % 2) + ((k / 2) % 2) * m_noOfSubDomains[0] + (k / 4) * m_noOfSubDomains[0] * m_noOfSubDomains[1];
470 for(
MInt l = 0; l < (
MInt)subDomainContentEllipsoid[index].subDomain.size(); l++) {
471 collisionCheckEllipsoidEllipsoid(subDomainContentEllipsoid[i].subDomain.at((
MUlong)j),
472 subDomainContentEllipsoid[index].subDomain.at((
MUlong)l));
477 if((subIndex[0] > 0) && (subIndex[1] < (m_noOfSubDomains[1] - 1))) {
478 index = i + m_noOfSubDomains[0] - 1;
479 for(
MInt l = 0; l < (
MInt)subDomainContentEllipsoid[index].subDomain.size(); l++) {
480 collisionCheckEllipsoidEllipsoid(subDomainContentEllipsoid[i].subDomain.at((
MUlong)j),
481 subDomainContentEllipsoid[index].subDomain.at((
MUlong)l));
484 if((subIndex[0] > 0) && (subIndex[2] < (m_noOfSubDomains[2] - 1))) {
485 index = i + m_noOfSubDomains[0] * m_noOfSubDomains[1] - 1;
486 for(
MInt l = 0; l < (
MInt)subDomainContentEllipsoid[index].subDomain.size(); l++) {
487 collisionCheckEllipsoidEllipsoid(subDomainContentEllipsoid[i].subDomain.at((
MUlong)j),
488 subDomainContentEllipsoid[index].subDomain.at((
MUlong)l));
491 if((subIndex[0] > 0) && (subIndex[1] < (m_noOfSubDomains[1] - 1))
492 && (subIndex[2] < (m_noOfSubDomains[2] - 1))) {
493 index = i + m_noOfSubDomains[0] * (1 + m_noOfSubDomains[1]) - 1;
494 for(
MInt l = 0; l < (
MInt)subDomainContentEllipsoid[index].subDomain.size(); l++) {
495 collisionCheckEllipsoidEllipsoid(subDomainContentEllipsoid[i].subDomain.at((
MUlong)j),
496 subDomainContentEllipsoid[index].subDomain.at((
MUlong)l));
506 while(!collList.empty()) {
509 thisColl = collList.front();
519 if(!(*collPair[0]).toBeDeleted()) {
520 switch(m_lpt->a_bndryCellId(bndryId)) {
524 if(!(*collPair[0]).wasSend() && !(*collPair[0]).toBeDeleted()) {
525 m_log <<
"particle left domain through outlet boundary" << endl;
526 (*collPair[0]).toBeDeleted() =
true;
527 (*collPair[0]).toBeRespawn() =
true;
528 (*collPair[0]).isInvalid() =
true;
537 MFloat l = checkBndryCross(bndryId, collPair[0], 0.0);
538 if(l >= 0.0 && l <= 1.1) {
540 if(!(*collPair[0]).wasSend() && !(*collPair[0]).toBeDeleted()) {
541 m_log <<
"particle left domain through inlet boundary" << endl;
542 (*collPair[0]).toBeDeleted() =
true;
543 (*collPair[0]).toBeRespawn() =
true;
544 (*collPair[0]).isInvalid() =
true;
558 MFloat bndryBasis[MAX_SPACE_DIMENSIONS][MAX_SPACE_DIMENSIONS];
559 MFloat normN[MAX_SPACE_DIMENSIONS - 1];
560 MFloat reboundVel[MAX_SPACE_DIMENSIONS];
561 MFloat oldCoordinates[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
562 numeric_limits<MFloat>::max()};
563 std::array<std::array<MFloat, MAX_SPACE_DIMENSIONS>, MAX_SPACE_DIMENSIONS> A;
564 std::array<MFloat, MAX_SPACE_DIMENSIONS>
b;
565 fill_n(A[0].data(), MAX_SPACE_DIMENSIONS * MAX_SPACE_DIMENSIONS, 0.0);
566 fill_n(
b.data(), MAX_SPACE_DIMENSIONS, 0.0);
568 MFloat lambda = outtime / timeStep;
570 for(
MInt i = 0; i < nDim; i++) {
572 (*collPair[0]).m_oldPos[i] + lambda * ((*collPair[0]).m_position[i] - (*collPair[0]).m_oldPos[i]);
573 normVel +=
POW2(m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i]
574 * ((*collPair[0]).m_position[i] - (*collPair[0]).m_oldPos[i]) / timeStep);
587 for(
MInt i = 0; i < nDim - 1; i++) {
591 for(
MInt i = 0; i < nDim - 1; i++) {
592 for(
MInt j = 0; j < nDim; j++) {
593 normN[i] +=
POW2(m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[i + 1][j]
594 - m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[0][j]);
598 for(
MInt i = 0; i < nDim - 1; i++) {
599 normN[i] = sqrt(normN[i]);
602 for(
MInt i = 0; i < nDim; i++) {
603 bndryBasis[i][0] = m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i];
604 for(
MInt j = 1; j < nDim; j++) {
605 bndryBasis[i][j] = (m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[j][i]
606 - m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[0][i])
613 for(
MInt i = 0; i < nDim; i++) {
614 A[0][i] = m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i];
615 for(
MInt j = 1; j < nDim; j++) {
616 A[j][i] = (m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[j][i]
617 - m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[0][i])
620 b[i] = (*collPair[0]).m_oldVel[i];
628 (*collPair[0]).m_oldVel[0] = 0.0;
629 reboundVel[0] = -
b[0];
631 for(
MInt i = 1; i < nDim; i++) {
632 (*collPair[0]).m_oldVel[i] = 0.0;
633 (*collPair[0]).m_velocity[i] = 0.0;
634 reboundVel[i] =
b[i];
639 for(
MInt i = 0; i < nDim; i++) {
640 for(
MInt j = 0; j < nDim; j++) {
641 (*collPair[0]).m_oldVel[i] += bndryBasis[i][j] * reboundVel[j];
642 (*collPair[0]).m_velocity[i] = (*collPair[0]).m_oldVel[i];
644 (*collPair[0]).m_position[i] = oldCoordinates[i] + (1.0 - lambda) * timeStep * (*collPair[0]).m_oldVel[i];
647 (*collPair[0]).checkCellChange(&(*collPair[0]).m_oldPos[0]);
650 for(
MInt i = 0; i < nDim; i++) {
651 (*collPair[0]).m_oldPos[i] = oldCoordinates[i] + (lambda - 1.0) * timeStep * (*collPair[0]).m_oldVel[i];
654 (*collPair[0]).hasCollided() =
true;
655 (*collPair[0]).firstStep() =
true;
670 cerr <<
"WARNING: This boundary condition not implemented for particles!" << endl;
671 cerr <<
"Treated as a solid wall" << endl;
682 if(!(*collPair[0]).toBeDeleted()) {
683 MInt subCollIndex[3] = {numeric_limits<MInt>::max(), numeric_limits<MInt>::max(),
684 numeric_limits<MInt>::max()};
686 for(
MInt i = 0; i < nDim; i++) {
687 subCollIndex[i] = (
MInt)(((*collPair[0]).m_position[i] - m_subDomainCoordOffset[i]) / m_subDomainSize[i]);
690 IF_CONSTEXPR(nDim == 2) {
695 for(
MInt i = (subCollIndex[0] - 1); i < (subCollIndex[0] + 2); i++) {
696 for(
MInt j = (subCollIndex[1] - 1); j < (subCollIndex[1] + 2); j++) {
697 if((i >= 0) && (i < m_noOfSubDomains[0]) && (j >= 0) && (j < m_noOfSubDomains[1])) {
698 _index2 = i + j * m_noOfSubDomains[0];
699 for(
MInt l = 0; l < (
MInt)subDomainContent[_index2].subDomain.size(); l++) {
700 if((collPair[0] != subDomainContent[_index2].subDomain.at((
MUlong)l))
701 && !((*subDomainContent[_index2].subDomain.at((
MUlong)l)).toBeDeleted())) {
703 collisionCheck(collPair[0], subDomainContent[_index2].subDomain.at((
MUlong)l), currCollTime);
704 if(_thisCollTime >= 0.0)
708 thisColl.
particle1 = subDomainContent[_index2].subDomain.at((
MUlong)l);
711 collList.push_back(thisColl);
725 for(
MInt i = (subCollIndex[0] - 1); i < (subCollIndex[0] + 2); i++) {
726 for(
MInt j = (subCollIndex[1] - 1); j < (subCollIndex[1] + 2); j++) {
727 for(
MInt k = (subCollIndex[2] - 1); k < (subCollIndex[2] + 2); k++) {
728 if((i >= 0) && (i < m_noOfSubDomains[0]) && (j >= 0) && (j < m_noOfSubDomains[1]) && (k >= 0)
729 && (k < m_noOfSubDomains[2])) {
730 _index2 = i + j * m_noOfSubDomains[0] + k * m_noOfSubDomains[0] * m_noOfSubDomains[1];
731 for(
MInt l = 0; l < (
MInt)subDomainContent[_index2].subDomain.size(); l++) {
732 if((collPair[0] != subDomainContent[_index2].subDomain.at((
MUlong)l))
733 && !((*subDomainContent[_index2].subDomain.at((
MUlong)l)).toBeDeleted())) {
735 collisionCheck(collPair[0], subDomainContent[_index2].subDomain.at((
MUlong)l), currCollTime);
736 if(__thisCollTime >= 0.0)
740 thisColl.
particle1 = subDomainContent[_index2].subDomain.at((
MUlong)l);
743 collList.push_back(thisColl);
754 geometryInteraction();
757 currCollTime = outtime;
760 MFloat wdotr = 0.0, relVel = 0.0, meanVel = 0.0, deltap = 0.0;
761 MFloat vi0[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
762 numeric_limits<MFloat>::max()};
763 MFloat vi1[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
764 numeric_limits<MFloat>::max()};
765 MFloat r[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
766 numeric_limits<MFloat>::max()};
767 MFloat x0old[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
768 numeric_limits<MFloat>::max()};
769 MFloat x1old[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
770 numeric_limits<MFloat>::max()};
771 MFloat partMass0, partMass1;
772 MFloat pointOfImpact[MAX_SPACE_DIMENSIONS] = {numeric_limits<MFloat>::max(), numeric_limits<MFloat>::max(),
773 numeric_limits<MFloat>::max()};
774 MFloat rLength = (*collPair[1]).m_diameter / ((*collPair[0]).m_diameter + (*collPair[1]).m_diameter);
783 MBool writeThisColl =
true;
784 MBool haloPart0 = (*collPair[0]).wasSend();
785 MBool haloPart1 = (*collPair[1]).wasSend();
786 MBool larger = ((*collPair[0]).m_partId > (*collPair[1]).m_partId);
787 if(haloPart0 & haloPart1) {
788 writeThisColl =
false;
790 if(haloPart0 ^ haloPart1) {
791 if(haloPart1 & larger) {
792 writeThisColl =
false;
794 if(haloPart0 & !larger) {
795 writeThisColl =
false;
801 for(
MInt k = 0; k < nDim; k++) {
802 vi0[k] = ((*collPair[0]).m_position[k] - (*collPair[0]).m_oldPos[k]) / timeStep;
803 vi1[k] = ((*collPair[1]).m_position[k] - (*collPair[1]).m_oldPos[k]) / timeStep;
804 r[k] = ((*collPair[0]).m_oldPos[k] + outtime * vi0[k]) - ((*collPair[1]).m_oldPos[k] + outtime * vi1[k]);
805 x0old[k] = (*collPair[0]).m_oldPos[k];
806 x1old[k] = (*collPair[1]).m_oldPos[k];
807 wdotr += r[k] * (vi0[k] - vi1[k]);
808 relVel +=
POW2(vi0[k] - vi1[k]);
809 meanVel +=
POW2(vi0[k] + vi1[k]);
811 pointOfImpact[k] = (*collPair[1]).m_oldPos[k] + outtime * vi1[k] + r[k] * rLength;
817 relVel = sqrt(relVel);
818 meanVel = 0.5 * sqrt(meanVel);
820 partMass0 = F1B6 * PI * (*collPair[0]).m_densityRatio *
POW3((*collPair[0]).m_diameter);
821 partMass1 = F1B6 * PI * (*collPair[1]).m_densityRatio *
POW3((*collPair[1]).m_diameter);
823 if((m_collisionModel == 1) || (m_collisionModel == 2)) {
826 for(
MInt k = 0; k < nDim; k++) {
827 deltap = -2.0 * wdotr * r[k]
828 / ((partMass0 + partMass1) * 0.25 *
POW2((*collPair[0]).m_diameter + (*collPair[1]).m_diameter));
829 (*collPair[0]).m_velocity[k] = vi0[k] + deltap * partMass1;
830 (*collPair[1]).m_velocity[k] = vi1[k] - deltap * partMass0;
831 (*collPair[0]).m_position[k] =
832 (*collPair[0]).m_oldPos[k] + vi0[k] * outtime + (*collPair[0]).m_velocity[k] * (timeStep - outtime);
833 (*collPair[1]).m_position[k] =
834 (*collPair[1]).m_oldPos[k] + vi1[k] * outtime + (*collPair[1]).m_velocity[k] * (timeStep - outtime);
838 (*collPair[0]).checkCellChange(x0old);
839 (*collPair[1]).checkCellChange(x1old);
841 for(
MInt k = 0; k < nDim; k++) {
843 (*collPair[0]).m_oldPos[k] = (*collPair[0]).m_position[k] - (*collPair[0]).m_velocity[k] * timeStep;
844 (*collPair[1]).m_oldPos[k] = (*collPair[1]).m_position[k] - (*collPair[1]).m_velocity[k] * timeStep;
847 (*collPair[0]).hasCollided() =
true;
848 (*collPair[0]).firstStep() =
true;
849 (*collPair[1]).hasCollided() =
true;
850 (*collPair[1]).firstStep() =
true;
852 if(m_collisionModel == 1) {
854 for(
MInt k = 0; k < nDim; k++) {
855 part2CFL +=
POW2((*collPair[1]).m_velocity[k]);
857 part2CFL *=
POW2(timeStep / (*collPair[1]).m_diameter);
858 if(part2CFL > 0.04) {
859 cout <<
"Caution: a particle CFL number of " << sqrt(part2CFL) <<
" has been found!\n";
868 if((m_collisionModel == 3) || (m_collisionModel == 4)) {
871 if((*collPair[0]).m_partId > (*collPair[1]).m_partId) {
872 qmax = (*collPair[0]).m_partId;
873 (*collPair[0]).m_partId = (*collPair[1]).m_partId;
874 (*collPair[1]).m_partId = qmax;
879 MFloat FSumMass = 1.0 / (partMass0 + partMass1);
881 for(
MInt k = 0; k < nDim; k++) {
882 (*collPair[0]).m_velocity[k] =
883 FSumMass * (partMass0 * (*collPair[0]).m_velocity[k] + partMass1 * (*collPair[1]).m_velocity[k]);
884 (*collPair[0]).m_oldVel[k] = (*collPair[1]).m_velocity[k];
885 (*collPair[0]).m_position[k] = FSumMass
886 * (partMass0 * ((*collPair[0]).m_oldPos[k] + outtime * vi0[k])
887 + partMass1 * ((*collPair[1]).m_oldPos[k] + outtime * vi1[k]))
888 + (timeStep - outtime) * (*collPair[0]).m_velocity[k];
892 (*collPair[0]).checkCellChange(x0old);
894 for(
MInt k = 0; k < nDim; k++) {
895 (*collPair[0]).m_oldPos[k] = (*collPair[0]).m_position[k] - timeStep * (*collPair[0]).m_velocity[k];
898 MFloat diam0 = (*collPair[0]).m_diameter;
899 MFloat diam1 = (*collPair[1]).m_diameter;
902 (*collPair[0]).m_diameter = pow(diam03 + diam13, F1B3);
903 (*collPair[0]).m_densityRatio =
904 (diam03 * (*collPair[0]).m_densityRatio + diam13 * (*collPair[1]).m_densityRatio) / (diam03 + diam13);
908 (*collPair[0]).hasCollided() =
true;
909 (*collPair[0]).firstStep() =
true;
916 (*collPair[1]).toBeDeleted() =
true;
917 (*collPair[0]).isInvalid() =
true;
920 if((m_collisionModel == 5) || (m_collisionModel == 6)) {
923 if(m_collisionModel == 5) {
925 for(
MInt k = 0; k < nDim; k++) {
926 part2CFL +=
POW2((*collPair[1]).m_velocity[k]);
928 part2CFL *=
POW2(timeStep / (*collPair[1]).m_diameter);
929 if(part2CFL > 0.04) {
930 cout <<
"Caution: a particle CFL number of " << sqrt(part2CFL) <<
" has been found!\n";
934 collList.pop_front();
939 if((m_collisionModel == 1) || (m_collisionModel == 3) || (m_collisionModel == 5)) {
941 for(
MInt k = 0; k < nDim; k++) {
942 part0CFL +=
POW2((*collPair[0]).m_velocity[k]);
944 part0CFL *=
POW2(timeStep / (*collPair[0]).m_diameter);
945 if(part0CFL > 0.04) {
946 cout <<
"Caution: a particle CFL number of " << sqrt(part0CFL) <<
" has been found!\n";
953 currCollTime = outtime;
955 if((m_collisionModel != 5) && (m_collisionModel != 6)) {
958 IF_CONSTEXPR(nDim == 2) {
964 for(
MInt q = 0; q < qmax; q++) {
965 if((*collPair[q]).toBeDeleted()) {
968 for(
MInt i = 0; i < nDim; i++) {
969 subIndex[i] = (
MInt)(((*collPair[q]).m_position[i] - m_subDomainCoordOffset[i]) / m_subDomainSize[i]);
972 for(
MInt i = (subIndex[0] - 1); i < (subIndex[0] + 2); i++) {
973 for(
MInt j = (subIndex[1] - 1); j < (subIndex[1] + 2); j++) {
974 if((i >= 0) && (i < m_noOfSubDomains[0]) && (j >= 0) && (j < m_noOfSubDomains[1])) {
975 MInt _index2 = i + j * m_noOfSubDomains[0];
976 for(
MInt l = 0; l < (
MInt)subDomainContent[_index2].subDomain.size(); l++) {
977 if((collPair[q] != subDomainContent[_index2].subDomain.at((
MUlong)l))
978 && !((*subDomainContent[_index2].subDomain.at((
MUlong)l)).toBeDeleted())) {
980 collisionCheck(collPair[q], subDomainContent[_index2].subDomain.at((
MUlong)l), currCollTime);
981 if(_thisCollTime >= 0.0)
985 thisColl.
particle1 = subDomainContent[_index2].subDomain.at((
MUlong)l);
988 collList.push_back(thisColl);
1004 for(
MInt q = 0; q < qmax; q++) {
1005 if((*collPair[q]).toBeDeleted()) {
1008 for(
MInt i = (subIndex[0] - 1); i < (subIndex[0] + 2); i++) {
1009 for(
MInt j = (subIndex[1] - 1); j < (subIndex[1] + 2); j++) {
1010 for(
MInt k = (subIndex[2] - 1); k < (subIndex[2] + 2); k++) {
1011 if((i >= 0) && (i < m_noOfSubDomains[0]) && (j >= 0) && (j < m_noOfSubDomains[1]) && (k >= 0)
1012 && (k < m_noOfSubDomains[2])) {
1013 MInt __index2 = i + j * m_noOfSubDomains[0] + k * m_noOfSubDomains[0] * m_noOfSubDomains[1];
1014 for(
MInt l = 0; l < (
MInt)subDomainContent[__index2].subDomain.size(); l++) {
1015 if((collPair[q] != subDomainContent[__index2].subDomain.at((
MUlong)l))
1016 && !((*subDomainContent[__index2].subDomain.at((
MUlong)l)).toBeDeleted())) {
1017 MFloat __thisCollTime = collisionCheck(
1018 collPair[q], subDomainContent[__index2].subDomain.at((
MUlong)l), currCollTime);
1019 if(__thisCollTime >= 0.0)
1023 thisColl.
particle1 = subDomainContent[__index2].subDomain.at((
MUlong)l);
1024 thisColl.
collTime = __thisCollTime;
1026 collList.push_back(thisColl);
1037 if(m_lpt->m_wallCollisions) {
1039 for(
MInt q = 0; q < qmax; q++) {
1040 if((*collPair[q]).toBeDeleted()) {
1043 geometryInteraction();
1052 if(pointOfImpact[0] > m_offset) {
1053 writeCollEvent(time, (*collPair[0]).m_partId, (*collPair[1]).m_partId, (*collPair[0]).m_diameter,
1054 (*collPair[1]).m_diameter, (*collPair[0]).m_densityRatio, (*collPair[1]).m_densityRatio,
1055 relVel, meanVel, pointOfImpact);
1061 for(
MInt i = 0; i < m_totalSubDomains; i++) {
1062 subDomainContent[i].subDomain.clear();
1065 if(m_includeEllipsoids) {
1066 for(
MInt i = 0; i < m_totalSubDomains; i++) {
1067 subDomainContentEllipsoid[i].subDomain.clear();
1072#ifdef MAIA_GCC_COMPILER
1073#pragma GCC diagnostic pop
1190 switch(m_collisionModel) {
1194 MFloat currDist, collDist, squaredw = 0.0, squaredr0 = 0.0;
1195 MFloat wdotr0 = 0.0, tempa, tempb;
1200 collDist =
POW2(0.5 * ((*i).m_diameter + (*j).m_diameter));
1203 if(currDist < collDist) {
1206 for(
MInt k = 0; k < nDim; k++) {
1207 tempa = (((*i).m_position[k] - (*i).m_oldPos[k]) - ((*j).m_position[k] - (*j).m_oldPos[k])) / m_timeStep;
1208 tempb = (*i).m_oldPos[k] - (*j).m_oldPos[k];
1209 squaredw +=
POW2(tempa);
1210 squaredr0 +=
POW2(tempb);
1211 wdotr0 += tempa * tempb;
1213 collTime = -(wdotr0 / squaredw) * (1.0 - sqrt(1.0 - squaredw * (squaredr0 - collDist) /
POW2(wdotr0)));
1221 MFloat bigK, squaredw = 0.0, squaredr0 = 0.0, wdotr0 = 0.0;
1224 for(
MInt k = 0; k < nDim; k++) {
1225 tempa = (((*i).m_position[k] - (*i).m_oldPos[k]) - ((*j).m_position[k] - (*j).m_oldPos[k])) / m_timeStep;
1226 tempb = (*i).m_oldPos[k] - (*j).m_oldPos[k];
1227 squaredw +=
POW2(tempa);
1228 squaredr0 +=
POW2(tempb);
1229 wdotr0 += tempa * tempb;
1234 tempb =
POW2(0.5 * ((*i).m_diameter + (*j).m_diameter));
1235 bigK = squaredw * (squaredr0 - tempb) /
POW2(wdotr0);
1243 bigK = sqrt(1.0 - bigK);
1244 tempa = -wdotr0 / squaredw;
1245 squaredw = tempa * (1.0 - bigK);
1246 squaredr0 = tempa * (1.0 + bigK);
1247 tempb = (squaredw < squaredr0) ? squaredw : squaredr0;
1249 if((tempb < m_timeStep) && (tempb >= currCollTime)) {
1257 mTerm(1, AT_,
"Unknown particle collision type");
1262 if(!(*i).toBeDeleted() && !(*j).toBeDeleted()) {
1282 if((*i1).m_position[0] < m_offset) {
1285 if((*i2).m_position[0] < m_offset) {
1289 switch(m_collisionModel) {
1294 collisionCheckSEP(i1, i2);
1301 if(m_ellipsoidCCD) {
1302 collisionCheckSECCD(i1, i2);
1304 collisionCheckSEP(i1, i2);
1309 mTerm(1, AT_,
"Unknown particle collision type");
1327 if((*i2).m_position[0] < m_offset) {
1330 if((*i3).m_position[0] < m_offset) {
1334 switch(m_collisionModel) {
1339 collisionCheckEEProActive(i2, i3);
1346 if(m_ellipsoidCCD) {
1347 collisionCheckEECCD(i2, i3);
1349 collisionCheckEEProActive(i2, i3);
1354 mTerm(1, AT_,
"Unknown particle collision type");
1373 MFloat deltaVdeltaX = F0;
1375 for(
MInt d = 0; d < nDim; ++d) {
1376 dist[d] = i1->m_oldPos[d] - i2->m_oldPos[d];
1377 MFloat deltaV = ((i1->m_position[d] - i1->m_oldPos[d]) - (i2->m_position[d] - i2->m_oldPos[d])) / m_timeStep;
1379 deltaVSq +=
POW2(deltaV);
1380 deltaVdeltaX +=
dist[d] * deltaV;
1382 if(
approx(deltaVSq, F0, MFloatEps)) {
1383 collisionCheckSERetroActive(i1, i2);
1387 MFloat i1minR = i1->m_diameter / F2;
1389 MFloat i2minR = min(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
1390 MFloat i2maxR = max(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
1397 MFloat bigKmax =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RmaxSq);
1401 bigKmax = sqrt(bigKmax);
1402 MFloat tempt1 = (-deltaVdeltaX - bigKmax) / deltaVSq;
1403 MFloat tempt2 = (-deltaVdeltaX + bigKmax) / deltaVSq;
1404 MFloat t1max = min(tempt1, tempt2);
1405 MFloat t2max = max(tempt1, tempt2);
1406 if(t1max > m_timeStep) {
1415 MFloat bigKmin =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RminSq);
1417 bigKmin = sqrt(bigKmin);
1418 tempt1 = (-deltaVdeltaX - bigKmin) / deltaVSq;
1419 tempt2 = (-deltaVdeltaX + bigKmin) / deltaVSq;
1420 MFloat t1min = min(tempt1, tempt2);
1421 MFloat t2min = max(tempt1, tempt2);
1422 if((t1min <= m_timeStep) && (t2min >= F0)) {
1425 thisColl.
part0 = (*i2).m_partId;
1426 thisColl.
part1 = (*i1).m_partId;
1431 thisColl.
dens0 = (*i2).m_densityRatio;
1432 thisColl.
dens1 = (*i1).m_densityRatio;
1433 thisColl.
collPosX = i1->m_oldPos[0] + (i1->m_position[0] - i1->m_oldPos[0]) * t1min / m_timeStep;
1434 thisColl.
collPosY = i1->m_oldPos[1] + (i1->m_position[1] - i1->m_oldPos[1]) * t1min / m_timeStep;
1435 thisColl.
collPosZ = i1->m_oldPos[2] + (i1->m_position[2] - i1->m_oldPos[2]) * t1min / m_timeStep;
1436 collQueueEllipsoid.push(thisColl);
1448 MFloat l2[3] = {1.0, 0.0, 0.0}, m2[3] = {0.0, 1.0, 0.0}, n2[3] = {0.0, 0.0, 1.0};
1449 MFloat tmin = (-deltaVdeltaX / deltaVSq) / m_timeStep;
1450 if((tmin < F0) || (tmin > F1)) {
1453 for(
MInt i = 0; i < 4; ++i) {
1454 partQuatA[i] = i2->m_oldQuaternion[i];
1456 distTminSq = deltaXSq;
1458 for(
MInt i = 0; i < 4; ++i) {
1459 partQuatA[i] = i2->m_quaternion[i];
1461 for(
MInt i = 0; i < nDim; ++i) {
1462 distTminSq +=
POW2(i1->m_position[i] - i2->m_position[i]);
1466 a[0] = 1.0 - 2.0 * (partQuatA[2] * partQuatA[2] + partQuatA[3] * partQuatA[3]);
1467 a[1] = 2.0 * (partQuatA[1] * partQuatA[2] + partQuatA[0] * partQuatA[3]);
1468 a[2] = 2.0 * (partQuatA[1] * partQuatA[3] - partQuatA[0] * partQuatA[2]);
1469 b[0] = 2.0 * (partQuatA[1] * partQuatA[2] - partQuatA[0] * partQuatA[3]);
1470 b[1] = 1.0 - 2.0 * (partQuatA[1] * partQuatA[1] + partQuatA[3] * partQuatA[3]);
1471 b[2] = 2.0 * (partQuatA[2] * partQuatA[3] + partQuatA[0] * partQuatA[1]);
1472 c[0] = 2.0 * (partQuatA[1] * partQuatA[3] + partQuatA[0] * partQuatA[2]);
1473 c[1] = 2.0 * (partQuatA[2] * partQuatA[3] - partQuatA[0] * partQuatA[1]);
1474 c[2] = 1.0 - 2.0 * (partQuatA[1] * partQuatA[1] + partQuatA[2] * partQuatA[2]);
1479 e = i2->m_oldQuaternion.data();
1480 a[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1481 a[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1482 a[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1483 e = i2->m_quaternion.data();
1484 b[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1485 b[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1486 b[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1490 for(
MInt dim = 0; dim < 3; ++dim) {
1496 for(
MInt dim = 0; dim < 3; ++dim) {
1497 innerProd += c[dim] *
a[dim];
1499 for(
MInt dim = 0; dim < 3; ++dim) {
1500 b[dim] =
a[dim] - innerProd * c[dim];
1503 a[0] =
b[1] * c[2] -
b[2] * c[1];
1504 a[1] =
b[2] * c[0] -
b[0] * c[2];
1505 a[2] =
b[0] * c[1] -
b[1] * c[0];
1508 for(
MInt dim = 0; dim < nDim; ++dim) {
1509 distTminSq +=
POW2((i1->m_position[dim] - i2->m_position[dim]) * tmin
1510 + (i1->m_oldPos[dim] - i2->m_oldPos[dim]) * (1 - tmin));
1524 (*i2).m_semiMinorAxis * (*i2).m_aspectRatio, i1minR, i1minR, i1minR);
1526 largestCollDistSquared =
POW2(largestCollDistSquared);
1528 if(distTminSq < largestCollDistSquared) {
1531 thisColl.
part0 = (*i2).m_partId;
1532 thisColl.
part1 = (*i1).m_partId;
1537 thisColl.
dens0 = (*i2).m_densityRatio;
1538 thisColl.
dens1 = (*i1).m_densityRatio;
1539 thisColl.
collPosX = i1->m_oldPos[0] + (i1->m_position[0] - i1->m_oldPos[0]) * tmin;
1540 thisColl.
collPosY = i1->m_oldPos[1] + (i1->m_position[1] - i1->m_oldPos[1]) * tmin;
1541 thisColl.
collPosZ = i1->m_oldPos[2] + (i1->m_position[2] - i1->m_oldPos[2]) * tmin;
1542 collQueueEllipsoid.push(thisColl);
1559 MFloat totalDistanceSquared = 0.0;
1561 for(
MInt i = 0; i < nDim; i++) {
1562 dist[i] = (*i2).m_position[i] - (*i1).m_position[i];
1563 totalDistanceSquared +=
POW2(
dist[i]);
1566 MFloat Length1 = 0.5 * (*i1).m_diameter;
1567 MFloat minLength2, maxLength2;
1568 minLength2 = (*i2).m_semiMinorAxis * (*i2).m_aspectRatio;
1569 if(minLength2 < (*i2).m_semiMinorAxis) {
1570 maxLength2 = (*i2).m_semiMinorAxis;
1572 maxLength2 = minLength2;
1573 minLength2 = (*i2).m_semiMinorAxis;
1579 MFloat largestCollDistSquared =
POW2(Length1 + maxLength2);
1580 if(totalDistanceSquared > largestCollDistSquared) {
1583 MFloat smallestCollDistSquared =
POW2(Length1 + minLength2);
1584 if(totalDistanceSquared < smallestCollDistSquared) {
1587 thisColl.
part0 = (*i2).m_partId;
1588 thisColl.
part1 = (*i1).m_partId;
1593 thisColl.
dens0 = (*i2).m_densityRatio;
1594 thisColl.
dens1 = (*i1).m_densityRatio;
1595 thisColl.
collPosX = i1->m_position[0];
1596 thisColl.
collPosY = i1->m_position[1];
1597 thisColl.
collPosZ = i1->m_position[2];
1598 collQueueEllipsoid.push(thisColl);
1610 A[0][0] = 1.0 - 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[2] + (*i2).m_quaternion[3] * (*i2).m_quaternion[3]);
1611 A[0][1] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[2] + (*i2).m_quaternion[0] * (*i2).m_quaternion[3]);
1612 A[0][2] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[3] - (*i2).m_quaternion[0] * (*i2).m_quaternion[2]);
1613 A[1][0] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[2] - (*i2).m_quaternion[0] * (*i2).m_quaternion[3]);
1614 A[1][1] = 1.0 - 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[1] + (*i2).m_quaternion[3] * (*i2).m_quaternion[3]);
1615 A[1][2] = 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[3] + (*i2).m_quaternion[0] * (*i2).m_quaternion[1]);
1616 A[2][0] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[3] + (*i2).m_quaternion[0] * (*i2).m_quaternion[2]);
1617 A[2][1] = 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[3] - (*i2).m_quaternion[0] * (*i2).m_quaternion[1]);
1618 A[2][2] = 1.0 - 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[1] + (*i2).m_quaternion[2] * (*i2).m_quaternion[2]);
1653 MFloat l1[3], m1[3], n1[3];
1654 MFloat l2[3] = {1.0, 0.0, 0.0}, m2[3] = {0.0, 1.0, 0.0}, n2[3] = {0.0, 0.0, 1.0};
1655 for(
MInt i = 0; i < 3; i++) {
1666 EllipsoidDistance theDistance(
dist, l1, m1, n1, l2, m2, n2, (*i2).m_semiMinorAxis, (*i2).m_semiMinorAxis,
1667 (*i2).m_semiMinorAxis * (*i2).m_aspectRatio, Length1, Length1, Length1);
1668 largestCollDistSquared = theDistance.
ellipsoids();
1669 largestCollDistSquared =
POW2(largestCollDistSquared);
1671 if(totalDistanceSquared < largestCollDistSquared) {
1674 thisColl.
part0 = (*i2).m_partId;
1675 thisColl.
part1 = (*i1).m_partId;
1680 thisColl.
dens0 = (*i2).m_densityRatio;
1681 thisColl.
dens1 = (*i1).m_densityRatio;
1682 thisColl.
collPosX = i1->m_position[0];
1683 thisColl.
collPosY = i1->m_position[1];
1684 thisColl.
collPosZ = i1->m_position[2];
1685 collQueueEllipsoid.push(thisColl);
1705 MFloat deltaVdeltaX = F0;
1707 for(
MInt d = 0; d < nDim; ++d) {
1708 dist[d] = i2->m_oldPos[d] - i3->m_oldPos[d];
1709 MFloat deltaV = ((i2->m_position[d] - i2->m_oldPos[d]) - (i3->m_position[d] - i3->m_oldPos[d])) / m_timeStep;
1711 deltaVSq +=
POW2(deltaV);
1712 deltaVdeltaX +=
dist[d] * deltaV;
1714 if(
approx(deltaVSq, F0, MFloatEps)) {
1715 collisionCheckEERetroActive(i2, i3);
1719 MFloat i2minR = min(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
1720 MFloat i2maxR = max(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
1721 MFloat i3minR = min(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
1722 MFloat i3maxR = max(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
1729 MFloat bigKmax =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RmaxSq);
1733 bigKmax = sqrt(bigKmax);
1734 MFloat tempt1 = (-deltaVdeltaX - bigKmax) / deltaVSq;
1735 MFloat tempt2 = (-deltaVdeltaX + bigKmax) / deltaVSq;
1736 MFloat t1max = min(tempt1, tempt2);
1737 MFloat t2max = max(tempt1, tempt2);
1738 if(t1max > m_timeStep) {
1747 MFloat bigKmin =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RminSq);
1749 bigKmin = sqrt(bigKmin);
1750 tempt1 = (-deltaVdeltaX - bigKmin) / deltaVSq;
1751 tempt2 = (-deltaVdeltaX + bigKmin) / deltaVSq;
1752 MFloat t1min = min(tempt1, tempt2);
1753 MFloat t2min = max(tempt1, tempt2);
1754 if((t1min <= m_timeStep) && (t2min >= F0)) {
1757 thisColl.
part0 = (*i2).m_partId;
1758 thisColl.
part1 = (*i3).m_partId;
1763 thisColl.
dens0 = (*i2).m_densityRatio;
1764 thisColl.
dens1 = (*i3).m_densityRatio;
1765 thisColl.
collPosX = i2->m_oldPos[0] + (i2->m_position[0] - i2->m_oldPos[0]) * t1min / m_timeStep;
1766 thisColl.
collPosY = i2->m_oldPos[1] + (i2->m_position[1] - i2->m_oldPos[1]) * t1min / m_timeStep;
1767 thisColl.
collPosZ = i2->m_oldPos[2] + (i2->m_position[2] - i2->m_oldPos[2]) * t1min / m_timeStep;
1768 collQueueEllipsoid.push(thisColl);
1778 MFloat a1[3], b1[3], c1[3];
1779 MFloat a2[3], b2[3], c2[3];
1781 MFloat tmin = (-deltaVdeltaX / deltaVSq) / m_timeStep;
1782 if((tmin < F0) || (tmin > F1)) {
1783 MFloat partQuatA[4], partQuatB[4];
1785 for(
MInt i = 0; i < 4; ++i) {
1786 partQuatA[i] = i2->m_oldQuaternion[i];
1787 partQuatB[i] = i3->m_oldQuaternion[i];
1789 distTminSq = deltaXSq;
1791 for(
MInt i = 0; i < 4; ++i) {
1792 partQuatA[i] = i2->m_quaternion[i];
1793 partQuatB[i] = i3->m_quaternion[i];
1796 for(
MInt i = 0; i < nDim; ++i) {
1797 distTminSq +=
POW2(i2->m_position[i] - i3->m_position[i]);
1801 a1[0] = 1.0 - 2.0 * (partQuatA[2] * partQuatA[2] + partQuatA[3] * partQuatA[3]);
1802 a1[1] = 2.0 * (partQuatA[1] * partQuatA[2] + partQuatA[0] * partQuatA[3]);
1803 a1[2] = 2.0 * (partQuatA[1] * partQuatA[3] - partQuatA[0] * partQuatA[2]);
1804 b1[0] = 2.0 * (partQuatA[1] * partQuatA[2] - partQuatA[0] * partQuatA[3]);
1805 b1[1] = 1.0 - 2.0 * (partQuatA[1] * partQuatA[1] + partQuatA[3] * partQuatA[3]);
1806 b1[2] = 2.0 * (partQuatA[2] * partQuatA[3] + partQuatA[0] * partQuatA[1]);
1807 c1[0] = 2.0 * (partQuatA[1] * partQuatA[3] + partQuatA[0] * partQuatA[2]);
1808 c1[1] = 2.0 * (partQuatA[2] * partQuatA[3] - partQuatA[0] * partQuatA[1]);
1809 c1[2] = 1.0 - 2.0 * (partQuatA[1] * partQuatA[1] + partQuatA[2] * partQuatA[2]);
1812 a2[0] = 1.0 - 2.0 * (partQuatB[2] * partQuatB[2] + partQuatB[3] * partQuatB[3]);
1813 a2[1] = 2.0 * (partQuatB[1] * partQuatB[2] + partQuatB[0] * partQuatB[3]);
1814 a2[2] = 2.0 * (partQuatB[1] * partQuatB[3] - partQuatB[0] * partQuatB[2]);
1815 b2[0] = 2.0 * (partQuatB[1] * partQuatB[2] - partQuatB[0] * partQuatB[3]);
1816 b2[1] = 1.0 - 2.0 * (partQuatB[1] * partQuatB[1] + partQuatB[3] * partQuatB[3]);
1817 b2[2] = 2.0 * (partQuatB[2] * partQuatB[3] + partQuatB[0] * partQuatB[1]);
1818 c2[0] = 2.0 * (partQuatB[1] * partQuatB[3] + partQuatB[0] * partQuatB[2]);
1819 c2[1] = 2.0 * (partQuatB[2] * partQuatB[3] - partQuatB[0] * partQuatB[1]);
1820 c2[2] = 1.0 - 2.0 * (partQuatB[1] * partQuatB[1] + partQuatB[2] * partQuatB[2]);
1825 e = i2->m_oldQuaternion.data();
1826 a1[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1827 a1[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1828 a1[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1829 e = i2->m_quaternion.data();
1830 b1[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1831 b1[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1832 b1[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1833 slerp(a1, b1, tmin, c1, 3);
1836 for(
MInt dim = 0; dim < 3; ++dim) {
1842 for(
MInt dim = 0; dim < 3; ++dim) {
1843 innerProd += c1[dim] * a1[dim];
1845 for(
MInt dim = 0; dim < 3; ++dim) {
1846 b1[dim] = a1[dim] - innerProd * c1[dim];
1849 a1[0] = b1[1] * c1[2] - b1[2] * c1[1];
1850 a1[1] = b1[2] * c1[0] - b1[0] * c1[2];
1851 a1[2] = b1[0] * c1[1] - b1[1] * c1[0];
1854 e = i3->m_oldQuaternion.data();
1855 a2[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1856 a2[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1857 a2[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1858 e = i3->m_quaternion.data();
1859 b2[0] = 2.0 * (e[1] * e[3] + e[0] * e[2]);
1860 b2[1] = 2.0 * (e[2] * e[3] - e[0] * e[1]);
1861 b2[2] = 1.0 - 2.0 * (e[1] * e[1] + e[2] * e[2]);
1862 slerp(a2, b2, tmin, c2, 3);
1865 for(
MInt dim = 0; dim < nDim; ++dim) {
1871 for(
MInt dim = 0; dim < nDim; ++dim) {
1872 innerProd += c2[dim] * a2[dim];
1874 for(
MInt dim = 0; dim < nDim; ++dim) {
1875 b2[dim] = a2[dim] - innerProd * c2[dim];
1878 a2[0] = b2[1] * c2[2] - b2[2] * c2[1];
1879 a2[1] = b2[2] * c2[0] - b2[0] * c2[2];
1880 a2[2] = b2[0] * c2[1] - b2[1] * c2[0];
1884 for(
MInt dim = 0; dim < nDim; ++dim) {
1885 distTminSq +=
POW2((i2->m_position[dim] - i3->m_position[dim]) * tmin
1886 + (i2->m_oldPos[dim] - i3->m_oldPos[dim]) * (1 - tmin));
1899 EllipsoidDistance theDistance(
dist, a1, b1, c1, a2, b2, c2, (*i2).m_semiMinorAxis, (*i2).m_semiMinorAxis,
1900 (*i2).m_semiMinorAxis * (*i2).m_aspectRatio, (*i3).m_semiMinorAxis,
1901 (*i3).m_semiMinorAxis, (*i3).m_semiMinorAxis * (*i3).m_aspectRatio);
1903 largestCollDistSquared =
POW2(largestCollDistSquared);
1905 if(distTminSq < largestCollDistSquared) {
1908 thisColl.
part0 = (*i2).m_partId;
1909 thisColl.
part1 = (*i3).m_partId;
1914 thisColl.
dens0 = (*i2).m_densityRatio;
1915 thisColl.
dens1 = (*i3).m_densityRatio;
1916 thisColl.
collPosX = i2->m_oldPos[0] + (i2->m_position[0] - i2->m_oldPos[0]) * tmin;
1917 thisColl.
collPosY = i2->m_oldPos[1] + (i2->m_position[1] - i2->m_oldPos[1]) * tmin;
1918 thisColl.
collPosZ = i2->m_oldPos[2] + (i2->m_position[2] - i2->m_oldPos[2]) * tmin;
1919 collQueueEllipsoid.push(thisColl);
1936 MFloat totalDistanceSquared = 0.0;
1940 if((*i2).m_position[0] < m_offset) {
1943 if((*i3).m_position[0] < m_offset) {
1947 for(
MInt i = 0; i < nDim; i++) {
1948 dist[i] = (*i3).m_position[i] - (*i2).m_position[i];
1949 totalDistanceSquared +=
POW2(
dist[i]);
1952 MFloat minLength2, maxLength2, minLength3, maxLength3;
1953 minLength2 = (*i2).m_semiMinorAxis * (*i2).m_aspectRatio;
1954 if(minLength2 < (*i2).m_semiMinorAxis) {
1955 maxLength2 = (*i2).m_semiMinorAxis;
1957 maxLength2 = minLength2;
1958 minLength2 = (*i2).m_semiMinorAxis;
1960 minLength3 = (*i3).m_semiMinorAxis * (*i3).m_aspectRatio;
1961 if(minLength3 < (*i3).m_semiMinorAxis) {
1962 maxLength3 = (*i3).m_semiMinorAxis;
1964 maxLength3 = minLength3;
1965 minLength3 = (*i3).m_semiMinorAxis;
1971 MFloat largestCollDistSquared =
POW2(maxLength2 + maxLength3);
1972 if(totalDistanceSquared > largestCollDistSquared) {
1977 MFloat smallestCollDistSquared =
POW2(minLength2 + minLength3);
1978 if(totalDistanceSquared < smallestCollDistSquared) {
1981 thisColl.
part0 = (*i2).m_partId;
1982 thisColl.
part1 = (*i3).m_partId;
1987 thisColl.
dens0 = (*i2).m_densityRatio;
1988 thisColl.
dens1 = (*i3).m_densityRatio;
1989 thisColl.
collPosX = i2->m_position[0];
1990 thisColl.
collPosY = i2->m_position[1];
1991 thisColl.
collPosZ = i2->m_position[2];
1992 collQueueEllipsoid.push(thisColl);
2003 A[0][0] = 1.0 - 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[2] + (*i2).m_quaternion[3] * (*i2).m_quaternion[3]);
2004 A[0][1] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[2] + (*i2).m_quaternion[0] * (*i2).m_quaternion[3]);
2005 A[0][2] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[3] - (*i2).m_quaternion[0] * (*i2).m_quaternion[2]);
2006 A[1][0] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[2] - (*i2).m_quaternion[0] * (*i2).m_quaternion[3]);
2007 A[1][1] = 1.0 - 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[1] + (*i2).m_quaternion[3] * (*i2).m_quaternion[3]);
2008 A[1][2] = 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[3] + (*i2).m_quaternion[0] * (*i2).m_quaternion[1]);
2009 A[2][0] = 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[3] + (*i2).m_quaternion[0] * (*i2).m_quaternion[2]);
2010 A[2][1] = 2.0 * ((*i2).m_quaternion[2] * (*i2).m_quaternion[3] - (*i2).m_quaternion[0] * (*i2).m_quaternion[1]);
2011 A[2][2] = 1.0 - 2.0 * ((*i2).m_quaternion[1] * (*i2).m_quaternion[1] + (*i2).m_quaternion[2] * (*i2).m_quaternion[2]);
2018 B[0][0] = 1.0 - 2.0 * ((*i3).m_quaternion[2] * (*i3).m_quaternion[2] + (*i3).m_quaternion[3] * (*i3).m_quaternion[3]);
2019 B[0][1] = 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[2] + (*i3).m_quaternion[0] * (*i3).m_quaternion[3]);
2020 B[0][2] = 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[3] - (*i3).m_quaternion[0] * (*i3).m_quaternion[2]);
2021 B[1][0] = 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[2] - (*i3).m_quaternion[0] * (*i3).m_quaternion[3]);
2022 B[1][1] = 1.0 - 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[1] + (*i3).m_quaternion[3] * (*i3).m_quaternion[3]);
2023 B[1][2] = 2.0 * ((*i3).m_quaternion[2] * (*i3).m_quaternion[3] + (*i3).m_quaternion[0] * (*i3).m_quaternion[1]);
2024 B[2][0] = 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[3] + (*i3).m_quaternion[0] * (*i3).m_quaternion[2]);
2025 B[2][1] = 2.0 * ((*i3).m_quaternion[2] * (*i3).m_quaternion[3] - (*i3).m_quaternion[0] * (*i3).m_quaternion[1]);
2026 B[2][2] = 1.0 - 2.0 * ((*i3).m_quaternion[1] * (*i3).m_quaternion[1] + (*i3).m_quaternion[2] * (*i3).m_quaternion[2]);
2080 MFloat l1[3], m1[3], n1[3];
2081 MFloat l2[3], m2[3], n2[3];
2082 for(
MInt i = 0; i < 3; i++) {
2096 EllipsoidDistance theDistance(
dist, l1, m1, n1, l2, m2, n2, (*i2).m_semiMinorAxis, (*i2).m_semiMinorAxis,
2097 (*i2).m_semiMinorAxis * (*i2).m_aspectRatio, (*i3).m_semiMinorAxis,
2098 (*i3).m_semiMinorAxis, (*i3).m_semiMinorAxis * (*i3).m_aspectRatio);
2099 largestCollDistSquared = theDistance.
ellipsoids();
2100 largestCollDistSquared =
POW2(largestCollDistSquared);
2102 if(totalDistanceSquared < largestCollDistSquared) {
2105 thisColl.
part0 = (*i2).m_partId;
2106 thisColl.
part1 = (*i3).m_partId;
2111 thisColl.
dens0 = (*i2).m_densityRatio;
2112 thisColl.
dens1 = (*i3).m_densityRatio;
2113 thisColl.
collPosX = i2->m_position[0];
2114 thisColl.
collPosY = i2->m_position[1];
2115 thisColl.
collPosZ = i2->m_position[2];
2116 collQueueEllipsoid.push(thisColl);
2132 const MInt dim3 = 3;
2136 MFloat deltaVdeltaX = F0;
2138 for(
MInt d = 0; d < dim3; ++d) {
2139 dist[d] = i2->m_oldPos[d] - i3->m_oldPos[d];
2140 MFloat deltaV = ((i2->m_position[d] - i2->m_oldPos[d]) - (i3->m_position[d] - i3->m_oldPos[d])) / m_timeStep;
2142 deltaVSq +=
POW2(deltaV);
2143 deltaVdeltaX +=
dist[d] * deltaV;
2145 if(
approx(deltaVSq, F0, MFloatEps)) {
2146 collisionCheckEERetroActive(i2, i3);
2150 MFloat i2minR = min(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
2151 MFloat i2maxR = max(i2->m_semiMinorAxis, i2->m_semiMinorAxis * i2->m_aspectRatio);
2152 MFloat i3minR = min(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
2153 MFloat i3maxR = max(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
2160 MFloat bigKmax =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RmaxSq);
2164 bigKmax = sqrt(bigKmax);
2165 MFloat tempt1 = (-deltaVdeltaX - bigKmax) / deltaVSq;
2166 MFloat tempt2 = (-deltaVdeltaX + bigKmax) / deltaVSq;
2167 MFloat t1max = min(tempt1, tempt2);
2168 MFloat t2max = max(tempt1, tempt2);
2169 if(t1max > m_timeStep) {
2178 MFloat bigKmin =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RminSq);
2180 bigKmin = sqrt(bigKmin);
2181 tempt1 = (-deltaVdeltaX - bigKmin) / deltaVSq;
2182 tempt2 = (-deltaVdeltaX + bigKmin) / deltaVSq;
2183 MFloat t1min = min(tempt1, tempt2);
2184 MFloat t2min = max(tempt1, tempt2);
2185 if((t1min <= m_timeStep) && (t2min >= F0)) {
2188 thisColl.
part0 = (*i2).m_partId;
2189 thisColl.
part1 = (*i3).m_partId;
2194 thisColl.
dens0 = (*i2).m_densityRatio;
2195 thisColl.
dens1 = (*i3).m_densityRatio;
2196 thisColl.
collPosX = i2->m_oldPos[0] + (i2->m_position[0] - i2->m_oldPos[0]) * t1min / m_timeStep;
2197 thisColl.
collPosY = i2->m_oldPos[1] + (i2->m_position[1] - i2->m_oldPos[1]) * t1min / m_timeStep;
2198 thisColl.
collPosZ = i2->m_oldPos[2] + (i2->m_position[2] - i2->m_oldPos[2]) * t1min / m_timeStep;
2199 collQueueEllipsoid.push(thisColl);
2208 MFloat e0_1 = i2->m_quaternion[0];
2209 MFloat e1_1 = i2->m_quaternion[1];
2210 MFloat e2_1 = i2->m_quaternion[2];
2211 MFloat e3_1 = i2->m_quaternion[3];
2213 MFloat e0_2 = i3->m_quaternion[0];
2214 MFloat e1_2 = i3->m_quaternion[1];
2215 MFloat e2_2 = i3->m_quaternion[2];
2216 MFloat e3_2 = i3->m_quaternion[3];
2219 MA[0] = ((e0_1 * e0_1 + e1_1 * e1_1) - e2_1 * e2_1) - e3_1 * e3_1;
2220 MA[4] = 2.0 * e1_1 * e2_1 - 2.0 * e0_1 * e3_1;
2221 MA[8] = 2.0 * e0_1 * e2_1 + 2.0 * e1_1 * e3_1;
2222 MA[12] = i2->m_oldPos[0];
2223 MA[1] = 2.0 * e0_1 * e3_1 + 2.0 * e1_1 * e2_1;
2224 MA[5] = ((e0_1 * e0_1 - e1_1 * e1_1) + e2_1 * e2_1) - e3_1 * e3_1;
2225 MA[9] = 2.0 * e2_1 * e3_1 - 2.0 * e0_1 * e1_1;
2226 MA[13] = i2->m_oldPos[1];
2227 MA[2] = 2.0 * e1_1 * e3_1 - 2.0 * e0_1 * e2_1;
2228 MA[6] = 2.0 * e0_1 * e1_1 + 2.0 * e2_1 * e3_1;
2229 MA[10] = ((e0_1 * e0_1 - e1_1 * e1_1) - e2_1 * e2_1) + e3_1 * e3_1;
2230 MA[14] = i2->m_oldPos[2];
2237 invMB[0] = ((e0_2 * e0_2 + e1_2 * e1_2) - e2_2 * e2_2) - e3_2 * e3_2;
2238 invMB[4] = 2.0 * e0_2 * e3_2 + 2.0 * e1_2 * e2_2;
2239 invMB[8] = 2.0 * e1_2 * e3_2 - 2.0 * e0_2 * e2_2;
2240 invMB[12] = -(invMB[0] * i3->m_oldPos[0] + invMB[4] * i3->m_oldPos[1] + invMB[8] * i3->m_oldPos[2]);
2241 invMB[1] = 2.0 * e1_2 * e2_2 - 2.0 * e0_2 * e3_2;
2242 invMB[5] = ((e0_2 * e0_2 - e1_2 * e1_2) + e2_2 * e2_2) - e3_2 * e3_2;
2243 invMB[9] = 2.0 * e0_2 * e1_2 + 2.0 * e2_2 * e3_2;
2244 invMB[13] = -(invMB[1] * i3->m_oldPos[0] + invMB[5] * i3->m_oldPos[1] + invMB[9] * i3->m_oldPos[2]);
2245 invMB[2] = 2.0 * e0_2 * e2_2 + 2.0 * e1_2 * e3_2;
2246 invMB[6] = 2.0 * e2_2 * e3_2 - 2.0 * e0_2 * e1_2;
2247 invMB[10] = ((e0_2 * e0_2 - e1_2 * e1_2) - e2_2 * e2_2) + e3_2 * e3_2;
2248 invMB[14] = -(invMB[2] * i3->m_oldPos[0] + invMB[6] * i3->m_oldPos[1] + invMB[10] * i3->m_oldPos[2]);
2255 v_1[0] = (i2->m_position[0] - i2->m_oldPos[0]);
2256 v_1[1] = (i2->m_position[1] - i2->m_oldPos[1]);
2257 v_1[2] = (i2->m_position[2] - i2->m_oldPos[2]);
2260 v_2[0] = (i3->m_position[0] - i3->m_oldPos[0]);
2261 v_2[1] = (i3->m_position[1] - i3->m_oldPos[1]);
2262 v_2[2] = (i3->m_position[2] - i3->m_oldPos[2]);
2264 MFloat A[16] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0};
2265 A[0] = 1 / (i2->m_semiMinorAxis * i2->m_semiMinorAxis);
2267 A[10] = 1 / (i2->m_semiMinorAxis * i2->m_semiMinorAxis * i2->m_aspectRatio * i2->m_aspectRatio);
2270 / (i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_semiMinorAxis
2271 * i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_aspectRatio * i3->m_aspectRatio);
2275 createMatrix_CCD(MA, v_1, invMB, v_2, i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio, b_Matrix, m);
2283 MFloat positive1 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t1);
2284 if(positive1 < 0.0) {
2287 MFloat positive2 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t2);
2288 if(positive2 < 0.0) {
2291 collision = checkCSI_CCD(A, b_Matrix, m, detMinusB, t1, t2, positive1, positive2, iteration);
2299 thisColl.
part0 = (*i2).m_partId;
2300 thisColl.
part1 = (*i3).m_partId;
2305 thisColl.
dens0 = (*i2).m_densityRatio;
2306 thisColl.
dens1 = (*i3).m_densityRatio;
2307 thisColl.
collPosX = i2->m_position[0];
2308 thisColl.
collPosY = i2->m_position[1];
2309 thisColl.
collPosZ = i2->m_position[2];
2310 collQueueEllipsoid.push(thisColl);
2326 const MInt dim3 = 3;
2330 MFloat deltaVdeltaX = F0;
2332 for(
MInt d = 0; d < dim3; ++d) {
2333 dist[d] = i2->m_oldPos[d] - i3->m_oldPos[d];
2334 MFloat deltaV = ((i2->m_position[d] - i2->m_oldPos[d]) - (i3->m_position[d] - i3->m_oldPos[d])) / m_timeStep;
2336 deltaVSq +=
POW2(deltaV);
2337 deltaVdeltaX +=
dist[d] * deltaV;
2339 if(
approx(deltaVSq, F0, MFloatEps)) {
2340 collisionCheckSERetroActive(i2, i3);
2344 MFloat i1minR = i2->m_diameter / F2;
2346 MFloat i2minR = min(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
2347 MFloat i2maxR = max(i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio);
2354 MFloat bigKmax =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RmaxSq);
2358 bigKmax = sqrt(bigKmax);
2359 MFloat tempt1 = (-deltaVdeltaX - bigKmax) / deltaVSq;
2360 MFloat tempt2 = (-deltaVdeltaX + bigKmax) / deltaVSq;
2361 MFloat t1max = min(tempt1, tempt2);
2362 MFloat t2max = max(tempt1, tempt2);
2363 if(t1max > m_timeStep) {
2372 MFloat bigKmin =
POW2(deltaVdeltaX) - deltaVSq * (deltaXSq - RminSq);
2374 bigKmin = sqrt(bigKmin);
2375 tempt1 = (-deltaVdeltaX - bigKmin) / deltaVSq;
2376 tempt2 = (-deltaVdeltaX + bigKmin) / deltaVSq;
2377 MFloat t1min = min(tempt1, tempt2);
2378 MFloat t2min = max(tempt1, tempt2);
2379 if((t1min <= m_timeStep) && (t2min >= F0)) {
2382 thisColl.
part0 = (*i3).m_partId;
2383 thisColl.
part1 = (*i2).m_partId;
2388 thisColl.
dens0 = (*i3).m_densityRatio;
2389 thisColl.
dens1 = (*i2).m_densityRatio;
2390 thisColl.
collPosX = i2->m_oldPos[0] + (i2->m_position[0] - i2->m_oldPos[0]) * t1min / m_timeStep;
2391 thisColl.
collPosY = i2->m_oldPos[1] + (i2->m_position[1] - i2->m_oldPos[1]) * t1min / m_timeStep;
2392 thisColl.
collPosZ = i2->m_oldPos[2] + (i2->m_position[2] - i2->m_oldPos[2]) * t1min / m_timeStep;
2393 collQueueEllipsoid.push(thisColl);
2407 MFloat e0_2 = i3->m_quaternion[0];
2408 MFloat e1_2 = i3->m_quaternion[1];
2409 MFloat e2_2 = i3->m_quaternion[2];
2410 MFloat e3_2 = i3->m_quaternion[3];
2416 MA[12] = i2->m_oldPos[0];
2420 MA[13] = i2->m_oldPos[1];
2424 MA[14] = i2->m_oldPos[2];
2431 invMB[0] = ((e0_2 * e0_2 + e1_2 * e1_2) - e2_2 * e2_2) - e3_2 * e3_2;
2432 invMB[4] = 2.0 * e0_2 * e3_2 + 2.0 * e1_2 * e2_2;
2433 invMB[8] = 2.0 * e1_2 * e3_2 - 2.0 * e0_2 * e2_2;
2434 invMB[12] = -(invMB[0] * i3->m_oldPos[0] + invMB[4] * i3->m_oldPos[1] + invMB[8] * i3->m_oldPos[2]);
2435 invMB[1] = 2.0 * e1_2 * e2_2 - 2.0 * e0_2 * e3_2;
2436 invMB[5] = ((e0_2 * e0_2 - e1_2 * e1_2) + e2_2 * e2_2) - e3_2 * e3_2;
2437 invMB[9] = 2.0 * e0_2 * e1_2 + 2.0 * e2_2 * e3_2;
2438 invMB[13] = -(invMB[1] * i3->m_oldPos[0] + invMB[5] * i3->m_oldPos[1] + invMB[9] * i3->m_oldPos[2]);
2439 invMB[2] = 2.0 * e0_2 * e2_2 + 2.0 * e1_2 * e3_2;
2440 invMB[6] = 2.0 * e2_2 * e3_2 - 2.0 * e0_2 * e1_2;
2441 invMB[10] = ((e0_2 * e0_2 - e1_2 * e1_2) - e2_2 * e2_2) + e3_2 * e3_2;
2442 invMB[14] = -(invMB[2] * i3->m_oldPos[0] + invMB[6] * i3->m_oldPos[1] + invMB[10] * i3->m_oldPos[2]);
2449 v_1[0] = (i2->m_position[0] - i2->m_oldPos[0]);
2450 v_1[1] = (i2->m_position[1] - i2->m_oldPos[1]);
2451 v_1[2] = (i2->m_position[2] - i2->m_oldPos[2]);
2454 v_2[0] = (i3->m_position[0] - i3->m_oldPos[0]);
2455 v_2[1] = (i3->m_position[1] - i3->m_oldPos[1]);
2456 v_2[2] = (i3->m_position[2] - i3->m_oldPos[2]);
2458 MFloat A[16] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0};
2459 A[0] = 4.0 / (i2->m_diameter * i2->m_diameter);
2464 / (i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_semiMinorAxis
2465 * i3->m_semiMinorAxis * i3->m_semiMinorAxis * i3->m_aspectRatio * i3->m_aspectRatio);
2469 createMatrix_CCD(MA, v_1, invMB, v_2, i3->m_semiMinorAxis, i3->m_semiMinorAxis * i3->m_aspectRatio, b_Matrix, m);
2477 MFloat positive1 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t1);
2478 if(positive1 < 0.0) {
2481 MFloat positive2 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t2);
2482 if(positive2 < 0.0) {
2485 collision = checkCSI_CCD(A, b_Matrix, m, detMinusB, t1, t2, positive1, positive2, iteration);
2494 thisColl.
part0 = (*i2).m_partId;
2495 thisColl.
part1 = (*i3).m_partId;
2500 thisColl.
dens0 = (*i2).m_densityRatio;
2501 thisColl.
dens1 = (*i3).m_densityRatio;
2502 thisColl.
collPosX = i2->m_oldPos[0];
2503 thisColl.
collPosY = i2->m_oldPos[1];
2504 thisColl.
collPosZ = i2->m_oldPos[2];
2505 collQueueEllipsoid.push(thisColl);
2522 MFloat particleDiameter) {
2525 MFloat nx0 = 0.0, na = 0.0, nb = 0.0;
2527 for(
MInt i = 0; i < nDim; i++) {
2528 nx0 += m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i]
2529 * m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_planeCoordinates[0][i];
2530 na += m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i] * (*vectorId).m_oldPos[i];
2532 m_lpt->m_bndryCells->a[bndryId].m_srfcs[0]->m_normal[i] * ((*vectorId).m_position[i] - (*vectorId).m_oldPos[i]);
2535 return (nx0 - na + (0.5 * particleDiameter)) / nb;
2572 collQueueElem collData = {collisionTime, diam0, diam1, dens0, dens1, relVel,
2573 meanVel, x[0], x[1], x[2], particle0, particle1};
2574 collQueue.push(collData);
2602 MFloat b_y, c_y, d_y, e_y, f_y;
2603 b_j1 = (-invMB[0] * u2[0] - invMB[4] * u2[1]) - invMB[8] * u2[2];
2604 k1 = (-invMB[1] * u2[0] - invMB[5] * u2[1]) - invMB[9] * u2[2];
2605 l1 = (-invMB[2] * u2[0] - invMB[6] * u2[1]) - invMB[10] * u2[2];
2606 d1 = (MA[0] * invMB[2] + MA[1] * invMB[6]) + MA[2] * invMB[10];
2607 d2 = (MA[0] * invMB[1] + MA[1] * invMB[5]) + MA[2] * invMB[9];
2608 d3 = (MA[0] * invMB[0] + MA[1] * invMB[4]) + MA[2] * invMB[8];
2609 bla1 = (invMB[8] * d3 / (a_2 * a_2) + invMB[9] * d2 / (a_2 * a_2)) + invMB[10] * d1 / (c_2 * c_2);
2610 bla2 = (invMB[4] * d3 / (a_2 * a_2) + invMB[5] * d2 / (a_2 * a_2)) + invMB[6] * d1 / (c_2 * c_2);
2611 bla3 = (invMB[0] * d3 / (a_2 * a_2) + invMB[1] * d2 / (a_2 * a_2)) + invMB[2] * d1 / (c_2 * c_2);
2612 n[0] = (MA[2] * bla1 + MA[1] * bla2) + MA[0] * bla3;
2613 n[4] = (MA[6] * bla1 + MA[5] * bla2) + MA[4] * bla3;
2614 n[8] = (MA[10] * bla1 + MA[9] * bla2) + MA[8] * bla3;
2616 d1 = (MA[4] * invMB[2] + MA[5] * invMB[6]) + MA[6] * invMB[10];
2617 d2 = (MA[4] * invMB[1] + MA[5] * invMB[5]) + MA[6] * invMB[9];
2618 d3 = (MA[4] * invMB[0] + MA[5] * invMB[4]) + MA[6] * invMB[8];
2619 bla1 = (invMB[8] * d3 / (a_2 * a_2) + invMB[9] * d2 / (a_2 * a_2)) + invMB[10] * d1 / (c_2 * c_2);
2620 bla2 = (invMB[4] * d3 / (a_2 * a_2) + invMB[5] * d2 / (a_2 * a_2)) + invMB[6] * d1 / (c_2 * c_2);
2621 bla3 = (invMB[0] * d3 / (a_2 * a_2) + invMB[1] * d2 / (a_2 * a_2)) + invMB[2] * d1 / (c_2 * c_2);
2622 n[1] = (MA[2] * bla1 + MA[1] * bla2) + MA[0] * bla3;
2623 n[5] = (MA[6] * bla1 + MA[5] * bla2) + MA[4] * bla3;
2624 n[9] = (MA[10] * bla1 + MA[9] * bla2) + MA[8] * bla3;
2626 d1 = (MA[8] * invMB[2] + MA[9] * invMB[6]) + MA[10] * invMB[10];
2627 d2 = (MA[8] * invMB[1] + MA[9] * invMB[5]) + MA[10] * invMB[9];
2628 d3 = (MA[8] * invMB[0] + MA[9] * invMB[4]) + MA[10] * invMB[8];
2629 bla1 = (invMB[8] * d3 / (a_2 * a_2) + invMB[9] * d2 / (a_2 * a_2)) + invMB[10] * d1 / (c_2 * c_2);
2630 bla2 = (invMB[4] * d3 / (a_2 * a_2) + invMB[5] * d2 / (a_2 * a_2)) + invMB[6] * d1 / (c_2 * c_2);
2631 bla3 = (invMB[0] * d3 / (a_2 * a_2) + invMB[1] * d2 / (a_2 * a_2)) + invMB[2] * d1 / (c_2 * c_2);
2632 n[2] = (MA[2] * bla1 + MA[1] * bla2) + MA[0] * bla3;
2633 n[6] = (MA[6] * bla1 + MA[5] * bla2) + MA[4] * bla3;
2634 n[10] = (MA[10] * bla1 + MA[9] * bla2) + MA[8] * bla3;
2636 d1 = ((invMB[14] + invMB[2] * MA[12]) + invMB[6] * MA[13]) + invMB[10] * MA[14];
2637 d2 = ((invMB[13] + invMB[1] * MA[12]) + invMB[5] * MA[13]) + invMB[9] * MA[14];
2638 d3 = ((invMB[12] + invMB[0] * MA[12]) + invMB[4] * MA[13]) + invMB[8] * MA[14];
2639 bla1 = (invMB[8] * d3 / (a_2 * a_2) + invMB[9] * d2 / (a_2 * a_2)) + invMB[10] * d1 / (c_2 * c_2);
2640 bla2 = (invMB[4] * d3 / (a_2 * a_2) + invMB[5] * d2 / (a_2 * a_2)) + invMB[6] * d1 / (c_2 * c_2);
2641 bla3 = (invMB[0] * d3 / (a_2 * a_2) + invMB[1] * d2 / (a_2 * a_2)) + invMB[2] * d1 / (c_2 * c_2);
2642 n[3] = (MA[2] * bla1 + MA[1] * bla2) + MA[0] * bla3;
2643 n[7] = (MA[6] * bla1 + MA[5] * bla2) + MA[4] * bla3;
2644 n[11] = (MA[10] * bla1 + MA[9] * bla2) + MA[8] * bla3;
2645 n[15] = (((((-1.0 + MA[12] * bla3) + MA[13] * bla2) + MA[14] * bla1) + invMB[12] * d3 / (a_2 * a_2))
2646 + invMB[13] * d2 / (a_2 * a_2))
2647 + invMB[14] * d1 / (c_2 * c_2);
2651 d_y = b_j1 * d3 / (a_2 * a_2);
2652 e_y = k1 * d2 / (a_2 * a_2);
2653 f_y = l1 * d1 / (c_2 * c_2);
2657 d1 = ((l1 + invMB[2] * u1[0]) + invMB[6] * u1[1]) + invMB[10] * u1[2];
2658 d2 = ((k1 + invMB[1] * u1[0]) + invMB[5] * u1[1]) + invMB[9] * u1[2];
2659 d3 = ((b_j1 + invMB[0] * u1[0]) + invMB[4] * u1[1]) + invMB[8] * u1[2];
2660 bla1 = (invMB[8] * d3 / (a_2 * a_2) + invMB[9] * d2 / (a_2 * a_2)) + invMB[10] * d1 / (c_2 * c_2);
2661 bla2 = (invMB[4] * d3 / (a_2 * a_2) + invMB[5] * d2 / (a_2 * a_2)) + invMB[6] * d1 / (c_2 * c_2);
2662 bla3 = (invMB[0] * d3 / (a_2 * a_2) + invMB[1] * d2 / (a_2 * a_2)) + invMB[2] * d1 / (c_2 * c_2);
2663 m[0] = (MA[2] * bla1 + MA[1] * bla2) + MA[0] * bla3;
2664 m[1] = (MA[6] * bla1 + MA[5] * bla2) + MA[4] * bla3;
2665 m[2] = (MA[10] * bla1 + MA[9] * bla2) + MA[8] * bla3;
2666 m[3] = ((((((((((
y + b_y) + c_y) + d_y) + e_y) + f_y) + MA[12] * bla3) + MA[13] * bla2) + MA[14] * bla1)
2667 + invMB[12] * d3 / (a_2 * a_2))
2668 + invMB[13] * d2 / (a_2 * a_2))
2669 + invMB[14] * d1 / (c_2 * c_2);
2670 m[4] = ((((u1[0] * bla3 + u1[1] * bla2) + u1[2] * bla1) + b_j1 * d3 / (a_2 * a_2)) + k1 * d2 / (a_2 * a_2))
2671 + l1 * d1 / (c_2 * c_2);
2689 const MFloat eps = 1.0E-13;
2692 copy(b_Matrix, b_Matrix + 16,
b);
2693 b[12] =
b[12] + m[0] * t;
2694 b[13] =
b[13] + m[1] * t;
2695 b[14] =
b[14] + m[2] * t;
2696 b[15] =
b[15] + m[3] * t + m[4] * t * t;
2705 MFloat termA = (
b[0] * A[5] * A[10] +
b[5] * A[0] * A[10]) +
b[10] * A[0] * A[5];
2706 MFloat termB = ((b2233 - b23s) * A[0] + (
b[0] *
b[10] - b13s) * A[5]) + (
b[0] *
b[5] - b12s) * A[10];
2708 MFloat T4 = -A[0] * A[5] * A[10];
2709 MFloat T3 = termA +
b[15] * T4;
2710 MFloat T2 = (((termA *
b[15] - termB) - b34s * A[0] * A[5]) - b14s * A[5] * A[10]) - b24s * A[0] * A[10];
2712 MFloat tmp2 =
b[0] * (b2233 + A[5] * b34s + A[10] * b24s - b23s);
2713 MFloat tmp3 =
b[5] * (A[0] * b34s + A[10] * b14s - b13s);
2714 MFloat tmp4 =
b[10] * (A[0] * b24s + A[5] * b14s - b12s);
2715 MFloat tmp5 =
b[14] * (A[0] *
b[9] *
b[13] + A[5] *
b[8] *
b[12]) +
b[4] * (A[10] *
b[12] *
b[13] -
b[8] *
b[9]);
2717 MFloat T1 = -tmp1 + tmp2 + tmp3 + tmp4 - tmp5;
2720 MFloat t4 = (T0 + T1 + T2 + T3 + T4);
2721 MFloat t3 = (-T1 - 2 * T2 - 3 * T3 - 4 * T4);
2722 MFloat t2 = (T2 + 3 * T3 + 6 * T4);
2723 MFloat t1 = (-T3 - 4 * T4);
2731 MFloat p = (3 *
a * c - bb * bb) / (3 *
a *
a);
2732 MFloat q = (2 * bb * bb * bb - 9 *
a * bb * c + 27 *
a *
a * d) / (27 *
a *
a *
a);
2735 MFloat term = sqrt(p / 3.0);
2736 MFloat u = -2 * term * sinh((1.0 / 3.0) * asinh((3 * q / (2 * p)) / term)) - bb / (3 *
a);
2737 return testU_CCD(u, t4, t3, t2, t1, t0);
2739 MFloat test = 4 * p * p * p + 27 * q * q;
2740 MFloat term = sqrt(-p / 3.0);
2743 -2 * fabs(q) / q * term * cosh((1.0 / 3.0) * acosh((-3 * fabs(q) / (2 * p)) / term)) - bb / (3 *
a);
2744 return testU_CCD(u, t4, t3, t2, t1, t0);
2746 for(
MInt that = 0; that < 3; that++) {
2748 2 * term * cos((1.0 / 3.0) * acos((3 * q / (2 * p)) / term) - that * 2 * PI / 3.0) - bb / (3 *
a);
2749 MFloat positive = testU_CCD(u, t4, t3, t2, t1, t0);
2758 MFloat u = pow(-q, (1.0 / 3.0)) - bb / (3 *
a);
2759 return testU_CCD(u, t4, t3, t2, t1, t0);
2762 return testU_CCD(u, t4, t3, t2, t1, t0);
2766 if(fabs(bb) > eps) {
2767 MFloat p_2 = c / bb / 2.0;
2769 MFloat temp = p_2 * p_2 - q;
2773 MFloat positive = testU_CCD(u, t4, t3, t2, t1, t0);
2778 return testU_CCD(u, t4, t3, t2, t1, t0);
2785 return testU_CCD(u, t4, t3, t2, t1, t0);
2819 if(t2 - t1 < 1.0E-13) {
2825 for(
MInt q0 = 0; q0 < 16; q0++) {
2826 b_A[q0] = A[q0] * (positive1 - 1.0) - positive1 * b_Matrix[q0];
2830 for(
MInt q0 = 0; q0 < 5; q0++) {
2831 b_positive1[q0] = -positive1 * m[q0];
2834 t1 = checkDynamicOverlap_CCD(b_A, b_positive1, t1, t2);
2838 for(
MInt q0 = 0; q0 < 16; q0++) {
2839 b_A[q0] = A[q0] * (positive2 - 1.0) - positive2 * b_Matrix[q0];
2842 for(
MInt q0 = 0; q0 < 5; q0++) {
2843 b_positive1[q0] = -positive2 * m[q0];
2846 t2 = checkDynamicOverlap_CCD(b_A, b_positive1, t2, t1);
2850 MFloat t_neu = (t1 + t2) / 2.0;
2851 MFloat positive_neu = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t_neu);
2852 if(positive_neu < 0.0) {
2855 positive1 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t1);
2856 MBool value = checkCSI_CCD(A, b_Matrix, m, detMinusB, t1, t_neu, positive1, positive_neu, iteration);
2860 positive2 = checkStaticOverlap_CCD(b_Matrix, A, m, detMinusB, t2);
2861 if(positive2 < 0.0) {
2864 return checkCSI_CCD(A, b_Matrix, m, detMinusB, t_neu, t2, positive_neu, positive2, iteration);
2886 if((u > 0) && (u <= 1)) {
2887 MFloat result = t4 * u * u * u * u + t3 * u * u * u + t2 * u * u + t1 * u + t0;
2926 AA = (((((((((((((((m[0] * m[0] * (n[9] * n[9]) - n[5] * n[10] * (m[0] * m[0])) + 2.0 * n[10] * m[0] * m[1] * n[4])
2927 - 2.0 * m[0] * m[1] * n[8] * n[9])
2928 - 2.0 * m[0] * m[2] * n[4] * n[9])
2929 + 2.0 * n[5] * m[0] * m[2] * n[8])
2930 + m[1] * m[1] * (n[8] * n[8]))
2931 - n[0] * n[10] * (m[1] * m[1]))
2932 - 2.0 * m[1] * m[2] * n[4] * n[8])
2933 + 2.0 * n[0] * m[1] * m[2] * n[9])
2934 + m[2] * m[2] * (n[4] * n[4]))
2935 - n[0] * n[5] * (m[2] * m[2]))
2936 - m[4] * n[10] * (n[4] * n[4]))
2937 + 2.0 * m[4] * n[4] * n[8] * n[9])
2938 - m[4] * n[5] * (n[8] * n[8]))
2939 - m[4] * n[0] * (n[9] * n[9]))
2940 + m[4] * n[0] * n[5] * n[10];
2941 BB = (((((((((((((((((((((2.0 * n[13] * m[1] * (n[8] * n[8]) + 2.0 * n[14] * m[2] * (n[4] * n[4]))
2942 + 2.0 * n[12] * m[0] * (n[9] * n[9]))
2943 - m[3] * n[0] * (n[9] * n[9]))
2944 - m[3] * (n[8] * n[8]) * n[5])
2945 - m[3] * (n[4] * n[4]) * n[10])
2946 - 2.0 * n[13] * m[2] * n[4] * n[8])
2947 - 2.0 * m[1] * n[14] * n[4] * n[8])
2948 - 2.0 * n[12] * m[1] * n[8] * n[9])
2949 - 2.0 * m[0] * n[13] * n[8] * n[9])
2950 - 2.0 * n[12] * m[2] * n[4] * n[9])
2951 + 2.0 * n[12] * m[2] * n[8] * n[5])
2952 - 2.0 * m[0] * n[14] * n[4] * n[9])
2953 + 2.0 * m[0] * n[14] * n[8] * n[5])
2954 + 2.0 * n[13] * m[2] * n[0] * n[9])
2955 + 2.0 * m[1] * n[14] * n[0] * n[9])
2956 - 2.0 * n[14] * m[2] * n[0] * n[5])
2957 + 2.0 * n[12] * m[1] * n[4] * n[10])
2958 + 2.0 * m[0] * n[13] * n[4] * n[10])
2959 - 2.0 * n[13] * m[1] * n[0] * n[10])
2960 - 2.0 * n[12] * m[0] * n[5] * n[10])
2961 + 2.0 * m[3] * n[4] * n[8] * n[9])
2962 + m[3] * n[0] * n[5] * n[10];
2963 CC = (((((((((((((((n[12] * n[12] * (n[9] * n[9]) - n[5] * n[10] * (n[12] * n[12]))
2964 + 2.0 * n[10] * n[12] * n[13] * n[4])
2965 - 2.0 * n[12] * n[13] * n[8] * n[9])
2966 - 2.0 * n[12] * n[14] * n[4] * n[9])
2967 + 2.0 * n[5] * n[12] * n[14] * n[8])
2968 + n[13] * n[13] * (n[8] * n[8]))
2969 - n[0] * n[10] * (n[13] * n[13]))
2970 - 2.0 * n[13] * n[14] * n[4] * n[8])
2971 + 2.0 * n[0] * n[13] * n[14] * n[9])
2972 + n[14] * n[14] * (n[4] * n[4]))
2973 - n[0] * n[5] * (n[14] * n[14]))
2974 - n[15] * n[10] * (n[4] * n[4]))
2975 + 2.0 * n[15] * n[4] * n[8] * n[9])
2976 - n[15] * n[5] * (n[8] * n[8]))
2977 - n[15] * n[0] * (n[9] * n[9]))
2978 + n[15] * n[0] * n[5] * n[10];
2979 if(fabs(AA) > 1.0E-13) {
2980 p_2 = BB / (2.0 * AA);
2981 BB = p_2 * p_2 - CC / AA;
2983 BB = side * sqrt(BB);
2985 if((t >= t1) && (t <= t2)) {
2988 if((t >= t1) && (t <= t2)) {
2996 }
else if(fabs(BB) > 1.0E-13) {
2998 if((t >= t1) && (t <= t2)) {
3019 MInt ncmpiCollQueueSize = (
MInt)collQueue.size();
3022 MPI_Allgather(&ncmpiCollQueueSize, 1, MPI_INT, &ncmpiCollCount[0], 1, MPI_INT, mpiComm(), AT_,
"ncmpiCollQueueSize",
3023 "ncmpiCollCount[0]");
3025 MInt ncmpiCollCountMax = 0;
3026 for(
MInt i = 0; i < noDomains(); ++i) {
3027 ncmpiCollCountMax += ncmpiCollCount[i];
3031 if(ncmpiCollCountMax != 0) {
3034 stringstream ncmpistream;
3035 string ncmpiFileName;
3036 ncmpistream <<
"out/collData." <<
globalTimeStep << ParallelIo::fileExt();
3037 ncmpistream >> ncmpiFileName;
3038 ncmpistream.clear();
3041 ParallelIo parallelIo(ncmpiFileName, PIO_REPLACE, mpiComm());
3044 parallelIo.setAttribute(m_lpt->m_timeStep,
"particleTimestep");
3048 parallelIo.defineArray(PIO_INT,
"collCount", noDomains());
3051 parallelIo.defineArray(PIO_FLOAT,
"collTime", ncmpiCollCountMax);
3052 parallelIo.defineArray(PIO_INT,
"part0", ncmpiCollCountMax);
3053 parallelIo.defineArray(PIO_INT,
"part1", ncmpiCollCountMax);
3054 parallelIo.defineArray(PIO_FLOAT,
"p0diam", ncmpiCollCountMax);
3055 parallelIo.defineArray(PIO_FLOAT,
"p1diam", ncmpiCollCountMax);
3056 parallelIo.defineArray(PIO_FLOAT,
"p0dens", ncmpiCollCountMax);
3057 parallelIo.defineArray(PIO_FLOAT,
"p1dens", ncmpiCollCountMax);
3058 parallelIo.defineArray(PIO_FLOAT,
"relVel", ncmpiCollCountMax);
3059 parallelIo.defineArray(PIO_FLOAT,
"meanVel", ncmpiCollCountMax);
3060 parallelIo.defineArray(PIO_FLOAT,
"collPos", 3 * ncmpiCollCountMax);
3064 ParallelIo::size_type ncmpiStart = domainId();
3065 ParallelIo::size_type ncmpiCount = 1;
3067 parallelIo.setOffset(ncmpiCount, ncmpiStart);
3068 parallelIo.writeArray(&ncmpiCollQueueSize,
"collCount");
3071 for(
MInt i = 0; i < domainId(); ++i) {
3072 ncmpiStart += ncmpiCollCount[i];
3074 ncmpiCount = ncmpiCollCount[domainId()];
3075 if(ncmpiStart >= ncmpiCollCountMax) {
3076 if(ncmpiCount == 0) {
3080 "Error in LPT::writeCollData!! ncmpiStart >= "
3081 "ncmpiCollCountMax but ncmpiCount != 0");
3087 MIntScratchSpace ncmpiPart0(ncmpiCollCount[domainId()], AT_,
"ncmpiCollTime");
3088 MIntScratchSpace ncmpiPart1(ncmpiCollCount[domainId()], AT_,
"ncmpiCollTime");
3095 MFloatScratchSpace ncmpiCollPos(3 * ncmpiCollCount[domainId()], AT_,
"ncmpiCollTime");
3096 MInt ncmpiCountId = 0;
3099 while(!collQueue.empty()) {
3100 ncmpiCollTime[ncmpiCountId] = collQueue.front().collTime;
3101 ncmpiPart0[ncmpiCountId] = collQueue.front().part0;
3102 ncmpiPart1[ncmpiCountId] = collQueue.front().part1;
3103 ncmpiP0Diam[ncmpiCountId] = collQueue.front().diam0;
3104 ncmpiP1Diam[ncmpiCountId] = collQueue.front().diam1;
3105 ncmpiP0Dens[ncmpiCountId] = collQueue.front().dens0;
3106 ncmpiP1Dens[ncmpiCountId] = collQueue.front().dens1;
3107 ncmpiRelVel[ncmpiCountId] = collQueue.front().relVel;
3108 ncmpiMeanVel[ncmpiCountId] = collQueue.front().meanVel;
3109 ncmpiCollPos[(3 * ncmpiCountId)] = collQueue.front().collPosX;
3110 ncmpiCollPos[(3 * ncmpiCountId) + 1] = collQueue.front().collPosY;
3111 ncmpiCollPos[(3 * ncmpiCountId) + 2] = collQueue.front().collPosZ;
3118 parallelIo.setOffset(ncmpiCount, ncmpiStart);
3119 parallelIo.writeArray(&ncmpiCollTime[0],
"collTime");
3120 parallelIo.writeArray(&ncmpiPart0[0],
"part0");
3121 parallelIo.writeArray(&ncmpiPart1[0],
"part1");
3122 parallelIo.writeArray(&ncmpiP0Diam[0],
"p0diam");
3123 parallelIo.writeArray(&ncmpiP1Diam[0],
"p1diam");
3124 parallelIo.writeArray(&ncmpiP0Dens[0],
"p0dens");
3125 parallelIo.writeArray(&ncmpiP1Dens[0],
"p1dens");
3126 parallelIo.writeArray(&ncmpiRelVel[0],
"relVel");
3127 parallelIo.writeArray(&ncmpiMeanVel[0],
"meanVel");
3130 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
3131 parallelIo.setOffset(ncmpiCount, ncmpi3Start);
3132 parallelIo.writeArray(&ncmpiCollPos[0],
"collPos");
3135 while(!collQueue.empty()) {
3140 if(m_includeEllipsoids) {
3142 ncmpiCollQueueSize = (
MInt)collQueueEllipsoid.
size();
3144 MIntScratchSpace ncmpiEllipsoidCollCount(noDomains(), AT_,
"ncmpiEllipsoidCollCount");
3145 MPI_Allgather(&ncmpiCollQueueSize, 1, MPI_INT, &ncmpiEllipsoidCollCount[0], 1, MPI_INT, mpiComm(), AT_,
3146 "ncmpiCollQueueSize",
"ncmpiEllipsoidCollCount[0]");
3148 ncmpiCollCountMax = 0;
3149 for(
MInt i = 0; i < noDomains(); ++i) {
3150 ncmpiCollCountMax += ncmpiEllipsoidCollCount[i];
3154 if(ncmpiCollCountMax != 0) {
3157 stringstream ncmpistream;
3158 string ncmpiFileName;
3159 ncmpistream <<
"out/collEllipsoid." <<
globalTimeStep << ParallelIo::fileExt();
3160 ncmpistream >> ncmpiFileName;
3161 ncmpistream.clear();
3170 TERMM(1,
"untested I/O method, please see comment for how to proceed");
3172 ParallelIo parallelIo(ncmpiFileName, PIO_REPLACE, mpiComm());
3173 ncmpiFileName.clear();
3177 parallelIo.setAttribute(ncmpiTimeStep,
"timestep");
3181 parallelIo.defineArray(PIO_INT,
"overlapCount", noDomains());
3184 parallelIo.defineArray(PIO_FLOAT,
"collTimeStep", ncmpiCollCountMax);
3185 parallelIo.defineArray(PIO_INT,
"part0", ncmpiCollCountMax);
3186 parallelIo.defineArray(PIO_INT,
"part1", ncmpiCollCountMax);
3187 parallelIo.defineArray(PIO_FLOAT,
"p0semiMinorAxis", ncmpiCollCountMax);
3188 parallelIo.defineArray(PIO_FLOAT,
"p1semiMinorAxis", ncmpiCollCountMax);
3189 parallelIo.defineArray(PIO_FLOAT,
"p0aspectRatio", ncmpiCollCountMax);
3190 parallelIo.defineArray(PIO_FLOAT,
"p1aspectRatio", ncmpiCollCountMax);
3191 parallelIo.defineArray(PIO_FLOAT,
"p0dens", ncmpiCollCountMax);
3192 parallelIo.defineArray(PIO_FLOAT,
"p1dens", ncmpiCollCountMax);
3193 parallelIo.defineArray(PIO_FLOAT,
"collPos", 3 * ncmpiCollCountMax);
3197 ParallelIo::size_type ncmpiStart = domainId();
3198 ParallelIo::size_type ncmpiCount = 1;
3200 parallelIo.setOffset(ncmpiCount, ncmpiStart);
3201 parallelIo.writeArray(&ncmpiCollQueueSize,
"overlapCount");
3204 for(
MInt i = 0; i < domainId(); ++i) {
3205 ncmpiStart += ncmpiEllipsoidCollCount[i];
3207 ncmpiCount = ncmpiEllipsoidCollCount[domainId()];
3208 if(ncmpiStart >= ncmpiCollCountMax) {
3209 if(ncmpiCount == 0) {
3213 "Error in LPT::writeCollData "
3214 "(m_includeEllipsoids)!! ncmpiStart >= "
3215 "ncmpiCollCountMax but ncmpiCount != 0");
3220 MFloatScratchSpace ncmpiCollTimeStep(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiCollTimeStep");
3221 MIntScratchSpace ncmpiPart0(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiPart0");
3222 MIntScratchSpace ncmpiPart1(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiPart1");
3223 MFloatScratchSpace ncmpiP0SemiMinorAxis(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP0SemiMinorAxis");
3224 MFloatScratchSpace ncmpiP1SemiMinorAxis(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP1SemiMinorAxis");
3225 MFloatScratchSpace ncmpiP0AspectRatio(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP0AspectRatio");
3226 MFloatScratchSpace ncmpiP1AspectRatio(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP1AspectRatio");
3227 MFloatScratchSpace ncmpiP0Dens(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP0Dens");
3228 MFloatScratchSpace ncmpiP1Dens(ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiP1Dens");
3229 MFloatScratchSpace ncmpiCollPos(3 * ncmpiEllipsoidCollCount[domainId()], AT_,
"ncmpiCollPos");
3230 MInt ncmpiCountId = 0;
3234 while(!collQueueEllipsoid.empty()) {
3235 ncmpiCollTimeStep[ncmpiCountId] = collQueueEllipsoid.front().collTimeStep;
3236 ncmpiPart0[ncmpiCountId] = collQueueEllipsoid.front().part0;
3237 ncmpiPart1[ncmpiCountId] = collQueueEllipsoid.front().part1;
3238 ncmpiP0SemiMinorAxis[ncmpiCountId] = collQueueEllipsoid.front().semiMinorAxis0;
3239 ncmpiP1SemiMinorAxis[ncmpiCountId] = collQueueEllipsoid.front().semiMinorAxis1;
3240 ncmpiP0AspectRatio[ncmpiCountId] = collQueueEllipsoid.front().aspectRatio0;
3241 ncmpiP1AspectRatio[ncmpiCountId] = collQueueEllipsoid.front().aspectRatio1;
3242 ncmpiP0Dens[ncmpiCountId] = collQueueEllipsoid.front().dens0;
3243 ncmpiP1Dens[ncmpiCountId] = collQueueEllipsoid.front().dens1;
3244 ncmpiCollPos[(3 * ncmpiCountId)] = collQueueEllipsoid.front().collPosX;
3245 ncmpiCollPos[(3 * ncmpiCountId) + 1] = collQueueEllipsoid.front().collPosY;
3246 ncmpiCollPos[(3 * ncmpiCountId) + 2] = collQueueEllipsoid.front().collPosZ;
3248 collQueueEllipsoid.pop();
3253 parallelIo.setOffset(ncmpiCount, ncmpiStart);
3254 parallelIo.writeArray(&ncmpiCollTimeStep[0],
"collTimeStep");
3255 parallelIo.writeArray(&ncmpiPart0[0],
"part0");
3256 parallelIo.writeArray(&ncmpiPart1[0],
"part1");
3257 parallelIo.writeArray(&ncmpiP0SemiMinorAxis[0],
"p0semiMinorAxis");
3258 parallelIo.writeArray(&ncmpiP1SemiMinorAxis[0],
"p1semiMinorAxis");
3259 parallelIo.writeArray(&ncmpiP0AspectRatio[0],
"p0aspectRatio");
3260 parallelIo.writeArray(&ncmpiP1AspectRatio[0],
"p1aspectRatio");
3261 parallelIo.writeArray(&ncmpiP0Dens[0],
"p0dens");
3262 parallelIo.writeArray(&ncmpiP1Dens[0],
"p1dens");
3265 ParallelIo::size_type ncmpi3Start = 3 * ncmpiStart;
3267 parallelIo.setOffset(ncmpiCount, ncmpi3Start);
3268 parallelIo.writeArray(&ncmpiCollPos[0],
"collPos");
3271 while(!collQueueEllipsoid.empty()) {
3272 collQueueEllipsoid.pop();
void collisionCheckEECCD(lptEllipticleI, lptEllipticleI)
checks continuously for the overlaps of the two ellipsoids i2 and i3 assuming that they do not rotate...
MFloat checkBndryCross(MInt, lptParticleI, MFloat)
Checks crossing of boundary surface of the boundary cell.
void collisionCheckSphereEllipsoid(lptParticleI, lptEllipticleI)
Collision check for ellipsoids i2 and i3 calls the corresponding proactive or retroactive method.
void collisionCheckEEProActive(lptEllipticleI, lptEllipticleI)
Collision check for ellipsoids i2 and i3 checks and stores collision event this method works proactiv...
void geometryInteraction()
void detectPartColl(std::vector< LPTSpherical< nDim > > &partList, std::vector< LPTEllipsoidal< nDim > > &partListEllipsoid, const MFloat timeStep, const MFloat time)
Disables the following warnings with gcc: -Warray-bounds.
void writeCollData()
write collision data queue to Netcdf file (using parallel output)
void collisionCheckSECCD(lptParticleI, lptEllipticleI)
checks continuously for the overlaps of the sphere i2 and the ellipsoid i3 assuming that they do not ...
ParticleCollision(LPT< nDim > *lptSolver, MInt collisionModel, const MInt solverId, const MInt domainId, const MInt noDomains, const MPI_Comm comm)
Constructor of the ParticleCollision class.
void collisionCheckSEP(lptParticleI, lptEllipticleI)
Collision check for sphere i1 and ellipsoid i2, specialized version of ellips ellips checks and store...
MFloat collisionCheck(lptParticleI, lptParticleI, MFloat)
Checks whether particles i and j collide after currCollTime, and returns collision time.
void collisionCheckEERetroActive(lptEllipticleI, lptEllipticleI)
Collision check for ellipsoids i2 and i3 based on overlap criterion, and store collision event when f...
void createMatrix_CCD(const MFloat(&MA)[16], const MFloat(&u1)[3], const MFloat(&invMB)[16], const MFloat(&u2)[3], const MFloat &a_2, const MFloat &c_2, MFloat(&n)[16], MFloat(&m)[5])
calculates M_A^T*(M_B^(-1))^T*B*(M_B^(-1))*M_A, write it the part independent of t in n and the other...
MFloat testU_CCD(const MFloat &u, const MFloat &t4, const MFloat &t3, const MFloat &t2, const MFloat &t1, const MFloat &t0)
calculates the value of the forth order polynomial and returns it if positive other returns -1
void collisionCheckEllipsoidEllipsoid(lptEllipticleI, lptEllipticleI)
Collision check for ellipsoids i2 and i3 calls the corresponding proactive or retroactive method.
void collisionCheckSERetroActive(lptParticleI, lptEllipticleI)
Collision check for sphere i1 and ellipsoid i2 based on overlap criterion, and store collision event ...
void writeCollEvent(MFloat collisionTime, MInt particle0, MInt particle1, MFloat diam0, MFloat diam1, MFloat dens0, MFloat dens1, MFloat relVel, MFloat meanVel, MFloat *x)
Add collision data to queue which is to be written.
MFloat checkStaticOverlap_CCD(const MFloat(&b_Matrix)[16], const MFloat(&A)[16], const MFloat(&m)[5], const MFloat &detMinusB, MFloat &t1)
calculates if there is a local maximum of det(A*(u-1)-u*B) in u for a fixed value of t and if the val...
void init()
Initialisation of collision model.
MFloat checkDynamicOverlap_CCD(const MFloat(&n)[16], const MFloat(&m)[5], MFloat t1, MFloat t2)
Performes BezierShot from "side", returns the first zero-crossing results in finding the roots of the...
MBool checkCSI_CCD(const MFloat(&A)[16], const MFloat(&b_Matrix)[16], const MFloat(&m)[5], const MFloat &detMinusB, MFloat &t1, MFloat &t2, MFloat &positive1, MFloat &positive2, MInt &iteration)
checks recursively if the ellipsoids are separated by subdividing the time intervals in smaller CSIs....
This class is a ScratchSpace.
std::vector< LPTSpherical< nDim > >::iterator particle1
std::vector< LPTSpherical< nDim > >::iterator particle0
void mTerm(const MInt errorCode, const MString &location, const MString &message)
constexpr Real POW3(const Real x)
constexpr Real POW2(const Real x)
MBool approx(const T &, const U &, const T)
constexpr MLong IPOW2(MInt x)
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
typename std::vector< LPTSpherical< nDim > >::iterator partListIterator
void slerp(const MFloat *before, const MFloat *now, const MFloat time, MFloat *result, const MInt length)
typename std::vector< LPTSpherical< nDim > >::const_iterator partListIteratorConst
typename std::vector< LPTEllipsoidal< nDim > >::const_iterator ellipsListIteratorConst
typename std::vector< LPTEllipsoidal< nDim > >::iterator ellipsListIterator
MFloat distance(const MFloat *a, const MFloat *b)
void normalize(std::array< T, N > &u)
template void solveQR< 3 >(std::array< std::array< MFloat, 3 >, 3 > &, std::array< MFloat, 3 > &)
PARALLELIO_DEFAULT_BACKEND ParallelIo
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)