MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Helpers.cc
Go to the documentation of this file.
1 //Copyright (c) 2013-2014, 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 #include "Helpers.h"
27 #include <cmath>
28 #include <sys/stat.h>
29 #include <sstream>
30 #include <string>
31 #include <Logger.h>
32 #include <DPMBase.h>
33 #include <Walls/InfiniteWall.h>
34 #include <Particles/BaseParticle.h>
35 #include <Species/BaseSpecies.h>
36 #include <assert.h>
37 #include "Math/ExtendedMath.h"
38 
39 
41 {
45  return ans;
46 }
47 
49 {
50  if (k <= 0)
51  {
52  std::cerr << "Error in helpers::computeCollisionTimeFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
53  exit(-1);
54  }
55  if (disp < 0)
56  {
57  std::cerr << "Error in helpers::computeCollisionTimeFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) dissipation is not set or has an unexpected value, (dissipation=" << disp << ")" << std::endl;
58  exit(-1);
59  }
60  if (mass <= 0)
61  {
62  std::cerr << "Error in helpers::computeCollisionTimeFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
63  exit(-1);
64  }
65  if (4.0 * k / mass - mathsFunc::square(disp / mass) < 0)
66  {
67  std::cerr << "Error in helpers::computeCollisionTimeFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) values for stiffness, dissipation and mass lead to an overdamped system (stiffness=" << k << " dissipation=" << disp << " mass=" << mass << ")" << std::endl;
68  exit(-1);
69  }
70  return 2.0 * constants::pi / std::sqrt(4.0 * k / mass - mathsFunc::square(disp / mass));
71 }
72 
74 {
75  if (k <= 0)
76  {
77  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
78  exit(-1);
79  }
80  if (disp < 0)
81  {
82  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) dissipation is not set or has an unexpected value, (dissipation=" << disp << ")" << std::endl;
83  exit(-1);
84  }
85  if (mass <= 0)
86  {
87  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
88  exit(-1);
89  }
90  if (4.0 * mass * k - mathsFunc::square(disp) < 0)
91  {
92  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKandDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) values for stiffness, dissipation and mass lead to an overdamped system (stiffness=" << k << " dissipation=" << disp << " mass=" << mass << ")" << std::endl;
93  exit(-1);
94  }
95  return std::exp(-disp * constants::pi / std::sqrt(4.0 * mass * k - mathsFunc::square(disp)));
96 }
97 
99 {
100  if (k <= 0)
101  {
102  std::cerr << "Error in helpers::computeDispFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
103  exit(-1);
104  }
105  if (r < 0)
106  {
107  std::cerr << "Error in helpers::computeDispFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) restitution coefficient is not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
108  exit(-1);
109  }
110  if (mass <= 0)
111  {
112  std::cerr << "Error in helpers::computeDispFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
113  exit(-1);
114  }
115  return -2.0 * sqrt(mass * k / (constants::sqr_pi + mathsFunc::square(std::log(r)))) * std::log(r);
116 }
117 
119 {
120  if (k <= 0)
121  {
122  std::cerr << "Error in helpers::computeCollisionTimeFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
123  exit(-1);
124  }
125  if (r < 0)
126  {
127  std::cerr << "Error in helpers::computeCollisionTimeFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) restitution coefficient is not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
128  exit(-1);
129  }
130  if (mass <= 0)
131  {
132  std::cerr << "Error in helpers::computeCollisionTimeFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
133  exit(-1);
134  }
135  return sqrt(mass / k * (constants::sqr_pi + mathsFunc::square(std::log(r))));
136 }
137 
139 {
140  if (k <= 0)
141  {
142  std::cerr << "Error in helpers::computeDispFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
143  exit(-1);
144  }
145  if (tc <= 0)
146  {
147  std::cerr << "Error in helpers::computeDispFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
148  exit(-1);
149  }
150  if (mass <= 0)
151  {
152  std::cerr << "Error in helpers::computeDispFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
153  exit(-1);
154  }
155  if (mass * k - constants::sqr_pi * mathsFunc::square(mass / tc) < 0)
156  {
157  std::cerr << "Error in helpers::computeDispFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) values for stiffness, collision time and mass lead to an overdamped system (stiffness=" << k << " collision time=" << tc << " mass=" << mass << ")" << std::endl;
158  exit(-1);
159  }
160  return 2.0 * std::sqrt(mass * k - constants::sqr_pi * mathsFunc::square(mass / tc));
161 }
162 
164 {
165  if (k <= 0)
166  {
167  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) stiffness is not set or has an unexpected value, (stiffness=" << k << ")" << std::endl;
168  exit(-1);
169  }
170  if (tc <= 0)
171  {
172  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
173  exit(-1);
174  }
175  if (mass <= 0)
176  {
177  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
178  exit(-1);
179  }
180  if (k / mass * mathsFunc::square(tc) - constants::sqr_pi < 0)
181  {
182  std::cerr << "Error in helpers::computeRestitutionCoefficientFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass) values for stiffness, collision time and mass lead to an overdamped system (stiffness=" << k << " collision time=" << tc << " mass=" << mass << ")" << std::endl;
183  exit(-1);
184  }
185  return std::exp(-std::sqrt(k / mass * mathsFunc::square(tc) - constants::sqr_pi));
186 }
187 
189 {
190  if (tc <= 0)
191  {
192  std::cerr << "Error in helpers::computeDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
193  exit(-1);
194  }
195  if (r < 0)
196  {
197  std::cerr << "Error in helpers::computeDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) restitution coefficient not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
198  exit(-1);
199  }
200  if (mass <= 0)
201  {
202  std::cerr << "Error in helpers::computeDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
203  exit(-1);
204  }
205  return -2.0 * mass * std::log(r) / tc;
206 }
207 
209 {
210  if (tc <= 0)
211  {
212  std::cerr << "Error in helpers::computeKFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
213  exit(-1);
214  }
215  if (r < 0)
216  {
217  std::cerr << "Error in helpers::computeKFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) restitution coefficient not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
218  exit(-1);
219  }
220  if (mass <= 0)
221  {
222  std::cerr << "Error in helpers::computeKFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
223  exit(-1);
224  }
225  return mass * (mathsFunc::square(constants::pi / tc) + mathsFunc::square(-std::log(r) / tc));
226 }
227 
229 {
230  if (tc <= 0)
231  {
232  std::cerr << "Error in helpers::computeKFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
233  exit(-1);
234  }
235  if (disp < 0)
236  {
237  std::cerr << "Error in helpers::computeKFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) dissipation not set or has an unexpected value, (dissipation=" << disp << ")" << std::endl;
238  exit(-1);
239  }
240  if (mass <= 0)
241  {
242  std::cerr << "Error in helpers::computeKFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
243  exit(-1);
244  }
245  return 0.25 * mathsFunc::square(disp) / mass + constants::sqr_pi * mass / mathsFunc::square(tc);
246 }
247 
249 {
250  if (tc <= 0)
251  {
252  std::cerr << "Error in helpers::computeRestitutionCoefficientFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) collision time is not set or has an unexpected value, (collision time=" << tc << ")" << std::endl;
253  exit(-1);
254  }
255  if (disp < 0)
256  {
257  std::cerr << "Error in helpers::computeRestitutionCoefficientFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) dissipation not set or has an unexpected value, (dissipation=" << disp << ")" << std::endl;
258  exit(-1);
259  }
260  if (mass <= 0)
261  {
262  std::cerr << "Error in helpers::computeRestitutionCoefficientFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
263  exit(-1);
264  }
265  return std::exp(-0.5 * disp * tc / mass);
266 }
267 
269 {
270  if (disp <= 0)
271  {
272  std::cerr << "Error in helpers::computeKFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) dissipation is not set or has an unexpected value, (dissipation time=" << disp << ")" << std::endl;
273  exit(-1);
274  }
275  if (r < 0)
276  {
277  std::cerr << "Error in helpers::computeKFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) restitution coefficient not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
278  exit(-1);
279  }
280  if (mass <= 0)
281  {
282  std::cerr << "Error in helpers::computeKFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
283  exit(-1);
284  }
285  return 0.25 * mathsFunc::square(disp)*(constants::sqr_pi / (mathsFunc::square(std::log(r))) + 1.0) / mass;
286 }
287 
289 {
290  if (disp <= 0)
291  {
292  std::cerr << "Error in helpers::computeCollisionTimeFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) dissipation is not set or has an unexpected value, (dissipation time=" << disp << ")" << std::endl;
293  exit(-1);
294  }
295  if (r < 0)
296  {
297  std::cerr << "Error in helpers::computeCollisionTimeFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) restitution coefficient not set or has an unexpected value, (restitution coefficient=" << r << ")" << std::endl;
298  exit(-1);
299  }
300  if (mass <= 0)
301  {
302  std::cerr << "Error in helpers::computeCollisionTimeFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass) mass is not set or has an unexpected value (mass=" << mass << ")" << std::endl;
303  exit(-1);
304  }
305  return -2.0 * mass * std::log(r) / disp;
306 }
308 
310 {
312  ans.disp = -2.0 * mass * log(r) / tc;
313  ans.k = mass * (mathsFunc::square(constants::pi / tc) + mathsFunc::square(ans.disp / (2.0 * mass)));
315  if (beta != 0.0)
316  ans.dispt = -2 * log(beta) * sqrt(1.0 / 7.0 * mass * ans.kt / (mathsFunc::square(constants::pi) + mathsFunc::square(log(beta))));
317  else
318  ans.dispt = 2. * sqrt(1.0 / 7.0 * mass * ans.kt);
319  return ans;
320 }
321 
323 {
324  // note: underestimate based on energy argument,
325  // Ekin = 2*1/2*m*(v/2)^2 = 1/2*k*(2*r)^2, gives
326  // return radius * sqrt(8.0*k/mass);
327 
328  // with dissipation, see S. Luding, Collisions & Contacts between two particles, eq 34
329  Mdouble w = sqrt(k / mass - mathsFunc::square(disp / (2.0 * mass)));
330  Mdouble w0 = sqrt(k / mass);
331  Mdouble DispCorrection = exp(-disp / mass / w) * asin(w / w0);
332  //std::cout << "DispCorrection" << DispCorrection << std::endl;
333  return radius * sqrt(8.0 * k / mass) / DispCorrection;
334 }
335 
350 unsigned int helpers::getSaveCountFromNumberOfSavesAndTimeMaxAndTimestep(unsigned int numberOfSaves, Mdouble timeMax, Mdouble timestep)
351 {
352  if (numberOfSaves > 0 && timeMax > 0 && timestep > 0)
353  {
354  return static_cast<unsigned int>(ceil((timeMax + timestep) / timestep / static_cast<double>(numberOfSaves - 1)));
355  }
356  else
357  {
358  logger(ERROR, "[Helpers::getSaveCountFromNumberOfSavesAndTimeMaxAndTimestep()] numberOfSaves: %, timeMax: %, timestep: %", numberOfSaves, timeMax, timestep);
359  logger(ERROR, " Arguments need to be positive");
360  exit(-1);
361  }
362 }
363 
364 //seems to be unused, consider taking out \author weinhartt
365 //unsigned int helpers::getSaveCountFromNumberOfSavesPerTimeUnitAndTimestep(unsigned int numberOfSaves, Mdouble timestep)
366 //{
367 // if (numberOfSaves > 1 && timestep > 0)
368 // {
369 // return static_cast<unsigned int>(ceil(1.0 / timestep / static_cast<double>(numberOfSaves - 1)));
370 // }
371 // else
372 // {
373 // std::cerr << "Error in getSaveCountFromNumberOfSavesPerTimeUnitAndTimestep (" << numberOfSaves << "," << timestep << ")" << std::endl;
374 // std::cerr << "Arguments need to be positive" << std::endl;
375 // exit(-1);
376 // }
377 //}
378 
396 void helpers::getLineFromStringStream(std::istream& in, std::stringstream& out)
397 {
398  std::string line_string;
399  getline(in, line_string);
400  out.str(line_string);
401  out.clear();
402 }
403 
418 bool helpers::writeToFile(std::string filename, std::string filecontent)
419 {
420  std::fstream file;
421  file.open(filename.c_str(), std::ios::out);
422  if (file.fail())
423  {
424  std::cerr << "Error in writeToFile: file could not be opened" << std::endl;
425  return false;
426  }
427  file << filecontent;
428  file.close();
429  return true;
430 }
431 
432 bool helpers::addToFile(std::string filename, std::string filecontent)
433 {
434  std::fstream file;
435  file.open(filename.c_str(), std::ios::app);
436  if (file.fail())
437  {
438  std::cerr << "Error in writeToFile: file could not be opened" << std::endl;
439  return false;
440  }
441  file << filecontent;
442  file.close();
443  return true;
444 }
445 
450 bool helpers::fileExists(std::string strFilename)
451 {
452  struct stat stFileInfo;
453  bool blnReturn;
454  int intStat;
455 
456  // Attempt to get the file attributes
457 
458  intStat = stat(strFilename.c_str(), &stFileInfo);
459  if (intStat == 0)
460  {
461  // We were able to get the file attributes
462  // so the file obviously exists.
463  blnReturn = true;
464  }
465  else
466  {
467  // We were not able to get the file attributes.
468  // This may mean that we don't have permission to
469  // access the folder which contains this file. If you
470  // need to do that level of checking, lookup the
471  // return values of stat which will give you
472  // more details on why stat failed.
473  blnReturn = false;
474  }
475 
476  return blnReturn;
477 }
478 
487 bool helpers::openFile(std::fstream& file, std::string filename, std::fstream::openmode mode)
488 {
489  file.open(filename.c_str(), mode);
490  if (file.fail())
491  return false;
492  else
493  return true;
494 }
495 
504 {
505  return mass0 * mass1 / (mass0 + mass1);
506 }
507 
508 std::vector<double> helpers::readArrayFromFile(std::string filename, int& n, int& m)
509 {
510  std::fstream file;
511  file.open(filename.c_str(), std::ios::in);
512  if (file.fail())
513  {
514  std::cerr << "Error in readArrayFromFile: file could not be opened" << std::endl;
515  exit(-1);
516  }
517  file >> n >> m;
518  std::vector<double> v;
519  Mdouble val;
520  for (int i=0; i<n*m; i++)
521  {
522  file >> val;
523  v.push_back(val);
524  }
525  file.close();
526  return v;
527 }
528 
535 void helpers::loadingTest(const ParticleSpecies* species, Mdouble displacement, Mdouble velocity, Mdouble radius, std::string name)
536 {
537  class LoadingTest : public DPMBase {
538  const ParticleSpecies* species;
539  Mdouble displacement;
540  Mdouble velocity;
541  Mdouble radius;
542  public:
543  //public variables
544  LoadingTest (const ParticleSpecies* species, Mdouble displacement, Mdouble velocity, Mdouble radius)
545  : species(species), displacement(displacement), velocity(velocity), radius(radius) {}
546 
547  void setupInitialConditions() override
548  {
549  //setName("LoadingTest"+species->getName());
550  setTimeMax(2.0*displacement/velocity);
551  setTimeStep(2e-3*getTimeMax());
552  setSaveCount(1);
554  fStatFile.setFileType(FileType::ONE_FILE);
555 
556  setMax({radius,radius,radius+radius});
557  setMin({-radius,-radius,0});
560 
561  speciesHandler.copyAndAddObject(*species);
562 
563  BaseParticle p;
564  p.setSpecies(speciesHandler.getObject(0));
565  p.setRadius(radius);
566  p.setPosition({0,0,radius});
567  particleHandler.copyAndAddObject(p);
568 
569  InfiniteWall w;
570  w.setSpecies(speciesHandler.getObject(0));
571  w.set(Vec3D(0,0,-1),Vec3D(0.0,0.0,0.0));
572  wallHandler.copyAndAddObject(w);
573  }
574 
575  void actionsBeforeTimeStep() override {
576  BaseParticle* p = particleHandler.getLastObject();
577  assert(p);
578  p->setAngularVelocity({0,0,0});
579 
580  //Moving particle normally into surface
581  if (getTime() <= displacement/velocity) {
582  p->setVelocity({0,0,velocity});
583  p->setPosition({0,0,radius-velocity*getTime()});
584  } else {
585  p->setVelocity({0,0,-velocity});
586  p->setPosition({0,0,radius-displacement-displacement+velocity*getTime()});
587  }
588  }
589  } test(species, displacement, velocity, radius);
590  test.setName(name);
591  test.solve();
592  writeToFile(test.getName()+".gnu","plot '"+test.getName()+".fstat' u 7:9 w lp");
593  logger(INFO,"finished loading test: run 'gnuplot %.gnu' to view output",test.getName());
594 }
595 
603  Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius,
604  std::string name)
605 {
606  class LoadingTest : public DPMBase {
607  const ParticleSpecies* species;
608  Mdouble displacement;
609  Mdouble tangentialDisplacement;
610  Mdouble velocity;
611  Mdouble radius;
612  public:
613  //public variables
614  LoadingTest (const ParticleSpecies* species, Mdouble displacement, Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius)
615  : species(species), displacement(displacement), tangentialDisplacement(tangentialDisplacement), velocity(velocity), radius(radius) {}
616 
617  void setupInitialConditions() override
618  {
619  //setName("TangentialLoadingTest"+species->getName());
620  setTimeMax(4.0*tangentialDisplacement/velocity);
621  setTimeStep(2e-3*getTimeMax());
622  setSaveCount(1);
624  fStatFile.setFileType(FileType::ONE_FILE);
625 
626  setMax({radius,radius,radius+radius});
627  setMin({-radius,-radius,0});
630 
631  speciesHandler.copyAndAddObject(*species);
632 
633  BaseParticle p;
634  p.setSpecies(speciesHandler.getObject(0));
635  p.setRadius(radius);
636  p.setPosition({0,0,radius-displacement});
637  particleHandler.copyAndAddObject(p);
638 
639  InfiniteWall w;
640  w.setSpecies(speciesHandler.getObject(0));
641  w.set(Vec3D(0,0,-1),Vec3D(0.0,0.0,0.0));
642  wallHandler.copyAndAddObject(w);
643  }
644 
645  void actionsBeforeTimeStep() override {
646  BaseParticle* p = particleHandler.getLastObject();
647  assert(p);
648  p->setAngularVelocity({0,0,0});
649 
650  //Moving particle normally into surface
651  Mdouble time = getTime() / (tangentialDisplacement/velocity);
652  if (time <= 1.0) {
653  p->setVelocity({velocity,0,0});
654  p->setPosition({velocity*getTime(),0,radius-displacement});
655  } else if (time <= 3.0) {
656  p->setVelocity({-velocity,0,0});
657  p->setPosition({2.0*tangentialDisplacement-velocity*getTime(),0,radius-displacement});
658  } else {
659  p->setVelocity({velocity,0,0});
660  p->setPosition({-4.0*tangentialDisplacement+velocity*getTime(),0,radius-displacement});
661  }
662  }
663 
664  } test(species, displacement, tangentialDisplacement, velocity, radius);
665  test.setName(name);
666  test.solve();
667  writeToFile(test.getName()+".gnu","plot '"+test.getName()+".fstat' u 8:($10*$14) w lp");
668  logger(INFO,"finished tangential loading test: run 'gnuplot %.gnu' to view output",test.getName());
669 }
670 
677 void helpers::objectivenessTest(const ParticleSpecies* species, Mdouble displacement, Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius, std::string name)
678 {
679  class ObjectivenessTest : public DPMBase {
680  const ParticleSpecies* species;
681  Mdouble displacement;
682  Mdouble tangentialDisplacement;
683  Mdouble velocity;
684  Mdouble radius;
685  public:
686  //public variables
687  ObjectivenessTest (const ParticleSpecies* species, Mdouble displacement, Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius)
688  : species(species), displacement(displacement), tangentialDisplacement(tangentialDisplacement), velocity(velocity), radius(radius) {}
689 
690  void setupInitialConditions() override
691  {
692  //setName("ObjectivenessTest"+species->getName());
693  setTimeMax((tangentialDisplacement+0.5*constants::pi*radius)/velocity);
694  setTimeStep(1e-4*getTimeMax());
695  setSaveCount(20);
697  dataFile.setFileType(FileType::ONE_FILE);
698  fStatFile.setFileType(FileType::ONE_FILE);
699 
700  setMax(radius*Vec3D(2,2,2));
701  setMin(radius*Vec3D(-2,-2,-2));
704 
705  speciesHandler.copyAndAddObject(*species);
706 
707  BaseParticle p;
708  p.setSpecies(speciesHandler.getObject(0));
709  p.setRadius(radius);
710  p.setPosition({0,radius-displacement,0});
711  particleHandler.copyAndAddObject(p);
712  p.setPosition({0,-radius+displacement,0});
713  particleHandler.copyAndAddObject(p);
714  }
715 
716  void actionsBeforeTimeStep() override {
717  BaseParticle* p = particleHandler.getObject(0);
718  BaseParticle* q = particleHandler.getLastObject();
719  assert(p);
720  assert(q);
721 
722  //Moving particle normally into surface
723  if (getTime() <= tangentialDisplacement/velocity) {
724  p->setAngularVelocity({0,0,0});
725  p->setVelocity({velocity,0,0});
726  p->setPosition({-tangentialDisplacement+velocity*getTime(),radius-displacement,0});
727  q->setAngularVelocity({0,0,0});
728  q->setVelocity({-velocity,0,0});
729  q->setPosition({tangentialDisplacement-velocity*getTime(),-radius+displacement,0});
730  } else {
731  Mdouble angle = velocity/(radius-displacement) * (getTime()-tangentialDisplacement/velocity);
732  Mdouble s = sin(angle);
733  Mdouble c = cos(angle);
734  p->setAngularVelocity(velocity/(radius-displacement)*Vec3D(0,0,-1));
735  //p->setAngularVelocity(Vec3D(0,0,0));
736  //p->setOrientation({1,0,0,0});
737  p->setVelocity(velocity*Vec3D(c,-s,0));
738  //p->setVelocity(Vec3D(0,0,0));
739  p->setPosition((radius-displacement)*Vec3D(s,c,0));
741  q->setOrientation(-p->getOrientation());
742  q->setVelocity(-p->getVelocity());
743  q->setPosition(-p->getPosition());
744  }
745  }
746 
747  } test (species, displacement, tangentialDisplacement, velocity, radius);
748  test.setName(name);
749  test.solve();
750  writeToFile(test.getName()+".gnu","set size ratio -1; plot '"+test.getName()+".fstat' u 14:15 every 2 w lp");
751  logger(INFO,"finished objectiveness test: run 'gnuplot %.gnu' to view output",test.getName());
752 }
753 
754 bool helpers::compare(std::istream& is,std::string s)
755 {
756  // Get current position
757  //check if the next line starts with 'interactionFile'; otherwise, skip interaction
758  int len = is.tellg();
759  std::string dummy;
760  is >> dummy;
761  if (dummy.compare(s) != 0)
762  {
763  is.seekg(len, std::ios_base::beg);
764  return false;
765  logger(INFO, "helpers::compare: Next stream value (%) is not %", dummy,s);
766  }
767  return true;
768 }
769 
770 void helpers::check(double real, double ideal, double error, std::string errorMessage) {
771  logger.assert_always(mathsFunc::isEqual(real, ideal, error),
772  errorMessage + ": % (should be %) ",real, ideal);
773 }
MERCURY_DEPRECATED KAndDispAndKtAndDispt computeDisptFromCollisionTimeAndRestitutionCoefficientAndTangentialRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble beta, Mdouble mass)
Set disp, k, dispt and kt such that is matches a given collision time tc and a normal andtangential r...
Definition: Helpers.cc:309
bool writeToFile(std::string filename, std::string filecontent)
Writes a string to a file.
Definition: Helpers.cc:418
The DPMBase header includes quite a few header files, defining all the handlers, which are essential...
Definition: DPMBase.h:65
void setVelocity(const Vec3D &velocity)
set the velocity of the BaseInteractable.
void setTimeMax(Mdouble newTMax)
Allows the upper time limit to be changed.
Definition: DPMBase.cc:199
Mdouble getEffectiveMass(Mdouble mass0, Mdouble mass1)
Calculates the effective mass of a particle pair, i.e. half the harmonic mean of two particle masses...
Definition: Helpers.cc:503
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
return type specifically for fuctions returning k and disp at once
Definition: Helpers.h:42
void setOrientation(const Vec3D &orientation)
Sets the orientation of this BaseInteractable.
MERCURY_DEPRECATED Mdouble computeRestitutionCoefficientFromKAndDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass)
Calculates the restitution coefficient time for a given stiffness, dissipation, and effective mass...
Definition: Helpers.cc:73
LL< Log::INFO > INFO
Info log level.
Definition: Logger.cc:53
Mdouble exp(Mdouble Exponent)
Definition: ExtendedMath.cc:78
MERCURY_DEPRECATED Mdouble computeRestitutionCoefficientFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass)
Calculates the restitution coefficient for a given stiffness, collision time, and effective mass...
Definition: Helpers.cc:163
void check(double real, double ideal, double error, std::string errorMessage)
Definition: Helpers.cc:770
double Mdouble
void setParticleDimensions(unsigned int particleDimensions)
Allows the dimension of the particle (f.e. for mass) to be changed. e.g. discs or spheres...
Definition: DPMBase.cc:583
virtual const Vec3D & getAngularVelocity() const
Returns the angular velocity of this interactable.
void setSpecies(const ParticleSpecies *species)
return type specifically for fuctions returning k, disp, kt, dispt at once
Definition: Helpers.h:143
void normalAndTangentialLoadingTest(const ParticleSpecies *species, Mdouble displacement, Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius, std::string name)
Used to test the tangential loading/unloading/reloading properties of a frictional contact law...
Definition: Helpers.cc:602
void setSystemDimensions(unsigned int newDim)
Allows for the dimension of the simulation to be changed.
Definition: DPMBase.cc:562
void setFileType(FileType fileType)
Sets File::fileType_ for all files (ene, data, fstat, restart, stat)
Definition: Files.cc:170
Mdouble log(Mdouble Power)
Definition: ExtendedMath.cc:97
LL< Log::ERROR > ERROR
Error log level.
Definition: Logger.cc:51
bool isEqual(Mdouble v1, Mdouble v2, Mdouble absError)
Compares the difference of two Mdouble with an absolute error, useful in UnitTests.
T square(T val)
squares a number
Definition: ExtendedMath.h:91
void setRadius(const Mdouble radius)
Sets the particle's radius_ (and adjusts the mass_ accordingly, based on the particle's species) ...
const Vec3D & getPosition() const
Returns the position of this BaseInteractable.
const Vec3D & getOrientation() const
Returns the orientation of this BaseInteractable.
MERCURY_DEPRECATED Mdouble computeKFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass)
Calculates the stiffness for a given collision time, dissipation, and effective mass.
Definition: Helpers.cc:228
Mdouble cos(Mdouble x)
Definition: ExtendedMath.cc:60
MERCURY_DEPRECATED KAndDisp computeKAndDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass)
Set disp and k such that is matches a given collision time tc and restitution coefficient r for a col...
Definition: Helpers.cc:40
MERCURY_DEPRECATED Mdouble computeCollisionTimeFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass)
Calculates the collision time for a given stiffness, restitution coefficient, and effective mass...
Definition: Helpers.cc:118
MERCURY_DEPRECATED Mdouble computeDispFromKAndRestitutionCoefficientAndEffectiveMass(Mdouble k, Mdouble r, Mdouble mass)
Calculates the dissipation for a given stiffness, restitution coefficient, and effective mass...
Definition: Helpers.cc:98
file will not be created/read
Mdouble sin(Mdouble x)
Definition: ExtendedMath.cc:42
Mdouble disp
Definition: Helpers.h:46
void getLineFromStringStream(std::istream &in, std::stringstream &out)
Reads a line from one stringstream into another, and prepares the latter for reading in...
Definition: Helpers.cc:396
const Mdouble pi
Definition: ExtendedMath.h:42
all data will be written into/ read from a single file called name_
void setSaveCount(unsigned int saveCount)
Sets File::saveCount_ for all files (ene, data, fstat, restart, stat)
Definition: Files.cc:139
MERCURY_DEPRECATED Mdouble computeCollisionTimeFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass)
Calculates the collision time for a given dissipation, restitution coefficient, and effective mass...
Definition: Helpers.cc:288
void loadingTest(const ParticleSpecies *species, Mdouble displacement, Mdouble velocity, Mdouble radius, std::string name)
Used to test the loading/unloading properties of a contact law.
Definition: Helpers.cc:535
virtual void actionsBeforeTimeStep()
A virtual function which allows to define operations to be executed before the new time step...
Definition: DPMBase.cc:779
MERCURY_DEPRECATED Mdouble computeRestitutionCoefficientFromCollisionTimeAndDispAndEffectiveMass(Mdouble tc, Mdouble disp, Mdouble mass)
Calculates the resitution coefficient for a given collision time, dissipation, and effective mass...
Definition: Helpers.cc:248
#define assert(e,...)
Definition: Logger.h:584
void setPosition(const Vec3D &position)
Sets the position of this BaseInteractable.
void set(Vec3D normal, Vec3D point)
Defines a standard wall, given an outward normal vector s.t. normal*x=normal*point for all x of the w...
Definition: InfiniteWall.cc:79
MERCURY_DEPRECATED Mdouble computeKFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass)
Calculates the stiffness for a given collision time, restitution coefficient, and effective mass...
Definition: Helpers.cc:208
MERCURY_DEPRECATED Mdouble computeDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass)
Calculates the dissipation for a given collision time, restitution coefficient, and effective mass...
Definition: Helpers.cc:188
void setTimeStep(Mdouble newDt)
Allows the time step dt to be changed.
Definition: DPMBase.cc:451
bool compare(std::istream &is, std::string s)
Definition: Helpers.cc:754
void setMin(Vec3D min)
Sets the values xMin, yMin, zMin of the problem domain, which is [xMin,xMax]x[yMin,yMax]x[zMin,zMax].
Definition: DPMBase.cc:405
This is a class defining walls.
Definition: InfiniteWall.h:47
bool fileExists(std::string strFilename)
Function to check if a file exists, is used to check if a run has already need done.
Definition: Helpers.cc:450
MERCURY_DEPRECATED Mdouble getMaximumVelocity(Mdouble k, Mdouble disp, Mdouble radius, Mdouble mass)
Calculates the maximum relative velocity allowed for a normal collision of two particles of radius r ...
Definition: Helpers.cc:322
virtual const Vec3D & getVelocity() const
Returns the velocity of this interactable.
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
MERCURY_DEPRECATED Mdouble computeCollisionTimeFromKAndDispAndEffectiveMass(Mdouble k, Mdouble disp, Mdouble mass)
Calculates the collision time for a given stiffness, dissipation, and effective mass.
Definition: Helpers.cc:48
bool openFile(std::fstream &file, std::string filename, std::fstream::openmode mode)
Provides a simple interface for opening a file.
Definition: Helpers.cc:487
void objectivenessTest(const ParticleSpecies *species, Mdouble displacement, Mdouble tangentialDisplacement, Mdouble velocity, Mdouble radius, std::string name)
Used to test the tangential loading/unloading/reloading properties of a frictional contact law...
Definition: Helpers.cc:677
bool addToFile(std::string filename, std::string filecontent)
Adds a string to an existing file.
Definition: Helpers.cc:432
void setAngularVelocity(const Vec3D &angularVelocity)
set the angular velocity of the BaseInteractble.
MERCURY_DEPRECATED Mdouble computeKFromDispAndRestitutionCoefficientAndEffectiveMass(Mdouble disp, Mdouble r, Mdouble mass)
Calculates the stiffness for a given dissipation, restitution coefficient, and effective mass...
Definition: Helpers.cc:268
MERCURY_DEPRECATED Mdouble computeDispFromKAndCollisionTimeAndEffectiveMass(Mdouble k, Mdouble tc, Mdouble mass)
Calculates the dissipation for a given stiffness, collision time, and effective mass.
Definition: Helpers.cc:138
unsigned int getSaveCountFromNumberOfSavesAndTimeMaxAndTimestep(unsigned int numberOfSaves, Mdouble timeMax, Mdouble timestep)
Returns the correct saveCount if the total number of saves, the final time and the time step is known...
Definition: Helpers.cc:350
Mdouble getTime() const
Access function for the time.
Definition: DPMBase.cc:169
const Mdouble sqr_pi
Definition: ExtendedMath.h:44
Mdouble getTimeMax() const
Allows the user to access the total simulation time during the simulation. Cannot change it though...
Definition: DPMBase.cc:214
std::vector< double > readArrayFromFile(std::string filename, int &n, int &m)
Definition: Helpers.cc:508
virtual void setupInitialConditions()
This function allows to set the initial conditions for our problem to be solved, by default particle ...
Definition: DPMBase.cc:966
void setSpecies(const ParticleSpecies *species)
Define the species of this wall.
Definition: BaseWall.cc:113
void setMax(Vec3D max)
Sets the values xMax, yMax, zMax of the problem domain, which is [xMin,xMax]x[yMin,yMax]x[zMin,zMax].
Definition: DPMBase.cc:395