ChuteWithPeriodicInflow.h
Go to the documentation of this file.
1 //Copyright (c) 2013-2023, The MercuryDPM Developers Team. All rights reserved.
2 //For the list of developers, see <http://www.MercuryDPM.org/Team>.
3 //
4 //Redistribution and use in source and binary forms, with or without
5 //modification, are permitted provided that the following conditions are met:
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above copyright
9 // notice, this list of conditions and the following disclaimer in the
10 // documentation and/or other materials provided with the distribution.
11 // * Neither the name MercuryDPM nor the
12 // names of its contributors may be used to endorse or promote products
13 // derived from this software without specific prior written permission.
14 //
15 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 //DISCLAIMED. IN NO EVENT SHALL THE MERCURYDPM DEVELOPERS TEAM BE LIABLE FOR ANY
19 //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 //updated force calculation to the changes in MD.cc (further, a few variables needed to be privatized)
27 #include <sstream>
28 #include <fstream>
29 #include <iostream>
30 #include <iomanip>
31 #include <cmath>
32 
33 #include "Chute.h"
35 #include "sys/stat.h"
38 {
39 public:
40  ChuteWithPeriodicInflow(std::string restart_file)
41  {
42  loadPeriodicBox(restart_file);
43  }
44 
45  ChuteWithPeriodicInflow(std::string restart_file, int numRepetitions)
46  {
47  loadPeriodicBox(restart_file);
48  AddContinuingBottom(numRepetitions);
49  }
50 
51  ChuteWithPeriodicInflow(std::string restart_file, int numRepetitions, int numRepetitionsInWidth)
52  {
53  loadPeriodicBox(restart_file);
54  AddContinuingBottom(numRepetitions);
55  ExtendInWidth(numRepetitionsInWidth);
56  }
57 
58  double getInfo(const BaseParticle& P) const override
59  {
60  return P.getIndSpecies();
61  }
62 
64  void loadPeriodicBox(std::string const restart_file)
65  {
66  FillChute = false;
67 
68  std::cout << "constructor" << std::endl;
69 
70  //load particles and chute setup into periodic chute
71  setName(restart_file.c_str());
73 
76 
77  //we don't want to treat the data as restarted, i.e. we start the program at time=0 and create new output files
78  setRestarted(false);
79 
80  //keep file name but create files in the local directory, i.e. remove folder
81  size_t found = restart_file.find_last_of("/\\");
82  setName(restart_file.substr(found + 1).c_str());
83 
84  // adds new species for the flow particles (0 for the periodic inflow particles)
85  for (int i = 0; i < get_PeriodicBoxNSpecies(); i++)
86  addSpecies(Species[i]);
87 
88  setName("ChuteWithPeriodicInflow");
89  }
90 
91  void AddContinuingBottom(int numRepetitions)
92  {
93  // creates bottom outside periodic chute of species 1
94  double lengthPeriodicChute = getXMax();
96  particleHandler.setStorageCapacity(N * (2. + numRepetitions));
97  //allows for a gap between the infow and flow regimes
98  double Gap = 0.;
99 
100  for (int j = 1; j < numRepetitions; j++)
101  {
102  for (int i = 0; i < N; i++)
103  {
105  {
108  particleHandler.getLastObject()->move(Vec3D(Gap + lengthPeriodicChute * j, 0., 0.));
109  }
110  }
111  }
112 
113  setXMax(numRepetitions * lengthPeriodicChute);
114  //setHGridNumberOfBucketsToPower(particleHandler.getStorageCapacity());
115  }
116 
117  void ExtendInWidth(int numRepetitionsInWidth)
118  {
120  // creates bottom outside periodic chute of species 1
121  double widthPeriodicChute = getYMax();
123  particleHandler.setStorageCapacity(N * numRepetitionsInWidth);
124  for (int j = 1; j < numRepetitionsInWidth; j++)
125  {
126  for (int i = 0; i < N; i++)
127  {
128  //if (particleHandler.getObject(i)->isFixed()) {
130  //Particles.back()->get_IndSpecies()=1;
131  particleHandler.getLastObject()->move(Vec3D(0.0, widthPeriodicChute * j, 0.0));
132  //}
133  }
134  }
135  setYMax(numRepetitionsInWidth * widthPeriodicChute);
136  perw->set(Vec3D(0, 1, 0), getYMin(), getYMax());
137  //setHGridNumberOfBucketsToPower(particleHandler.getNumberOfObjects());
138  }
139 
141  void actionsBeforeTimeStep() override
142  {
143  cleanChute();
144  }
145 
147  void cleanChute()
148  {
149  //clean outflow every 100 time steps
150  static int count = 0, maxcount = 100;
151  if (count > maxcount)
152  {
153  count = 0;
154  // delete all outflowing particles
155  for (unsigned int i = 0; i < particleHandler.getNumberOfObjects();)
156  {
157  //~ if (particleHandler.getObject(i)->getPosition().Z<getZMin()-10*getInflowParticleRadius()){
159  {
160  //~ cout << "Remove particle" << endl;
162  }
163  else
164  i++;
165  }
166  }
167  else
168  count++;
169  }
170 
172  void setupInitialConditions() override
173  {
174  }
175 
177  {
178  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it != particleHandler.end(); ++it)
179  {
180  (*it)->integrateBeforeForceComputation(getTimeStep());
181 
182  // This shifts particles that moved through periodic walls
184  PeriodicBoundary* perw1 = static_cast<PeriodicBoundary*>(boundaryHandler.getObject(1));
185  if ((*it)->getIndSpecies() == 0 && perw->getDistance(**it) < 0)
186  {
187  //if (iP->getIndSpecies()==0 && static_cast<PeriodicWall*>(boundaryHandler.getObject(0))->getDistance(*iP)<0) {
188  if (!perw->isClosestToLeftBoundary())
189  {
192  particleHandler.addObject((*it)->copy());
195  perw->shiftPosition((*it));
197  {
198  hGridRemoveParticle((*it));
199  hGridUpdateParticle((*it));
200  }
201  }
202  else
203  {
204  static int count = -1;
205  count++;
206  if (!(count % dataFile.getSaveCount()))
207 
208  std::cout << "Warning: Particle " << (*it)->getIndex() << " is left of xmin: x="
209  << (*it)->getPosition().X << ", v_x=" << (*it)->getVelocity().X << std::endl;
210  }
211  }
212  if (getIsPeriodic() > 1 && perw1->getDistance(**it) < 0)
213  {
214  perw1->shiftPosition(*it);
216  {
217  hGridRemoveParticle(*it);
218  hGridUpdateParticle(*it);
219  }
220  }
221  }
222 
223  }
224 
226  void printTime() const override
227  {
228  int counter = 0;
229 
230  double speed1 = 0;
231  double speed0 = 0;
232  double n1 = 0;
233  double n0 = 0;
234  for (int i = 0; i < particleHandler.getNumberOfObjects(); i++)
235  {
237  counter++;
239  {
241  {
242  speed0 += particleHandler.getObject(i)->getVelocity().X;
243  n0++;
244  }
245  else
246  {
247  speed1 += particleHandler.getObject(i)->getVelocity().X;
248  n1++;
249  }
250  }
251  }
252  speed0 /= n0;
253  speed1 /= n1;
254 
255  std::cout << "t=" << std::setprecision(5) << std::left << std::setw(6) << getTime()
256  << ", n=" << n1 << "(inflow:" << n0 << ")"
257  << ", speed= " << speed1 << "(" << speed0 << ")"
258  << std::endl;
259  //~ cout
260  //~ << " A " << PeriodicBoxLength
261  //~ << " A " << PeriodicBoxNSpecies
262  //~ << " A " << FillChute << endl;
263  }
264  //%%%%%%%%%%%%%%%%% Copied from MD.cc and then edited
266  {
267 <<<<<<< .mine
268  // For particles of the same species, set species vector to Species(PI);
269  // for particles of different species, set species vector to MixedSpecies(PI,PJ)
270  BaseSpecies* pSpecies = (PI->getIndSpecies() == PJ->getIndSpecies()) ? &Species[PI->getIndSpecies()] : speciesHandler.getMixedObject(PI->getIndSpecies(), PJ->getIndSpecies());
271 =======
272  //this is because the rough bottom allows overlapping fixed particles
273  if (P1->isFixed() && P2->isFixed())
274  return;
275 >>>>>>> .r824
276 
281 
282  //Dificult cases for tangential springs in comination with periodic walls are:
283  //
284  // A new contact over a periodic wall:
285  // Starting situation: There are no tangential springs stored at all
286  // Creating periodic particles: There are no tangential springs so nothing happens
287  // Contact detection: There are two contacts detected, one (CA) for P1 with P2per and one (CB) for P2 with P1per
288  // Switch to the 4 cases:
289  // CA: PI=P1, PJ=P2per PJreal=P2
290  // CB: PI=P2, PJ=P1per PJreal=P1
291  // Reconnecting springs:
292  // CA: PI=P1 and PJ=P2per do not have a spring, so a new spring is created in either PI or PJ (could be in periodic particle)
293  // CB: PI=P2 and PJ=P1Per do not have a spring, so a new spring is created in either PI or PJ (could be in periodic particle)
294  // Removing periodic particles: One of the springs will be stored in a periodic particle and thus removed, the other spring is kept and used (this is the real particle with the kighest index)
295 
296  // Reconnect to a contact over a periodic wall:
297  // Starting situation: There is a tangential spring stored in the particle with the highest index, lets assume this is P1
298  // Creating periodic particles: P1 has a tangential spring, so P1per has a reversed copy of this spring
299  // Contact detection: There are two contacts detected, one (CA) for P1 with P2per and one (CB) for P2 with P1per
300  // Switch to the 4 cases:
301  // CA: PI=P1, PJ=P2per PJreal=P2
302  // CB: PI=P2, PJ=P1per PJreal=P1
303  // Reconnecting springs:
304  // CA: PI=P1 and PJ=P2per have a spring in P1, so we reconnect to this spring in the normal way and integrate it.
305  // CB: PI=P2 and PJ=P1Per have a spring in P1per, however this spring has to be a reversed spring since it is in PJ.
306  // Removing periodic particles: The spring in P1per is removed
307 
308  //Cases (start from P1 and P2 and go to PI and PJ
309  //1 Normal-Normal ->PI=max(P1,P2), PJ=min(P1,P2)
310  //2 Periodic-Normal ->(PI=P2 PJ=real(P1))
311  //3 Normal-Periodic ->(PI=P1 PJ=real(P2))
312  //4 Periodic-Periodic ->do nothing
313 
314  //Just some statements to handle the 4 cases
315  BaseParticle *PI, *PJ, *PJreal;
316  bool isPeriodic;
317  BaseParticle *P1Per = P1->getPeriodicFromParticle();
318  BaseParticle *P2Per = P2->getPeriodicFromParticle();
319  if (P1Per == NULL)
320  {
321  if (P2Per == NULL) //N-N
322  if (P1->getIndex() < P2->getIndex())
323  {
324  PI = P2;
325  PJ = P1;
326  PJreal = P1;
327  isPeriodic = false;
328  }
329  else
330  {
331  PI = P1;
332  PJ = P2;
333  PJreal = P2;
334  isPeriodic = false;
335  }
336  else //N-P
337  {
338  PI = P1;
339  PJ = P2;
340  PJreal = P2Per;
341  isPeriodic = true;
342  }
343  }
344  else
345  {
346  if (P2Per == NULL) //P-N
347  {
348  PI = P2;
349  PJ = P1;
350  PJreal = P1Per;
351  isPeriodic = true;
352  }
353  else
354  return;
355  }
356 
357 #ifdef DEBUG_OUTPUT
358  std::cerr << "In computing internal forces between particle "<<PI->getPosition()<<" and "<<PJ->getPosition()<<std::endl;
359 #endif
360 
361  //Get the square of the distance between particle i and particle j
362  Mdouble dist_squared = Vec3D::getDistanceSquared(PI->getPosition(), PJ->getPosition());
363  Mdouble interactionRadii_sum = PI->getInteractionRadius() + PJ->getInteractionRadius();
364 
365 #ifdef DEBUG_OUTPUT_FULL
366  std::cerr << "Square of distance between " << dist_squared << " square sum of radii " << radii_sum*radii_sum <<std::endl;
367 #endif
368 
369  // True if the particles are in contact
370  if (dist_squared < (interactionRadii_sum * interactionRadii_sum))
371  {
372  // For particles of the same species, set species vector to Species(PI);
373  // for particles of different species, set species vector to MixedSpecies(PI,PJ)
374  CSpecies* pSpecies = (PI->getIndSpecies() == PJ->getIndSpecies()) ? &Species[PI->getIndSpecies()] : getMixedSpecies(PI->getIndSpecies(), PJ->getIndSpecies());
375 
376  // Calculate distance between the particles
377  Mdouble dist = sqrt(dist_squared);
378 
379  // Compute normal vector
380 
381  Vec3D normal = (PI->getPosition() - PJ->getPosition()) / dist;
382 
383  // Compute the overlap between the particles
384  Mdouble radii_sum = PI->getRadius() + PJ->getRadius();
385  Mdouble deltan = std::max(0.0, radii_sum - dist);
386 
387  Vec3D force = Vec3D(0, 0, 0);
388  ;
389  Vec3D forcet;
390  forcet.setZero();
391  Vec3D forcerolling;
392  forcerolling.setZero();
393  Vec3D forcetorsion;
394  forcetorsion.setZero();
395  Mdouble fdotn = 0;
396  CTangentialSpring* TangentialSpring = NULL;
397 
398  //evaluate shortrange non-contact forces
399  if (pSpecies->getAdhesionForceType() != AdhesionForceType::NONE)
400  fdotn += computeShortRangeForceWithParticle(PI, PJ, PJreal, pSpecies, dist);
401 
402  if (deltan > 0) //if contact forces
403  {
404 
405  // Compute the relative velocity vector v_ij
406  Vec3D vrel;
407  if (!pSpecies->getSlidingFrictionCoefficient())
408  {
409  vrel = (PI->getVelocity() - PJ->getVelocity());
410  }
411  else
412  {
413  vrel = (PI->getVelocity() - PJ->getVelocity()) + Vec3D::cross(normal, PI->getAngularVelocity() * (PI->getRadius() - .5 * deltan) + PJ->getAngularVelocity() * (PJ->getRadius() - .5 * deltan));
414  }
415 
416  // Compute the projection of vrel onto the normal (can be negative)
417  Mdouble vdotn = -Vec3D::dot(vrel, normal);
418 
419  //update restitution coeff
420  if (pSpecies->getIsRestitutionCoefficientConstant())
421  pSpecies->updateDissipation(PI->getMass(), PJ->getMass());
422  Mdouble a = 0, R = 0;
423 
424  // Compute normal force on particle i due to contact
425  if (pSpecies->getForceType() == ForceType::HERTZ_MINDLIN || pSpecies->getForceType() == ForceType::HERTZ_MINDLIN_DERESIEWICZ)
426  {
427  //R is twice the effective radius
428  R = 2.0 * PI->getRadius() * PJ->getRadius() / (PI->getRadius() + PJ->getRadius());
429  a = sqrt(R * deltan);
430  //pSpecies->getStiffness() stores the elastic modulus
431  Mdouble kn = 4. / 3. * pSpecies->getStiffness() * a;
432  fdotn += kn * deltan + pSpecies->getDissipation() * vdotn;
433  }
434  else
435  {
436  fdotn += pSpecies->getStiffness() * deltan + pSpecies->getDissipation() * vdotn;
437  }
438  force += normal * fdotn;
439 
440  //If tangential forces are present
441  if (pSpecies->getSlidingFrictionCoefficient() || pSpecies->getRollingFrictionCoefficient() || pSpecies->getTorsionFrictionCoefficient())
442  {
443  //call tangential spring
444  if (pSpecies->getSlidingStiffness() || pSpecies->getRollingStiffness() || pSpecies->getTorsionStiffness())
445  TangentialSpring = getTangentialSpring(PI, PJ, PJreal);
446 
447  //Compute norm of normal force
448  Mdouble norm_fn = fabs(fdotn);
449 
450  //calculate sliding friction
451  if (pSpecies->getSlidingFrictionCoefficient())
452  {
453  //Compute the tangential component of vrel
454  Vec3D vrelt = vrel + normal * vdotn;
455  //Compute norm of vrelt
456  Mdouble vdott = vrelt.getLength();
457 
458  if (pSpecies->getSlidingStiffness())
459  {
460  Vec3D* delta = &(TangentialSpring->delta);
461 
462  //Integrate the spring
464  //(*delta) += vrelt * dt - Vec3D::Dot(*delta,normal)*normal;
465  Vec3D ddelta = (vrelt - Vec3D::dot(*delta, PI->getVelocity() - PJ->getVelocity()) * normal / dist) * getTimeStep();
466  (*delta) += ddelta;
467 
468  //Calculate test force including viscous force
469  if (pSpecies->getForceType() == ForceType::HERTZ_MINDLIN)
470  {
471  //pSpecies->getSlidingStiffness() stores the elastic shear modulus
472  Mdouble kt = 8. * pSpecies->getSlidingStiffness() * a;
473  TangentialSpring->SlidingForce += -kt * ddelta;
474  forcet = TangentialSpring->SlidingForce - pSpecies->getSlidingDissipation() * vrelt;
475  }
476  else if (pSpecies->getForceType() == ForceType::HERTZ_MINDLIN_DERESIEWICZ)
477  {
478  //pSpecies->getSlidingStiffness() stores the elastic shear modulus
479  forcet = TangentialSpring->SlidingForce - pSpecies->getSlidingDissipation() * vrelt;
480  Mdouble kt = 8. * pSpecies->getSlidingStiffness() * a * std::pow(1 - Vec3D::getLength(forcet) / pSpecies->getSlidingFrictionCoefficient() / fdotn, 0.33);
481  TangentialSpring->SlidingForce += -kt * ddelta;
482  forcet = TangentialSpring->SlidingForce - pSpecies->getSlidingDissipation() * vrelt;
483  }
484  else
485  {
486  forcet = (-pSpecies->getSlidingDissipation()) * vrelt - pSpecies->getSlidingStiffness() * (*delta);
487  }
488  Mdouble forcet2 = forcet.getLengthSquared();
489 
490  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity getSlidingDissipation() (sticking),
491  //but the force is limited by Coulomb friction (sliding):
492  //f_t = -getSlidingDissipation()*vrelt, if getSlidingDissipation()*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
493  double muact = (TangentialSpring->sliding) ? (pSpecies->getSlidingFrictionCoefficient()) : (pSpecies->getSlidingFrictionCoefficientStatic()); // select mu from previous sliding mode
494  if (forcet2 <= mathsFunc::square(muact * norm_fn))
495  {
496  //sticking++;
497  TangentialSpring->sliding = false;
498  }
499  else
500  {
501  //sliding++;
502  TangentialSpring->sliding = true;
504  Mdouble norm_forcet = sqrt(forcet2);
505  forcet *= pSpecies->getSlidingFrictionCoefficient() * norm_fn / norm_forcet;
506  TangentialSpring->SlidingForce = forcet + pSpecies->getSlidingDissipation() * vrelt;
507  (*delta) = TangentialSpring->SlidingForce / (-pSpecies->getSlidingStiffness());
508  }
509 
510  //Add tangential force to total force
511  force += forcet;
512 
513  }
514  else
515  { //if no tangential spring
516  //tangential forces are modelled by a damper of viscosity getSlidingDissipation() (sticking),
517  //but the force is limited by Coulomb friction (sliding):
518  //f_t = -getSlidingDissipation()*vrelt, if getSlidingDissipation()*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
519  if (vdott * pSpecies->getSlidingDissipation() <= pSpecies->getSlidingFrictionCoefficientStatic() * norm_fn)
520  { //sticking++;
521  forcet = -pSpecies->getSlidingDissipation() * vrelt;
522  }
523  else
524  { //sliding++;
525  //set force to Coulomb limit
526  forcet = -(pSpecies->getSlidingFrictionCoefficient() * norm_fn / vdott) * vrelt;
527  }
528  //Add tangential force to total force
529  force += forcet;
530  }
531  }
532 
533  //calculate rolling friction
534  if (pSpecies->getRollingFrictionCoefficient())
535  {
536  //From Luding2008, objective rolling velocity (eq 15) w/o 2.0!
537  Mdouble reducedRadiusI = PI->getRadius() - .5 * deltan;
538  Mdouble reducedRadiusJ = PJ->getRadius() - .5 * deltan;
539  Mdouble reducedRadiusIJ = 2.0 * reducedRadiusI * reducedRadiusJ / (reducedRadiusI + reducedRadiusJ);
540  Vec3D vrolling = -reducedRadiusIJ * Vec3D::cross(normal, PI->getAngularVelocity() - PJ->getAngularVelocity());
541  if (pSpecies->getRollingStiffness())
542  {
543  Vec3D* RollingSpring = &(TangentialSpring->RollingSpring);
544 
545  //Integrate the spring
546  (*RollingSpring) += vrolling * getTimeStep(); // - Vec3D::Dot(*RollingSpring,normal)*normal;
547 
548  //Calculate test force including viscous force
549  forcerolling = (-pSpecies->getRollingDissipation()) * vrolling - pSpecies->getRollingStiffness() * (*RollingSpring);
550  Mdouble forcerolling2 = forcerolling.getLengthSquared();
551 
552  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity getSlidingDissipation() (sticking),
553  //but the force is limited by Coulomb friction (sliding):
554  //f_t = -getSlidingDissipation()*vrelt, if getSlidingDissipation()*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
555  double muact = (TangentialSpring->slidingRolling) ? (pSpecies->getRollingFrictionCoefficient()) : (pSpecies->getRollingFrictionCoefficientStatic()); // select mu from previous sliding mode
556  if (forcerolling2 <= mathsFunc::square(muact * norm_fn))
557  {
558  //sticking++;
559  TangentialSpring->slidingRolling = false;
560  }
561  else
562  {
563  //sliding++;
564  TangentialSpring->slidingRolling = true;
565  forcerolling *= pSpecies->getRollingFrictionCoefficient() * norm_fn / sqrt(forcerolling2);
566  (*RollingSpring) = (forcerolling + pSpecies->getRollingDissipation() * vrolling) / (-pSpecies->getRollingStiffness());
567  }
568 
569  //Add tangential force to torque
570  Vec3D Torque = reducedRadiusIJ * Vec3D::cross(normal, forcerolling);
571  PI->addTorque(Torque);
572  PJreal->addTorque(-Torque);
573  }
574  }
575 
576  //calculate torsive friction
577  if (pSpecies->getTorsionFrictionCoefficient())
578  {
579  //From Luding2008, spin velocity (eq 16) w/o 2.0!
580  Mdouble RadiusIJ = 2.0 * PI->getRadius() * PJ->getRadius() / (PI->getRadius() + PJ->getRadius());
581  Vec3D vtorsion = RadiusIJ * Vec3D::dot(normal, PI->getAngularVelocity() - PJ->getAngularVelocity()) * normal;
582  if (pSpecies->getTorsionStiffness())
583  {
584  //~ std::cout << "Error; not yet implemented" << std::endl;
585  //~ exit(-1);
586  Vec3D* TorsionSpring = &(TangentialSpring->TorsionSpring);
587 
588  //Integrate the spring
589  (*TorsionSpring) = Vec3D::dot((*TorsionSpring) + vtorsion * getTimeStep(), normal) * normal;
590 
591  //Calculate test force including viscous force
592  forcetorsion = (-pSpecies->getTorsionDissipation()) * vtorsion - pSpecies->getTorsionStiffness() * (*TorsionSpring);
593  Mdouble forcetorsion2 = forcetorsion.getLengthSquared();
594 
595  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity getSlidingDissipation() (sticking),
596  //but the force is limited by Coulomb friction (sliding):
597  //f_t = -getSlidingDissipation()*vrelt, if getSlidingDissipation()*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
598  double muact = (TangentialSpring->slidingTorsion) ? (pSpecies->getTorsionFrictionCoefficient()) : (pSpecies->getTorsionFrictionCoefficientStatic()); // select mu from previous sliding mode
599  if (forcetorsion2 <= mathsFunc::square(muact * norm_fn))
600  {
601  //sticking++;
602  TangentialSpring->slidingTorsion = false;
603  }
604  else
605  {
606  //sliding++;
607  TangentialSpring->slidingTorsion = true;
608  //~ std::cout << "sliding " << std::endl;
609  forcetorsion *= pSpecies->getTorsionFrictionCoefficient() * norm_fn / sqrt(forcetorsion2);
610  (*TorsionSpring) = (forcetorsion + pSpecies->getTorsionDissipation() * vtorsion) / (-pSpecies->getTorsionStiffness());
611  }
612 
613  //Add tangential force to torque
614  Vec3D torque = RadiusIJ * forcetorsion;
615  PI->addTorque(torque);
616  PJreal->addTorque(-torque);
617 
618  }
619  }
620  } //end if tangential forces
621 
623  //Make force Hertzian (note: deltan is normalized by the normal distanct of two particles in contact, as in Silbert)
624  if (pSpecies->getForceType() == ForceType::HERTZ)
625  force *= sqrt(deltan / (PI->getRadius() + PJ->getRadius()));
626 
627  }
628  else
629  { //end if contact forces
630  force += fdotn * normal;
631  }
632 
633  //Add forces to total force
634  //PI->addForce(force);
635  //if (!isPeriodic)
636  // PJreal->addForce(-force);
637 
638  // Add torque due to tangential forces: t = Vec3D::Cross(l,f), l=dist*Wall.normal
639  //if (pSpecies->getSlidingFrictionCoefficient())
640  //{
641  // Vec3D Vec3D::Cross = Vec3D::Cross(normal, force);
642  // PI->addTorque(-Vec3D::Cross * (PI->getRadius() - .5 * deltan));
643  // if (!isPeriodic)
644  // PJreal->addTorque(-Vec3D::Cross * (PJ->getRadius() - .5 * deltan));
645  //}
646  //BEGIN: CHANGE
647  if (InPeriodicBox(PI) != InPeriodicBox(PJreal))
648  {
649  if (InPeriodicBox(PI))
650  {
652  {
653  //~ if (PJreal->isFixed()) cout << "PJreal" << endl;
654  PJreal->addForce(-force);
655  }
656  }
657  else
658  {
660  {
661  //~ if (Particles[PI].isFixed()) cout << "PI" << endl;
662  PI->addForce(force);
663  }
664  }
665  }
666  else
667  {
668  PI->addForce(force);
669  PJreal->addForce(-force);
670  }
671  //END: CHANGE
672 
673  // Add torque due to tangential forces: t = Vec3D::Cross(l,f), l=dist*Wall.normal
674  //if (pSpecies->getSlidingFrictionCoefficient()) {
675  // Vec3D Vec3D::Cross = Vec3D::Cross(normal, force);
676  // PI ->add_Torque(-Vec3D::Cross * (PI->getRadius() - .5 * deltan));
677  // PJreal->add_Torque(-Vec3D::Cross * (PJ->getRadius() - .5 * deltan));
678  //}
679  //BEGIN: CHANGE
680  if (pSpecies->getSlidingFrictionCoefficient())
681  {
682  Vec3D cross = Vec3D::cross(normal, force);
683  if (InPeriodicBox(PI) != InPeriodicBox(PJreal))
684  {
685  if (InPeriodicBox(PI))
686  {
688  {
689  PJreal->addTorque(-cross * (PJreal->getRadius() - .5 * deltan));
690  }
691  }
692  else
693  {
695  {
696  PI->addTorque(-cross * (PI->getRadius() - .5 * deltan));
697  }
698  }
699  }
700  else
701  {
702  PI->addTorque(-cross * (PI->getRadius() - .5 * deltan));
703  PJreal->addTorque(-cross * (PJreal->getRadius() - .5 * deltan));
704  }
705  }
706  //END:CHANGE
707 
708  // output for ene and stat files:
709  if (eneFile.getSaveCurrentTimeStep())
710  {
711  if (!isPeriodic)
712  addElasticEnergy(0.5 * (pSpecies->getStiffness() * mathsFunc::square(deltan) + (TangentialSpring ? (pSpecies->getSlidingStiffness() * TangentialSpring->delta.getLengthSquared() + pSpecies->getRollingStiffness() * TangentialSpring->RollingSpring.getLengthSquared() + pSpecies->getTorsionStiffness() * TangentialSpring->TorsionSpring.getLengthSquared()) : 0.0)));
713  else
714  addElasticEnergy(0.25 * (pSpecies->getStiffness() * mathsFunc::square(deltan) + (TangentialSpring ? (pSpecies->getSlidingStiffness() * TangentialSpring->delta.getLengthSquared() + pSpecies->getRollingStiffness() * TangentialSpring->RollingSpring.getLengthSquared() + pSpecies->getTorsionStiffness() * TangentialSpring->TorsionSpring.getLengthSquared()) : 0.0)));
715  }
716  if (fStatFile.getSaveCurrentTimeStep() || statFile.getSaveCurrentTimeStep() || getDoCGAlways())
717  {
718 
719  Mdouble fdott = forcet.getLength();
720  Mdouble deltat_norm = TangentialSpring ? (-TangentialSpring->delta.getLength()) : 0.0;
721 
724  Vec3D centre = 0.5 * (PI->getPosition() + PJ->getPosition());
725 
729 
730  if (!PI->isFixed())
731  {
732  if (statFile.getSaveCurrentTimeStep() || getDoCGAlways())
733  gatherContactStatistics(PJreal->getIndex(), PI->getIndex(), centre, deltan, deltat_norm, fdotn, fdott, -normal, -(fdott ? forcet / fdott : forcet));
734  if (fStatFile.getSaveCurrentTimeStep())
735  fStatFile.getFstream() << getTime() << " " << PJreal->getIndex() << " " << PI->getIndex() << " " << centre << " " << radii_sum - dist << " " << deltat_norm << " " << fdotn << " " << fdott << " " << -normal << " " << -(fdott ? forcet / fdott : forcet) << std::endl;
736  }
737  if (!PJreal->isFixed() && !isPeriodic)
738  {
739  if (statFile.getSaveCurrentTimeStep() || getDoCGAlways())
740  gatherContactStatistics(PI->getIndex(), PJreal->getIndex(), centre, deltan, deltat_norm, fdotn, fdott, normal, (fdott ? forcet / fdott : forcet));
741  if (fStatFile.getSaveCurrentTimeStep())
742  fStatFile.getFstream() << getTime() << " " << PI->getIndex() << " " << PJreal->getIndex() << " " << centre << " " << radii_sum - dist << " " << deltat_norm << " " << fdotn << " " << fdott << " " << normal << " " << (fdott ? forcet / fdott : forcet) << std::endl;
743  }
744  }
745  } // end if particle i and j are overlapping
746  }
747 
749  {
750  int C = 0; //Number of particles created
751  for (int k = nWallPeriodic; k < getIsPeriodic(); k++)
752  { //Loop over all still posible walls
755  if ((k ? true : InPeriodicBox(i)) && (perw->getDistance(*i) < i->getRadius() + getMaxInflowParticleRadius()))
756  {
757  SphericalParticle F0 = *i;
758  perw->shiftPosition(i);
759 
760  //If Particle is Mdouble shifted, get correct original particle
761  BaseParticle* From = i;
762  while (From->getPeriodicFromParticle() != NULL)
763  From = From->getPeriodicFromParticle();
764  F0.setPeriodicFromParticle(From);
765 
767  C++;
768 
769  //Check for Mdouble shifted particles
771  }
772  }
773  return (C);
774  }
775 
776  void writeXBallsScript() const
777  {
778 
779  std::stringstream file_name;
780  std::ofstream script_file;
781  file_name << getName() << ".disp";
782  script_file.open((file_name.str()).c_str());
783 
785  script_file << "#!/bin/bash" << std::endl;
786  script_file << "x=$(echo $0 | cut -c2-)" << std::endl;
787  script_file << "file=$PWD$x" << std::endl;
788  script_file << "dirname=`dirname \"$file\"`" << std::endl;
789  script_file << "cd $dirname" << std::endl;
790 
791  double scale;
792  int format;
793 
794  int width = 1570, height = 860;
795  double ratio = getSystemDimensions() < 3 ? (getXMax() - getXMin()) / (getYMax() - getYMin()) : (getXMax() - getXMin()) / (getZMax() - getZMin());
796  if (ratio > width / height)
797  height = width / ratio;
798  else
799  width = height * ratio;
800  //~ cout << ratio << "r" << endl;
801  if (getSystemDimensions() < 3)
802  { // dim = 1 or 2
803  format = 8;
804  if (getXBallsScale() < 0)
805  {
806  scale = 1.0 / std::max(getYMax() - getYMin(), getXMax() - getXMin());
807  }
808  else
809  {
810  scale = getXBallsScale();
811  }
812  }
813  else
814  { //dim==3
815  format = 14;
816  if (getXBallsScale() < 0)
817  {
818  scale = width / 480 / (getXMax() - getXMin());
819  }
820 
821  else
822  {
823  scale = getXBallsScale();
824  }
825 
826  }
827 
828  script_file << "../xballs -format " << format
829  << " -f " << dataFile.getFullName()
830  << " -s " << scale
831  << " -w " << width + 140
832  << " -h " << height + 140
833  << " -cmode " << getXBallsColourMode()
834  << " -cmax -scala 4 -sort -oh 50 "
836  << " $*";
837  if (getXBallsVectorScale() > -1)
838  {
839  script_file << " -vscale " << getXBallsVectorScale();
840  }
841  script_file.close();
842 
843  //This line changes the file permision and gives the owner (i.e. you) read, write and execute permission to the file
844 #ifdef UNIX
845  chmod((file_name.str().c_str()),S_IRWXU);
846 #endif
847  }
848 
849  void outputXBallsDataParticlee(const unsigned int i, const unsigned int format, std::ostream& os) const
850  {
851  os
852  << particleHandler.getObject(i)->getPosition().X << " "
853  << particleHandler.getObject(i)->getPosition().Y << " "
854  << particleHandler.getObject(i)->getPosition().Z << " "
855  << particleHandler.getObject(i)->getVelocity().X << " "
856  << particleHandler.getObject(i)->getVelocity().Y << " "
857  << particleHandler.getObject(i)->getVelocity().Z << " "
858  //~ << (particleHandler.getObject(i)->isFixed()?0.0:particleHandler.getObject(i)->Force.X) << " "
859  //~ << (particleHandler.getObject(i)->isFixed()?0.0:particleHandler.getObject(i)->Force.Y) << " "
860  //~ << (particleHandler.getObject(i)->isFixed()?0.0:particleHandler.getObject(i)->Force.Z) << " "
861  << particleHandler.getObject(i)->getRadius() << " "
863  << particleHandler.getObject(i)->getOrientation().Y << " "
864  << particleHandler.getObject(i)->getOrientation().Z << " "
868  << particleHandler.getObject(i)->getIndSpecies() << std::endl;
869  }
870 
872  {
873  return PeriodicBoxLength;
874  }
875  void set_PeriodicBoxLength(double new_)
876  {
877  PeriodicBoxLength = new_;
878  }
880  {
881  return PeriodicBoxNSpecies;
882  }
883  void set_PeriodicBoxNSpecies(int new_)
884  {
885  PeriodicBoxNSpecies = new_;
886  }
887 
889  {
890  return P->getIndSpecies() < PeriodicBoxNSpecies;
891  }
892 
894 
895 private:
900 
901  bool FillChute;
902 };
@ R
Definition: StatisticsVector.h:42
virtual unsigned int getNumberOfObjects() const
Gets the number of real Object in this BaseHandler. (i.e. no mpi or periodic particles)
Definition: BaseHandler.h:648
void setStorageCapacity(const unsigned int N)
Sets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:669
const std::vector< T * >::const_iterator begin() const
Gets the begin of the const_iterator over all Object in this BaseHandler.
Definition: BaseHandler.h:690
std::enable_if<!std::is_pointer< U >::value, U * >::type copyAndAddObject(const U &object)
Creates a copy of a Object and adds it to the BaseHandler.
Definition: BaseHandler.h:379
unsigned int getStorageCapacity() const
Gets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:662
const std::vector< T * >::const_iterator end() const
Gets the end of the const_iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:704
T * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:613
T * getLastObject()
Gets a pointer to the last Object in this BaseHandler.
Definition: BaseHandler.h:634
const Quaternion & getOrientation() const
Returns the orientation of this BaseInteractable.
Definition: BaseInteractable.h:230
virtual const Vec3D & getAngularVelocity() const
Returns the angular velocity of this interactable.
Definition: BaseInteractable.cc:341
void addTorque(const Vec3D &addTorque)
Adds an amount to the torque on this BaseInteractable.
Definition: BaseInteractable.cc:132
virtual const Vec3D & getVelocity() const
Returns the velocity of this interactable.
Definition: BaseInteractable.cc:329
virtual void move(const Vec3D &move)
Moves this BaseInteractable by adding an amount to the position.
Definition: BaseInteractable.cc:215
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
Definition: BaseInteractable.h:218
void addForce(const Vec3D &addForce)
Adds an amount to the force on this BaseInteractable.
Definition: BaseInteractable.cc:116
unsigned int getIndSpecies() const
Returns the index of the species associated with the interactable object.
Definition: BaseInteractable.h:88
unsigned int getIndex() const
Returns the index of the object in the handler.
Definition: BaseObject.h:118
Definition: BaseParticle.h:54
bool isFixed() const override
Is fixed Particle function. It returns whether a Particle is fixed or not, by checking its inverse Ma...
Definition: BaseParticle.h:93
void setPeriodicFromParticle(BaseParticle *p)
Assigns the pointer to the 'original' particle this one's a periodic copy of (used in periodic bounda...
Definition: BaseParticle.h:441
Mdouble getRadius() const
Returns the particle's radius.
Definition: BaseParticle.h:348
Mdouble getMass() const
Returns the particle's mass.
Definition: BaseParticle.h:322
virtual BaseParticle * copy() const =0
Particle copy method. It calls to copy constructor of this Particle, useful for polymorphism.
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
Definition: BaseParticle.h:341
void setSpecies(const ParticleSpecies *species)
Definition: BaseParticle.cc:818
BaseSpecies is the class from which all other species are derived.
Definition: BaseSpecies.h:50
Particles of a single Species.
Definition: ChuteWithPeriodicInflow.h:38
void set_PeriodicBoxNSpecies(int new_)
Definition: ChuteWithPeriodicInflow.h:883
void set_PeriodicBoxLength(double new_)
Definition: ChuteWithPeriodicInflow.h:875
void integrateBeforeForceComputation()
Update particles' and walls' positions and velocities before force computation.
Definition: ChuteWithPeriodicInflow.h:176
int Check_and_Duplicate_Periodic_Particle(BaseParticle *i, int nWallPeriodic)
Definition: ChuteWithPeriodicInflow.h:748
void ExtendInWidth(int numRepetitionsInWidth)
Definition: ChuteWithPeriodicInflow.h:117
void computeInternalForces(BaseParticle *P1, BaseParticle *P2)
Definition: ChuteWithPeriodicInflow.h:265
void setupInitialConditions() override
Do not add bottom.
Definition: ChuteWithPeriodicInflow.h:172
double getInfo(const BaseParticle &P) const override
A virtual function that returns some user-specified information about a particle.
Definition: ChuteWithPeriodicInflow.h:58
void actionsBeforeTimeStep() override
Do not add, only remove particles.
Definition: ChuteWithPeriodicInflow.h:141
void writeXBallsScript() const
This writes a script which can be used to load the xballs problem to display the data just generated.
Definition: ChuteWithPeriodicInflow.h:776
bool FillChute
Definition: ChuteWithPeriodicInflow.h:901
void outputXBallsDataParticlee(const unsigned int i, const unsigned int format, std::ostream &os) const
Definition: ChuteWithPeriodicInflow.h:849
double PeriodicBoxLength
stores the length of the periodic box
Definition: ChuteWithPeriodicInflow.h:897
SphericalParticle inflowParticle_
Definition: ChuteWithPeriodicInflow.h:893
ChuteWithPeriodicInflow(std::string restart_file, int numRepetitions, int numRepetitionsInWidth)
Definition: ChuteWithPeriodicInflow.h:51
void printTime() const override
add some particular output
Definition: ChuteWithPeriodicInflow.h:226
void AddContinuingBottom(int numRepetitions)
Definition: ChuteWithPeriodicInflow.h:91
bool InPeriodicBox(BaseParticle *P)
Definition: ChuteWithPeriodicInflow.h:888
ChuteWithPeriodicInflow(std::string restart_file, int numRepetitions)
Definition: ChuteWithPeriodicInflow.h:45
double get_PeriodicBoxLength()
Definition: ChuteWithPeriodicInflow.h:871
int PeriodicBoxNSpecies
stores the number of species in the periodic box
Definition: ChuteWithPeriodicInflow.h:899
ChuteWithPeriodicInflow(std::string restart_file)
Definition: ChuteWithPeriodicInflow.h:40
void cleanChute()
Remove particles if they fall below a certain height (allows them to become supercritical)
Definition: ChuteWithPeriodicInflow.h:147
int get_PeriodicBoxNSpecies()
Definition: ChuteWithPeriodicInflow.h:879
void loadPeriodicBox(std::string const restart_file)
loads periodic chute data from restart file
Definition: ChuteWithPeriodicInflow.h:64
Creates chutes with different bottoms. Inherits from Mercury3D (-> MercuryBase -> DPMBase).
Definition: Chute.h:65
Mdouble getMaxInflowParticleRadius() const
Returns the maximum radius of inflow particles.
Definition: Chute.cc:947
bool getIsPeriodic() const
Returns whether the chute is periodic in Y.
Definition: Chute.cc:642
int getXBallsColourMode() const
Get the xballs colour mode (CMode).
Definition: DPMBase.cc:1310
Mdouble getXMin() const
If the length of the problem domain in x-direction is XMax - XMin, then getXMin() returns XMin.
Definition: DPMBase.h:619
Mdouble getXMax() const
If the length of the problem domain in x-direction is XMax - XMin, then getXMax() returns XMax.
Definition: DPMBase.h:626
File eneFile
An instance of class File to handle in- and output into a .ene file.
Definition: DPMBase.h:1488
SpeciesHandler speciesHandler
A handler to that stores the species type i.e. LinearViscoelasticSpecies, etc.
Definition: DPMBase.h:1427
double getXBallsVectorScale() const
Returns the scale of vectors used in xballs.
Definition: DPMBase.cc:1330
File fStatFile
An instance of class File to handle in- and output into a .fstat file.
Definition: DPMBase.h:1483
Mdouble getYMin() const
If the length of the problem domain in y-direction is YMax - YMin, then getYMin() returns YMin.
Definition: DPMBase.h:632
void setName(const std::string &name)
Allows to set the name of all the files (ene, data, fstat, restart, stat)
Definition: DPMBase.cc:422
Mdouble getTimeStep() const
Returns the simulation time step.
Definition: DPMBase.cc:1250
const std::string & getName() const
Returns the name of the file. Does not allow to change it though.
Definition: DPMBase.cc:399
Mdouble getTime() const
Returns the current simulation time.
Definition: DPMBase.cc:808
std::string getXBallsAdditionalArguments() const
Returns the additional arguments for xballs.
Definition: DPMBase.cc:1355
File dataFile
An instance of class File to handle in- and output into a .data file.
Definition: DPMBase.h:1478
void setYMax(Mdouble newYMax)
Sets the value of YMax, the upper bound of the problem domain in the y-direction.
Definition: DPMBase.cc:1191
void setRestarted(bool newRestartedFlag)
Allows to set the flag stating if the simulation is to be restarted or not.
Definition: DPMBase.cc:1501
BoundaryHandler boundaryHandler
An object of the class BoundaryHandler which concerns insertion and deletion of particles into or fro...
Definition: DPMBase.h:1452
void gatherContactStatistics()
Definition: DPMBase.cc:1898
void setXMax(Mdouble newXMax)
Sets the value of XMax, the upper bound of the problem domain in the x-direction.
Definition: DPMBase.cc:1165
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created.
Definition: DPMBase.h:1437
double getXBallsScale() const
Returns the scale of the view in xballs.
Definition: DPMBase.cc:1372
Mdouble getYMax() const
If the length of the problem domain in y-direction is YMax - YMin, then getYMax() returns XMax.
Definition: DPMBase.h:638
File statFile
An instance of class File to handle in- and output into a .stat file.
Definition: DPMBase.h:1498
unsigned int getSystemDimensions() const
Returns the system dimensionality.
Definition: DPMBase.cc:1430
Mdouble getZMax() const
If the length of the problem domain in z-direction is ZMax - ZMin, then getZMax() returns ZMax.
Definition: DPMBase.h:650
Mdouble getZMin() const
If the length of the problem domain in z-direction is ZMax - ZMin, then getZMin() returns ZMin.
Definition: DPMBase.h:644
bool readRestartFile(ReadOptions opt=ReadOptions::ReadAll)
Reads all the particle data corresponding to a given, existing . restart file (for more details regar...
Definition: DPMBase.cc:3006
std::fstream & getFstream()
Allows to access the member variable File::fstream_.
Definition: File.cc:153
const std::string getFullName() const
Also allows to access the file name, however with additional information which is the file counter,...
Definition: File.cc:170
unsigned int getSaveCount() const
Gets File::saveCount_.
Definition: File.cc:255
void hGridUpdateParticle(BaseParticle *obj) override
Updates the cell (not the level) of a BaseParticle.
Definition: Mercury3D.cc:361
void hGridRemoveParticle(BaseParticle *obj) override
Removes a BaseParticle from the HGrid.
Definition: Mercury3D.cc:422
bool getHGridUpdateEachTimeStep() const final
Gets whether or not the HGrid is updated every time step.
Definition: MercuryBase.cc:184
void addObject(BaseParticle *P) override
Adds a BaseParticle to the ParticleHandler.
Definition: ParticleHandler.cc:171
void removeObject(unsigned int index) override
Removes a BaseParticle from the ParticleHandler.
Definition: ParticleHandler.cc:394
unsigned int getNumberOfObjects() const override
Returns the number of objects in the container. In parallel code this practice is forbidden to avoid ...
Definition: ParticleHandler.cc:1325
BaseParticle * getLargestParticle() const
Returns the pointer of the largest particle in the particle handler. When mercury is running in paral...
Definition: ParticleHandler.cc:534
Definition: ParticleSpecies.h:37
Defines a pair of periodic walls. Inherits from BaseBoundary.
Definition: PeriodicBoundary.h:41
Mdouble getDistance(const BaseParticle &p) const override
Returns the distance of the edge to the particle.
Definition: PeriodicBoundary.cc:197
virtual void shiftPosition(BaseParticle *p) const override
shifts the particle
Definition: PeriodicBoundary.cc:219
virtual bool isClosestToLeftBoundary(const BaseParticle &p) const
Returns TRUE if particle checked is closest to the 'left' edge, and FALSE if it is closest to the 'ri...
Definition: PeriodicBoundary.cc:275
void set(Vec3D normal, Mdouble distanceLeft, Mdouble distanceRight)
Defines a PeriodicBoundary by its normal and positions.
Definition: PeriodicBoundary.cc:84
std::enable_if<!std::is_pointer< typename U::MixedSpeciesType >::value, typename U::MixedSpeciesType * >::type getMixedObject(const U *S, const U *T)
Definition: SpeciesHandler.h:74
Contains material and contact force properties.
Definition: Species.h:35
A spherical particle is the most simple particle used in MercuryDPM.
Definition: SphericalParticle.h:37
Definition: Vector.h:51
Mdouble Y
Definition: Vector.h:66
Mdouble Z
Definition: Vector.h:66
static Mdouble getLengthSquared(const Vec3D &a)
Calculates the squared length of a Vec3D: .
Definition: Vector.h:332
static Vec3D cross(const Vec3D &a, const Vec3D &b)
Calculates the cross product of two Vec3D: .
Definition: Vector.cc:163
Mdouble X
the vector components
Definition: Vector.h:66
static Mdouble getLength(const Vec3D &a)
Calculates the length of a Vec3D: .
Definition: Vector.cc:331
static Mdouble getDistanceSquared(const Vec3D &a, const Vec3D &b)
Calculates the squared distance between two Vec3D: .
Definition: Vector.h:311
void setZero()
Sets all elements to zero.
Definition: Vector.cc:43
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:76
Mdouble getLength() const
Calculates the length of this Vec3D: .
Definition: Vector.cc:320
double P
Uniform pressure.
Definition: TwenteMeshGluing.cpp:73
const std::complex< Mdouble > i
Definition: ExtendedMath.h:51
T square(const T val)
squares a number
Definition: ExtendedMath.h:106