MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MD.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 //#define DEBUG_OUTPUT
27 //#define DEBUG_OUTPUT_FULL
28 
29 #include "MD.h"
30 
31 #include <iostream>
32 #include <iomanip>
33 #include <cmath>
34 #include <fstream>
35 #include <cstdlib>
36 #include <limits>
37 
38 //This is only used to change the file permission of the xball script create, at some point this code may be moved from this file to a different file.
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 
42 //This is part of this class and just separates out the stuff to do with xballs.
44 #include "MD_xballs.icc"
45 #include "RNG.cc"
46 
51 {
52  Species.resize(1);
53  set_restarted(false);
54 
55  //This sets the maximum number of particles
58  dim = 2;
59  format = 0;
60 
61  //These are the particle parameters like dissipation etc..
62  set_k(1e4);
63  set_rho(2000);
64  //\todo{Why shouldn't we set dim_particle (which defines the mass calculations) ALWAYS to three, even for 2D problems?}
65  set_dim_particle(2);
66 
67  // Set gravitational acceleration
68  gravity = Vec3D(0.0, -9.8, 0.0);
69 
70  //This is the parameter of the numerical part
71  dt=0e-5; // if dt is not user-specified, this is set in actions_before_time_loop()
73  set_do_stat_always(false);
74  tmax=1.0;
75 
76  //This sets the default xballs domain
77  xmin=0.0;
78  xmax=0.01;
79  ymin=0.0;
80  ymax=0.01;
81  zmin=0.0;
82  zmax=0.0;
83 
84  //This set the default position of walls
85  /*Wall w0;
86  w0.set(Vec3D(-1,0,0), -xmin);
87  wallHandler.copyAndAddWall(w0);
88  w0.set(Vec3D( 1,0,0), xmax);
89  wallHandler.copyAndAddWall(w0);
90  w0.set(Vec3D(0,-1,0), -ymin);
91  wallHandler.copyAndAddWall(w0);
92  w0.set(Vec3D(0, 1,0), ymax);
93  wallHandler.copyAndAddWall(w0);*/
94 
95  problem_name << "Problem_1";
97 
98  //Default mode is energy with no scale of the vectors
99  xballs_cmode=0;
100  xballs_vscale=-1;
101  xballs_scale=-1;
103  set_append(false);
104 
106 
107  PeriodicCreated=0;
108 
109  //The default random seed is 0
111  #ifdef DEBUG_OUTPUT
112  std::cerr << "MD problem constructor finished " << std::endl;
113  #endif
114 }
115 
121 {
122 }
123 
128 {
129  //only write if we don't restart
130  if (get_append()||!ene_file.is_open()) return;
131 
133  static int width = ene_file.precision() + 6;
134  ene_file
135  << std::setw(width) << "t" << " "
136  << std::setw(width) << "ene_gra" << " "
137  << std::setw(width) << "ene_kin" << " "
138  << std::setw(width) << "ene_rot" << " "
139  << std::setw(width) << "ene_ela" << " "
140  << std::setw(width) << "X_COM" << " "
141  << std::setw(width) << "Y_COM" << " "
142  << std::setw(width) << "Z_COM" << std::endl;
143 }
144 
146 {
147  // line #1: time, volume fraction
148  // line #2: wall box: wx0, wy0, wz0, wx1, wy1, wz1
149  // line #3: radii-min-max & moments: rad_min, rad_max, r1, r2, r3, r4
150  fstat_file << "#"
151  << " " << get_t()
152  << " " << 0
153  << std::endl;
154  fstat_file << "#"
155  << " " << get_xmin()
156  << " " << get_ymin()
157  << " " << get_zmin()
158  << " " << get_xmax()
159  << " " << get_ymax()
160  << " " << get_zmax()
161  << std::endl;
162  fstat_file << "#"
163  << " " << getSmallestParticle()->get_Radius()
164  << " " << getLargestParticle()->get_Radius()
165  << " " << 0
166  << " " << 0
167  << " " << 0
168  << " " << 0
169  << std::endl;
170 }
171 
176 {
177  Mdouble ene_kin = 0, ene_rot = 0, ene_gra = 0, mass_sum= 0, x_masslength=0, y_masslength=0, z_masslength=0;
178 
179  for (std::vector<BaseParticle*>::iterator it = getParticleHandler().begin(); it!=getParticleHandler().end(); ++it) if (!(*it)->isFixed())
180  {
181  ene_kin += .5 * (*it)->get_Mass() * (*it)->get_Velocity().GetLength2();
182  ene_rot += .5 * (*it)->get_Inertia() * (*it)->get_AngularVelocity().GetLength2();
183  ene_gra -= (*it)->get_Mass() * Dot(get_gravity(),(*it)->get_Position());
184  mass_sum+= (*it)->get_Mass();
185  x_masslength +=(*it)->get_Mass()*(*it)->get_Position().X;
186  y_masslength +=(*it)->get_Mass()*(*it)->get_Position().Y;
187  z_masslength +=(*it)->get_Mass()*(*it)->get_Position().Z;
188  } //end for loop over Particles
189 
191  static int width = ene_file.precision() + 6;
192  ene_file << std::setw(width) << get_t()
193  << " " << std::setw(width) << ene_gra
194  << " " << std::setw(width) << ene_kin
195  << " " << std::setw(width) << ene_rot
196  << " " << std::setw(width) << get_ene_ela()
197  << " " << std::setw(width) << (mass_sum?x_masslength/mass_sum:std::numeric_limits<double>::quiet_NaN())
198  << " " << std::setw(width) << (mass_sum?y_masslength/mass_sum:std::numeric_limits<double>::quiet_NaN())
199  << " " << std::setw(width) << (mass_sum?z_masslength/mass_sum:std::numeric_limits<double>::quiet_NaN())
200  << std::endl;
201 
202  set_ene_ela(0);
203  //sliding = sticking = 0;
204 }
205 
210 {
211  //Set the correct formation based of dimension if the formation is not specified by the user
212  if (format ==0) {
213  switch (dim) {
214  case 1:
215  case 2:
216  format=8;
217  break;
218  case 3:
219  format=14;
220  break;
221  }
222  }
223 
224  // This outputs the location of walls and how many particles there are to file this is required by the xballs plotting
225  if (format!=14) // dim = 1 or 2
226  data_file << particleHandler.getNumberOfObjects() << " " <<t << " "
227  << xmin << " " << ymin << " "
228  << xmax << " " << ymax << " " << std::endl;
229  else //dim==3
230  data_file << particleHandler.getNumberOfObjects() << " " <<t << " "
231  << xmin << " " << ymin << " " << zmin << " "
232  << xmax << " " << ymax << " " << zmax << " " << std::endl;
233  // This outputs the particle data
234  for (unsigned int i = 0;i<particleHandler.getNumberOfObjects();i++)
236  #ifdef DEBUG_OUTPUT
237  std::cerr << "Have output the properties of the problem to disk " << std::endl;
238  #endif
239 }
240 
250 bool MD::load_from_data_file (const char* filename, unsigned int format)
251 {
252  //This opens the file the data will be recalled from
253  data_file.open( filename, std::fstream::in);
254  if (!data_file.is_open()||data_file.bad()) {
255  std::cout << "Loading data file " << filename << " failed" << std::endl;
256  return false;
257  }
258 
259  //options_data is ignored
261  set_options_data(1);
262  read_next_from_data_file(format);
263  set_options_data(options_data);
264 
265  data_file.close();
266 
267  //std::cout << "Loaded data file " << filename << " (t=" << get_t() << ")" << std::endl;
268  return true;
269 }
270 
271 bool MD::load_par_ini_file (const char* filename)
272 {
273  //Opens the par.ini file
274  std::fstream file;
275  file.open( filename, std::fstream::in);
276  if (!file.is_open()||file.bad()) {
277  //std::cout << "Loading par.ini file " << filename << " failed" << std::endl;
278  return false;
279  }
280 
281  Mdouble doubleValue;
282  int integerValue;
283 
284  // inputfile par.ini
285  // line 1 =============================================================
286  // Example: 1 1 0
287  // 1: integer (0|1) switches from non-periodic to periodic
288  // integer (5|6) does 2D integration only (y-coordinates fixed)
289  // and switches from non-periodic to periodic
290  // integer (11) uses a quarter system with circular b.c.
291  file >> integerValue;
292  //~ std::cout << "11" << integerValue << std::endl;
293  if (integerValue==0)
294  {
295  InfiniteWall w0;
296  w0.set(Vec3D(-1,0,0), -get_xmin());
298  w0.set(Vec3D( 1,0,0), get_xmax());
300  w0.set(Vec3D( 0,-1,0), -get_ymin());
302  w0.set(Vec3D(0, 1,0), get_ymax());
304  w0.set(Vec3D(0,0,-1), -get_zmin());
306  w0.set(Vec3D(0,0,1), get_zmax());
308  }
309  else if (integerValue==1)
310  {
311  PeriodicBoundary b0;
312  b0.set(Vec3D(1,0,0), get_xmin(), get_xmax());
314  b0.set(Vec3D(0,1,0), get_ymin(), get_ymax());
316  b0.set(Vec3D(0,0,1), get_zmin(), get_zmax());
318  }
319  else if (integerValue==5)
320  {
321  InfiniteWall w0;
322  w0.set(Vec3D(-1,0,0), -get_xmin());
324  w0.set(Vec3D( 1,0,0), get_xmax());
326  w0.set(Vec3D( 0,-1,0), -get_ymin());
328  w0.set(Vec3D(0, 1,0), get_ymax());
330 
331 
332  }
333  else if (integerValue==6)
334  {
335  PeriodicBoundary b0;
336  b0.set(Vec3D(1,0,0), get_xmin(), get_xmax());
338  b0.set(Vec3D(0,1,0), get_ymin(), get_ymax());
340  b0.set(Vec3D(0,0,1), get_zmin(), get_zmax());
342  }
343  else
344  {
345  std::cerr << "Error in par.ini: line 1, value 1 is " << integerValue << std::endl;
346  exit(-1);
347  }
348 
349  // 2: integer (0|1) dont use | use the search pattern for linked cells
350  file >> integerValue; //ignore
351 
352  // 3: real - gravity in z direction: positive points upwards
353  file >> doubleValue;
354  set_gravity(Vec3D(0.0,0.0,doubleValue));
355 
356  // line 2 =============================================================
357  // Example: -10000 .5e-2
358  // 1: time end of simulation - (negative resets start time to zero
359  // and uses -time as end-time)
360  file >> doubleValue;
361  if (doubleValue<0) set_t(0);
362  set_tmax(fabs(doubleValue));
363 
364  // 2: time-step of simulation
365  file >> doubleValue;
366  set_dt(doubleValue);
367 
368  // line 3 =============================================================
369  // Example: 1e-1 100
370  file >> doubleValue;
371  if (doubleValue>=0) {
372  // 1: time-step for output on time-series protocoll file -> "ene"
373  int savecount = round(doubleValue/get_dt());
374  set_savecount(savecount);
375 
376  // 2: time-step for output on film (coordinate) file -> "c3d"
377  // (fstat-output is coupled to c3d-output time-step)
378  file >> doubleValue;
379  savecount = round(doubleValue/get_dt());
380  set_save_count_data(savecount);
381  set_save_count_fstat(savecount);
382  } else {
383  // or: ---------------------------------------------------------------
384  // 1: negative number is multiplied to the previous log-output-time
385  // 2: requires initial log-output time
386  // 3: negative number is multiplied to the previous film-output-time
387  // 4: requires initial film-output time
388  std::cerr << "Error in par.ini: line 3, value 1 is " << doubleValue << std::endl;
389  exit(-1);
390  }
391 
392  // line 4 =============================================================
393  // Example: 2000 1e5 1e3 1e2
394  // 1: particle density (mass=4/3*constants::pi*density*rad^3)
395  file >> doubleValue;
396  set_dim_particle(3);
397  set_rho(doubleValue);
398 
399  // 2: linear spring constant
400  file >> doubleValue;
401  set_k(doubleValue);
402 
403  // 3: linear dashpot constant
404  file >> doubleValue;
405  set_disp(doubleValue);
406 
407  // 4: background damping dashpot constant
408  file >> doubleValue;
409  if (doubleValue) std::cerr << "Warning in par.ini: ignored background damping " << doubleValue << std::endl;
410 
411  // line 5 =============================================================
412  // Example: 0 0
413  // 1: growth rate: d(radius) = xgrow * dt
414  file >> doubleValue;
415  if (doubleValue) std::cerr << "Warning in par.ini: ignored growth rate " << doubleValue << std::endl;
416 
417  // 2: target volume_fraction
418  file >> doubleValue;
419  if (doubleValue) std::cerr << "Warning in par.ini: ignored target volume_fraction " << doubleValue << std::endl;
420 
421  file.close();
422  //std::cout << "Loaded par.ini file " << filename << std::endl;
423  return true;
424 }
425 
426 bool MD::find_next_data_file (Mdouble tmin, bool verbose)
427 {
428  if (get_options_data()==2) {
429  while(true) {
430  increase_counter_data(std::fstream::in);
431  //check if file exists and contains data
432  int N;
433  data_file >> N;
434  if (data_file.eof()||data_file.peek()==-1) {
435  std::cout << "file " << get_data_filename() << " not found" << std::endl;
436  return false;
437  }
438  //check if tmin condition is satisfied
439  Mdouble t;
440  data_file >> t;
441  if (t>tmin) {
443  return true;
444  }
445  if (verbose) std::cout <<"Jumping file counter: "<<get_file_counter() << std::endl;
446  }
447  } else return true;
448  //length = is.tellg();
449  //is.seekg (0, ios::end);
450 }
451 
453 bool MD::read_next_from_data_file (unsigned int format)
454 {
455  if (get_options_data()==2) increase_counter_data(std::fstream::in);
456 
457 
458 
459  //Set the correct formation based of dimension if the formation is not specified by the user
460  if (format ==0)
461  {
462  switch (dim)
463  {
464  case 1:
465  case 2:
466  format=8;
467  break;
468  case 3:
469  format=14;
470  break;
471  }
472  //end case
473 
474  }
475  //end if
476 
477  static unsigned int N;
478  static Mdouble dummy;
479 
480  //read first parameter and check if we reached the end of the file
481  data_file >> N;
482  BaseParticle* P0;
485  if(get_k2max()) {
486  P0 = new DeltaMaxsParticle();
487  //std::cout << "in read_next_from_data_file(): using DeltaMaxsParticle" << std::endl;
488  } else if(get_mu()) {
489  P0 = new TangentialSpringParticle();
490  //std::cout << "in read_next_from_data_file(): using TangentialSpringParticle" << std::endl;
491  } else {
492  P0 = new BaseParticle();
493  //std::cout << "in read_next_from_data_file(): using BaseParticle" << std::endl;
494  }
495 
499  else
502  delete P0;
503 
504  #ifdef DEBUG_OUTPUT
505  std::cout << "Number of particles read from file "<<N << std::endl;
506  #endif
507 
508  if (data_file.eof()||data_file.peek()==-1) return false;
509  //read all other data available for the time step
510  switch(format)
511  {
512  //This is the format that Stefan's and Vitaley's code saves in - note the axis rotation
513  case 7:
514  {
515  data_file >> t >> xmin >> zmin >> ymin >> xmax >> zmax >> ymax;
516  //std::cout << " time " << t << std::endl;
517  Mdouble radius;
518  Vec3D position,velocity;
519  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) {
520  data_file
521  >> position.X
522  >> position.Z
523  >> position.Y
524  >> velocity.X
525  >> velocity.Z
526  >> velocity.Y
527  >> radius
528  >> dummy;
529  (*it)->set_Position(position);
530  (*it)->set_Velocity(velocity);
531  (*it)->set_Angle(Vec3D(0.0,0.0,0.0));
532  (*it)->set_AngularVelocity(Vec3D(0.0,0.0,0.0));
533  (*it)->set_Radius(radius);
534  (*it)->compute_particle_mass(Species);
535  }
536  //End the interator over all particles
537  break;
538  }
539  //This is a 2D format
540  case 8:
541  {
542  data_file >> t >> xmin >> ymin >> xmax >> ymax;
543  zmin = 0.0;
544  zmax = 0.0;
545  Mdouble radius;
546  Vec3D position,velocity,angle,angularVelocity;
547  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) {
548  data_file
549  >> position.X
550  >> position.Y
551  >> velocity.X
552  >> velocity.Y
553  >> radius
554  >> angle.Z
555  >> angularVelocity.Z
556  >> dummy;
557  (*it)->set_Position(position);
558  (*it)->set_Velocity(velocity);
559  (*it)->set_Angle(-angle);
560  (*it)->set_AngularVelocity(-angularVelocity);
561  (*it)->set_Radius(radius);
562  (*it)->compute_particle_mass(Species);
563  } //end for all particles
564  break;
565  }
566  //This is a 3D format
567  case 14:
568  {
569  data_file >> t >> xmin >> ymin >> zmin >> xmax >> ymax >> zmax;
570  Mdouble radius;
571  Vec3D position,velocity,angle,angularVelocity;
572  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) {
573  data_file
574  >> position
575  >> velocity
576  >> radius
577  >> angle
578  >> angularVelocity
579  >> dummy;
580  (*it)->set_Position(position);
581  (*it)->set_Velocity(velocity);
582  (*it)->set_Angle(angle);
583  (*it)->set_AngularVelocity(angularVelocity);
584  (*it)->set_Radius(radius);
585  (*it)->compute_particle_mass(Species);
586  } //end for all particles
587  break;
588  }
589  //This is a 3D format
590  case 15:
591  {
592  data_file >> t >> xmin >> ymin >> zmin >> xmax >> ymax >> zmax;
593  Mdouble radius;
594  Vec3D position,velocity,angle,angularVelocity;
595  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) {
596  data_file
597  >> position
598  >> velocity
599  >> radius
600  >> angle
601  >> angularVelocity
602  >> dummy >> dummy;
603  (*it)->set_Position(position);
604  (*it)->set_Velocity(velocity);
605  (*it)->set_Angle(angle);
606  (*it)->set_AngularVelocity(angularVelocity);
607  (*it)->set_Radius(radius);
608  (*it)->compute_particle_mass(Species);
609  } //end for all particles
610  break;
611  }
612  } //end switch statement
613 
614  //fix particles, if data_FixedParticles!=0
615  if (data_FixedParticles) {
616  //std::cout << "fix " << min(data_FixedParticles,getParticleHandler().getNumberOfObjects()) << " Particles" << std::endl;
617  for (int i=0; i<std::min(data_FixedParticles,(int) particleHandler.getNumberOfObjects()); i++)
619  }
620 
621  //clean up tangential springs
623 
624  return true;
625 }
626 
627 
629 {
630  //This opens the file the data will be recalled from; note that data_filename needs to be set
631  std::fstream file;
632  file.open( data_filename.str().c_str() , std::fstream::in);
633 
634  //read first line and close file
635  std::string header_string;
636  getline(data_file,header_string);
637  std::stringstream header (std::stringstream::in | std::stringstream::out);
638  header << header_string;
639  file.close();
640 
641  //extract data from first line
642  Mdouble N, t, xmin, ymin, zmin, xmax, ymax, zmax;
643  header >> N >> t >> xmin >> ymin >> zmin >> xmax >> ymax >> zmax;
644 
645  //Set the correct formation based of dimension if the formation is not specified by the user
646  if (header.eof()) return 2;
647  else return 3;
648 }
649 
650 
655  std::stringstream restart_filename;
656  restart_filename.str("");
657  restart_filename << problem_name.str().c_str() << ".restart";
658 
660  if (options_restart==2) {
661  restart_filename << ".";
662  if (save_restart_data_counter<1000) restart_filename << "0";
663  if (save_restart_data_counter<100) restart_filename << "0";
664  if (save_restart_data_counter<10) restart_filename << "0";
665  restart_filename << save_restart_data_counter;
666  save_restart_data_counter++;
667  }
668 
669  std::ofstream restart_data(restart_filename.str().c_str());
670  restart_data.precision(8); //max. 16 for Mdouble precision
671  if( restart_data.good() )
672  {
673  write(restart_data);
674  restart_data.close();
675  } else {
676  std::cerr << "restart_data " << restart_filename.str() << " could not be saved" << std::endl;
677  exit(-1);
678  }
679 }
680 
686  std::stringstream restart_filename;
687  restart_filename.str("");
688  restart_filename << problem_name.str().c_str() << ".restart";
689  return load_restart_data(restart_filename.str());
690 }
691 
692 int MD::load_restart_data (std::string filename) {
693  std::ifstream restart_data(filename.c_str());
694  if( restart_data.good() )
695  {
696  read(restart_data);
697  restart_data.close();
698  set_restarted(true);
699  return(1);
700  } else {
701  std::cerr << "restart_data " << filename << " could not be loaded from " << filename << std::endl;
702  exit(-1);
703  }
704 }
705 
707 {
708  //std::cout<<"i="<<PI->get_Index()<<" j="<<PJ->get_Index()<<std::endl;
709  TangentialSpringParticle* TSParticleI=dynamic_cast<TangentialSpringParticle*>(PI);
710  TangentialSpringParticle* TSParticleJ=dynamic_cast<TangentialSpringParticle*>(PJ);
711 
712  //First check if particle I has a spring stores that is connected to particle J
713  CTangentialSpring* TangentialSpring = TSParticleI->get_TangentialSprings().select_particle_spring(PJreal->get_Index(), get_t(), get_dt());
714  if(TangentialSpring==NULL)
715  {
716  //Then check if particle J has a spring stored that is connected to particle I
717  TangentialSpring = TSParticleJ->get_TangentialSprings().select_particle_spring(PI->get_Index(), get_t(), get_dt());
718  if(TangentialSpring==NULL)
719  {
720  //A new spring has to be created, this is done in the real particle with the highest index
721  if(PI->get_Index()>PJreal->get_Index())
722  {
723  TangentialSpring = TSParticleI->get_TangentialSprings().create_new(PJreal->get_Index(), t, dt);
724  //std::cout<<"Created new spring in Particle "<<PI->get_Index()<<" between particle "<<PI->get_Index()<<" and "<<PJreal->get_Index()<<std::endl<<std::endl;
725  }
726  else
727  {
728  TangentialSpring = TSParticleJ->get_TangentialSprings().create_new(PI->get_Index(), t, dt);
729  //std::cout<<"Created new spring in Particle "<<PJ->get_Index()<<" between particle "<<PI->get_Index()<<" and "<<PJreal->get_Index()<<std::endl<<std::endl;
730  }
731  }
732  //else
733  //std::cout<<"i="<<PI->get_Index()<<" j="<<PJ->get_Index()<<" Reconnected to tangential spring in j"<<std::endl;
734  }
735  //else
736  //std::cout<<"i="<<PI->get_Index()<<" j="<<PJ->get_Index()<<" Reconnected to tangential spring in i"<<std::endl;
737  return TangentialSpring;
738 }
739 
740 
742 {
743  TangentialSpringParticle* TSParticle=dynamic_cast<TangentialSpringParticle*>(pI);
744  CTangentialSpring* TangentialSpring = TSParticle->get_TangentialSprings().select_wall_spring(w, get_t(), get_dt());
745 
746  if(TangentialSpring==NULL)
747  TangentialSpring = TSParticle->get_TangentialSprings().create_new_wall(w, t, dt);
748 
749  return TangentialSpring;
750 }
751 
752 
757 {
758  //this is because the rough bottom allows overlapping fixed particles
759  if (P1->isFixed()&&P2->isFixed()) return;
760 
765 
766  //Dificult cases for tangential springs in comination with periodic walls are:
767  //
768  // A new contact over a periodic wall:
769  // Starting situation: There are no tangential springs stored at all
770  // Creating periodic particles: There are no tangential springs so nothing happens
771  // Contact detection: There are two contacts detected, one (CA) for P1 with P2per and one (CB) for P2 with P1per
772  // Switch to the 4 cases:
773  // CA: PI=P1, PJ=P2per PJreal=P2
774  // CB: PI=P2, PJ=P1per PJreal=P1
775  // Reconnecting springs:
776  // 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)
777  // 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)
778  // 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)
779 
780  // Reconnect to a contact over a periodic wall:
781  // Starting situation: There is a tangential spring stored in the particle with the highest index, lets assume this is P1
782  // Creating periodic particles: P1 has a tangential spring, so P1per has a reversed copy of this spring
783  // Contact detection: There are two contacts detected, one (CA) for P1 with P2per and one (CB) for P2 with P1per
784  // Switch to the 4 cases:
785  // CA: PI=P1, PJ=P2per PJreal=P2
786  // CB: PI=P2, PJ=P1per PJreal=P1
787  // Reconnecting springs:
788  // CA: PI=P1 and PJ=P2per have a spring in P1, so we reconnect to this spring in the normal way and integrate it.
789  // 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.
790  // Removing periodic particles: The spring in P1per is removed
791 
792  //Cases (start from P1 and P2 and go to PI and PJ
793  //1 Normal-Normal ->PI=max(P1,P2), PJ=min(P1,P2)
794  //2 Periodic-Normal ->(PI=P2 PJ=real(P1))
795  //3 Normal-Periodic ->(PI=P1 PJ=real(P2))
796  //4 Periodic-Periodic ->do nothing
797 
798  //Just some statements to handle the 4 cases
799  BaseParticle *PI, *PJ, *PJreal;
800  bool isPeriodic;
803  if(P1Per==NULL)
804  {
805  if(P2Per==NULL)//N-N
806  if(P1->get_Index()<P2->get_Index())
807  {PI=P2;PJ=P1;PJreal=P1;isPeriodic=false;}
808  else
809  {PI=P1;PJ=P2;PJreal=P2;isPeriodic=false;}
810  else //N-P
811  {PI=P1;PJ=P2;PJreal=P2Per;isPeriodic=true;}
812  } else {
813  if(P2Per==NULL) //P-N
814  {PI=P2;PJ=P1;PJreal=P1Per;isPeriodic=true;}
815  else return;
816  }
817 
818 #ifdef DEBUG_OUTPUT
819  std::cerr << "In computing internal forces between particle "<<PI->get_Position()<<" and "<<PJ->get_Position()<<std::endl;
820 #endif
821 
822  //Get the square of the distance between particle i and particle j
823  Mdouble dist_squared=GetDistance2(PI->get_Position(), PJ->get_Position());
824  Mdouble interactionRadii_sum=PI->get_InteractionRadius()+PJ->get_InteractionRadius();
825 
826 #ifdef DEBUG_OUTPUT_FULL
827  std::cerr << "Square of distance between " << dist_squared << " square sum of radii " << radii_sum*radii_sum <<std::endl;
828 #endif
829 
830  // True if the particles are in contact
831  if (dist_squared<(interactionRadii_sum*interactionRadii_sum))
832  {
833  // For particles of the same species, set species vector to Species(PI);
834  // for particles of different species, set species vector to MixedSpecies(PI,PJ)
836 
837  // Calculate distance between the particles
838  Mdouble dist=sqrt(dist_squared);
839 
840  // Compute normal vector
841 
842  Vec3D normal=(PI->get_Position()-PJ->get_Position())/dist;
843 
844  // Compute the overlap between the particles
845  Mdouble radii_sum=PI->get_Radius()+PJ->get_Radius();
846  Mdouble deltan = std::max(0.0,radii_sum-dist);
847 
848  Vec3D force= Vec3D(0,0,0);;
849  Vec3D forcet; forcet.set_zero();
850  Vec3D forcerolling; forcerolling.set_zero();
851  Vec3D forcetorsion; forcetorsion.set_zero();
852  Mdouble fdotn = 0;
853  CTangentialSpring* TangentialSpring = NULL;
854 
855  //evaluate shortrange non-contact forces
856  if (pSpecies->AdhesionForceType!=None)
857  fdotn += computeShortRangeForceWithParticle(PI, PJ, PJreal, pSpecies, dist);
858 
859  if (deltan>0) //if contact forces
860  {
861 
862  // Compute the relative velocity vector v_ij
863  Vec3D vrel;
864  if (!pSpecies->mu) {
865  vrel=(PI->get_Velocity()-PJ->get_Velocity());
866  } else {
867  vrel=(PI->get_Velocity()-PJ->get_Velocity()) + Cross(normal, PI->get_AngularVelocity() * (PI->get_Radius() - .5 * deltan) + PJ->get_AngularVelocity() * (PJ->get_Radius() - .5 * deltan) );
868  }
869 
870  // Compute the projection of vrel onto the normal (can be negative)
871  Mdouble vdotn=-Dot(vrel,normal);
872 
873  //update restitution coeff
874  if (pSpecies->useRestitution) pSpecies->update_disp(PI->get_Mass(),PJ->get_Mass());
875  Mdouble a=0, R=0;
876 
877  // Compute normal force on particle i due to contact
878  if (pSpecies->get_ForceType()==HM||pSpecies->get_ForceType()==HMD)
879  {
880  //R is twice the effective radius
881  R = 2.0*PI->get_Radius()*PJ->get_Radius()/(PI->get_Radius()+PJ->get_Radius());
882  a = sqrt(R*deltan);
883  //pSpecies->k stores the elastic modulus
884  Mdouble kn = 4./3. * pSpecies->k * a;
885  fdotn += kn * deltan + pSpecies->disp*vdotn;
886  } else {
887  fdotn += pSpecies->k*deltan+pSpecies->disp*vdotn;
888  }
889  force += normal * fdotn;
890 
891  //If tangential forces are present
892  if (pSpecies->mu || pSpecies->murolling || pSpecies->mutorsion) {
893  //call tangential spring
894  if (pSpecies->kt || pSpecies->krolling || pSpecies->ktorsion)
895  TangentialSpring = getTangentialSpring(PI, PJ, PJreal);
896 
897  //Compute norm of normal force
898  Mdouble norm_fn = fabs(fdotn);
899 
900  //calculate sliding friction
901  if (pSpecies->mu) {
902  //Compute the tangential component of vrel
903  Vec3D vrelt=vrel+normal*vdotn;
904  //Compute norm of vrelt
905  Mdouble vdott=vrelt.GetLength();
906 
907  if (pSpecies->kt) {
908  Vec3D* delta = &(TangentialSpring->delta);
909 
910  //Integrate the spring
912  //(*delta) += vrelt * dt - Dot(*delta,normal)*normal;
913  Vec3D ddelta = (vrelt - Dot(*delta,PI->get_Velocity()-PJ->get_Velocity())*normal/dist) * get_dt();
914  (*delta) += ddelta;
915 
916  //Calculate test force including viscous force
917  if (pSpecies->get_ForceType()==HM) {
918  //pSpecies->kt stores the elastic shear modulus
919  Mdouble kt = 8. * pSpecies->kt * a;
920  TangentialSpring->SlidingForce += - kt * ddelta;
921  forcet = TangentialSpring->SlidingForce - pSpecies->dispt * vrelt;
922  } else if (pSpecies->get_ForceType()==HMD) {
923  //pSpecies->kt stores the elastic shear modulus
924  forcet = TangentialSpring->SlidingForce - pSpecies->dispt * vrelt;
925  Mdouble kt = 8. * pSpecies->kt * a * pow(1- GetLength(forcet)/pSpecies->mu/fdotn,0.33);
926  TangentialSpring->SlidingForce += - kt * ddelta;
927  forcet = TangentialSpring->SlidingForce - pSpecies->dispt * vrelt;
928  } else {
929  forcet = (-pSpecies->dispt) * vrelt - pSpecies->kt * (*delta);
930  }
931 
932  Mdouble forcet2 = forcet.GetLength2();
933 
934  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
935  //but the force is limited by Coulomb friction (sliding):
936  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
937  double muact=(TangentialSpring->sliding)?(pSpecies->mu):(pSpecies->mus); // select mu from previous sliding mode
938  if( forcet2 <= sqr(muact*norm_fn) ) {
939  //sticking++;
940  TangentialSpring->sliding=false;
941  } else {
942  //sliding++;
943  TangentialSpring->sliding=true;
945  Mdouble norm_forcet = sqrt(forcet2);
946  forcet *= pSpecies->mu * norm_fn / norm_forcet;
947  TangentialSpring->SlidingForce = forcet + pSpecies->dispt * vrelt;
948  (*delta) = TangentialSpring->SlidingForce/(-pSpecies->kt);
949  }
950 
951  //Add tangential force to total force
952  force += forcet;
953 
954  } else { //if no tangential spring
955  //tangential forces are modelled by a damper of viscosity dispt (sticking),
956  //but the force is limited by Coulomb friction (sliding):
957  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
958  if (vdott*pSpecies->dispt <= pSpecies->mus*norm_fn) { //sticking++;
959  forcet = -pSpecies->dispt * vrelt;
960  } else { //sliding++;
961  //set force to Coulomb limit
962  forcet = -(pSpecies->mu * norm_fn / vdott) * vrelt;
963  }
964  //Add tangential force to total force
965  force += forcet;
966  }
967  }
968 
969  //calculate rolling friction
970  if (pSpecies->murolling) {
971  //From Luding2008, objective rolling velocity (eq 15) w/o 2.0!
972  Mdouble reducedRadiusI = PI->get_Radius() - .5 * deltan;
973  Mdouble reducedRadiusJ = PJ->get_Radius() - .5 * deltan;
974  Mdouble reducedRadiusIJ = 2.0*reducedRadiusI*reducedRadiusJ/(reducedRadiusI+reducedRadiusJ);
975  Vec3D vrolling=-reducedRadiusIJ * Cross(normal, PI->get_AngularVelocity() - PJ->get_AngularVelocity());
976  if (pSpecies->krolling) {
977  Vec3D* RollingSpring = &(TangentialSpring->RollingSpring);
978 
979  //Integrate the spring
980  (*RollingSpring) += vrolling * get_dt();// - Dot(*RollingSpring,normal)*normal;
981 
982  //Calculate test force including viscous force
983  forcerolling = (-pSpecies->disprolling) * vrolling - pSpecies->krolling * (*RollingSpring);
984  Mdouble forcerolling2 = forcerolling.GetLength2();
985 
986  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
987  //but the force is limited by Coulomb friction (sliding):
988  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
989  double muact=(TangentialSpring->slidingRolling)?(pSpecies->murolling):(pSpecies->musrolling); // select mu from previous sliding mode
990  if( forcerolling2 <= sqr(muact*norm_fn) ) {
991  //sticking++;
992  TangentialSpring->slidingRolling=false;
993  } else {
994  //sliding++;
995  TangentialSpring->slidingRolling=true;
996  forcerolling *= pSpecies->murolling * norm_fn / sqrt(forcerolling2);
997  (*RollingSpring) = (forcerolling + pSpecies->disprolling * vrolling)/(-pSpecies->krolling);
998  }
999 
1000  //Add tangential force to torque
1001  Vec3D Torque = reducedRadiusIJ * Cross(normal, forcerolling);
1002  PI->add_Torque(Torque);
1003  PJreal->add_Torque(-Torque);
1004  }
1005  }
1006 
1007 
1008  //calculate torsive friction
1009  if (pSpecies->mutorsion) {
1010  //From Luding2008, spin velocity (eq 16) w/o 2.0!
1011  Mdouble RadiusIJ = 2.0*PI->get_Radius()*PJ->get_Radius()/(PI->get_Radius()+PJ->get_Radius());
1012  Vec3D vtorsion=RadiusIJ*Dot(normal,PI->get_AngularVelocity() - PJ->get_AngularVelocity())*normal;
1013  if (pSpecies->ktorsion) {
1014  //~ std::cout << "Error; not yet implemented" << std::endl;
1015  //~ exit(-1);
1016  Vec3D* TorsionSpring = &(TangentialSpring->TorsionSpring);
1017 
1018  //Integrate the spring
1019  (*TorsionSpring) = Dot((*TorsionSpring) + vtorsion * get_dt(),normal)*normal;
1020 
1021  //Calculate test force including viscous force
1022  forcetorsion = (-pSpecies->disptorsion) * vtorsion - pSpecies->ktorsion * (*TorsionSpring);
1023  Mdouble forcetorsion2 = forcetorsion.GetLength2();
1024 
1025  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
1026  //but the force is limited by Coulomb friction (sliding):
1027  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1028  double muact=(TangentialSpring->slidingTorsion)?(pSpecies->mutorsion):(pSpecies->mustorsion); // select mu from previous sliding mode
1029  if( forcetorsion2 <= sqr(muact*norm_fn) ) {
1030  //sticking++;
1031  TangentialSpring->slidingTorsion=false;
1032  } else {
1033  //sliding++;
1034  TangentialSpring->slidingTorsion=true;
1035  //~ std::cout << "sliding " << std::endl;
1036  forcetorsion *= pSpecies->mutorsion * norm_fn / sqrt(forcetorsion2);
1037  (*TorsionSpring) = (forcetorsion + pSpecies->disptorsion * vtorsion)/(-pSpecies->ktorsion);
1038  }
1039 
1040  //Add tangential force to torque
1041  Vec3D torque = RadiusIJ * forcetorsion;
1042  PI->add_Torque(torque);
1043  PJreal->add_Torque(-torque);
1044 
1045  }
1046  }
1047  } //end if tangential forces
1048 
1050  //Make force Hertzian (note: deltan is normalized by the normal distanct of two particles in contact, as in Silbert)
1051  if (pSpecies->get_ForceType()==Hertzian) force *= sqrt(deltan/(PI->get_Radius()+PJ->get_Radius()));
1052 
1053  } else {//end if contact forces
1054  force += fdotn*normal;
1055  }
1056 
1057  //Add forces to total force
1058  PI->add_Force(force);
1059  if(!isPeriodic)
1060  PJreal->add_Force(-force);
1061 
1062  // Add torque due to tangential forces: t = Cross(l,f), l=dist*Wall.normal
1063  if (pSpecies->mu) {
1064  Vec3D cross = Cross(normal, force);
1065  PI ->add_Torque(-cross * (PI->get_Radius() - .5 * deltan));
1066  if(!isPeriodic)
1067  PJreal->add_Torque(-cross * (PJ->get_Radius() - .5 * deltan));
1068  }
1069 
1070  // output for ene and stat files:
1071  if (get_save_data_ene()) {
1072  if(!isPeriodic)
1073  add_ene_ela(0.5 * (pSpecies->k * sqr(deltan) + (TangentialSpring?
1074  (pSpecies->kt * TangentialSpring->delta.GetLength2()
1075  +pSpecies->krolling * TangentialSpring->RollingSpring.GetLength2()
1076  +pSpecies->ktorsion * TangentialSpring->TorsionSpring.GetLength2()):0.0)));
1077  else
1078  add_ene_ela(0.25* (pSpecies->k * sqr(deltan) + (TangentialSpring?
1079  (pSpecies->kt * TangentialSpring->delta.GetLength2()
1080  +pSpecies->krolling * TangentialSpring->RollingSpring.GetLength2()
1081  +pSpecies->ktorsion * TangentialSpring->TorsionSpring.GetLength2()):0.0)));
1082  }
1084 
1085  Mdouble fdott = forcet.GetLength();
1086  Mdouble deltat_norm = TangentialSpring?(-TangentialSpring->delta.GetLength()):0.0;
1087 
1090  Vec3D centre = 0.5 * (PI->get_Position() + PJ->get_Position());
1091 
1095 
1096  if (!PI->isFixed())
1097  {
1098  if(get_save_data_stat()||get_do_stat_always()) gather_statistics_collision(PJreal->get_Index(),PI->get_Index(), centre, deltan, deltat_norm,fdotn,fdott,-normal,-(fdott?forcet/fdott:forcet));
1100  << get_t() << " "
1101  << PJreal->get_Index() << " "
1102  << PI->get_Index() << " "
1103  << centre << " "
1104  << radii_sum-dist << " "
1105  << deltat_norm << " "
1106  << fdotn << " "
1107  << fdott << " "
1108  << -normal << " "
1109  << -(fdott?forcet/fdott:forcet) << std::endl;
1110  }
1111  if (!PJreal->isFixed()&&!isPeriodic)
1112  {
1113  if(get_save_data_stat()||get_do_stat_always()) gather_statistics_collision(PI->get_Index(),PJreal->get_Index(), centre, deltan, deltat_norm,fdotn,fdott,normal,(fdott?forcet/fdott:forcet));
1115  << get_t() << " "
1116  << PI->get_Index() << " "
1117  << PJreal->get_Index() << " "
1118  << centre << " "
1119  << radii_sum-dist << " "
1120  << deltat_norm << " "
1121  << fdotn << " "
1122  << fdott << " "
1123  << normal << " "
1124  << (fdott?forcet/fdott:forcet) << std::endl;
1125  }
1126  }
1127 #ifdef FOLLOWPARTICLE
1128  if(PI->get_Index()==FPID||PJ->get_Index()==FPID)
1129  std::cout<<"Particle collission at time="<<get_t()<<" between "<<PI->get_Index()<<" and "<<PJ->get_Index()<<std::endl;
1130 #endif
1131 
1132  } // end if particle i and j are overlapping
1133 }
1134 
1135 
1140 {
1141  //this is because the rough bottom allows overlapping fixed particles
1142  if (P1->isFixed()&&P2->isFixed()) return;
1143 
1147 
1148  //Cases (start from P1 and P2 and go to PI and PJ
1149  //1 Normal-Normal ->PI=max(P1,P2), PJ=min(P1,P2)
1150  //2 Periodic-Normal ->if(P2>Real(P1)) (PI=P2 PJ=real(P1)) otherwise do nothing
1151  //3 Normal-Periodic ->if(P1>Real(P2)) (PI=P1 PJ=real(P2)) otherwise do nothing
1152  //4 Periodic-Periodic ->do nothing
1153 
1154  //Just some statements to handle the 4 cases
1155  BaseParticle *PI, *PJ,*PJreal;
1158  if(P1Per==NULL)
1159  {
1160  if(P2Per==NULL)
1161  //N-N
1162  if(P1->get_Index()<P2->get_Index())
1163  {PI=P2;PJ=P1;PJreal=PJ;}
1164  else
1165  {PI=P1;PJ=P2;PJreal=PJ;}
1166  else
1167  //N-P
1168  if(P1->get_Index()>P2Per->get_Index())
1169  {PI=P1;PJ=P2;PJreal=P2Per;}
1170  else return;
1171  } else {
1172  if(P2Per==NULL)
1173  //P-N
1174  if(P2->get_Index()>P1Per->get_Index())
1175  {PI=P2;PJ=P1;PJreal=P1Per;}
1176  else return;
1177  else return;
1178  }
1179 
1180  #ifdef DEBUG_OUTPUT
1181  std::cerr << "In computing interal forces between particle "<<PI->get_Position()<<" and "<<PJ->get_Position()<<std::endl;
1182  #endif
1183 
1184 
1185  //Get the square of the distance between particle i and particle j
1186  Mdouble dist_squared=GetDistance2(PI->get_Position(), PJ->get_Position());
1187  Mdouble interactionRadii_sum=PI->get_InteractionRadius()+PJ->get_InteractionRadius();
1188 
1189  #ifdef DEBUG_OUTPUT_FULL
1190  std::cerr << "Square of distance between " << dist_squared << " square sum of radii " << radii_sum*radii_sum <<std::endl;
1191  #endif
1192 
1193  // True if the particles are in contact
1194  if (dist_squared<(interactionRadii_sum*interactionRadii_sum))
1195  {
1196  // For particles of the same species, set species vector to Species(PI);
1197  // for particles of different species, set species vector to MixedSpecies(PI,PJ)
1199 
1200  // Calculate distance between the particles
1201  Mdouble dist=sqrt(dist_squared);
1202 
1203  // Compute normal vector
1204  Vec3D normal=(PI->get_Position()-PJ->get_Position())/dist;
1205 
1206  // Compute the overlap between the particles
1207  Mdouble radii_sum=PI->get_Radius()+PJ->get_Radius();
1208  Mdouble deltan = std::max(0.0,radii_sum-dist);
1209 
1210  Vec3D force= Vec3D(0,0,0);;
1211  Vec3D forcet; forcet.set_zero();
1212  Vec3D deltat; deltat.set_zero();
1213  Mdouble fdotn = 0;
1214 
1215  //evaluate shortrange non-contact forces
1216  if (pSpecies->AdhesionForceType!=None)
1217  fdotn += computeShortRangeForceWithParticle(PI, PJ, PJreal, pSpecies, dist);
1218 
1219  if (deltan>0) //if contact forces
1220  {
1221 
1222  // Compute the relative velocity vector v_ij
1223  Vec3D vrel;
1224  if (!pSpecies->mu) {
1225  vrel=(PI->get_Velocity()-PJ->get_Velocity());
1226  } else {
1227  vrel=(PI->get_Velocity()-PJ->get_Velocity()) + Cross(normal, PI->get_AngularVelocity() * (PI->get_Radius() - .5 * deltan) + PJ->get_AngularVelocity() * (PJ->get_Radius() - .5 * deltan) );
1228  }
1229 
1231  // BEGIN add viscous normal force
1232 
1233  // Compute the projection of vrel onto the normal (can be negative)
1234  Mdouble vdotn=-Dot(vrel,normal);
1235 
1236  // Compute normal force on particle i due to contact
1237  if (pSpecies->useRestitution) pSpecies->update_disp(PI->get_Mass(),PJ->get_Mass());
1238  fdotn += pSpecies->disp*vdotn;
1239 
1240  // END add viscous normal force
1241 
1242 
1243  // BEGIN add elastic force
1244 
1245  //calculate deltastar, the overlap above which k2max becomes active (the 'fluid branch')
1246  Mdouble deltastar = (pSpecies->k2max/(pSpecies->k2max-pSpecies->k))*pSpecies->depth*((2*PI->get_Radius()*PJ->get_Radius())/(PI->get_Radius()+PJ->get_Radius()));
1247  //2*depth*r_eff is the overlap at which fn=0 on the k2max branch
1248  //deltastar is the overlap at which the k1 and the k2max branch meet
1249 
1250  //retrieve history parameter deltamax, the max. achieved overlap
1251  DeltaMaxsParticle* DMParticle=dynamic_cast<DeltaMaxsParticle*>(PI);
1252  Mdouble *deltamax = DMParticle->get_DeltaMaxs().select_particle(PJreal->get_Index(), t, dt);
1253  //update deltastar
1254  *deltamax = std::min(deltastar,std::max(*deltamax,deltan));
1255 
1256  //calculate k2(deltamax) (only use first case for Walton-Braun spring)
1257  Mdouble k2;
1258  if (deltan>deltastar) {
1259  k2 = pSpecies->k2max;
1260  } else {
1261  k2 = pSpecies->k+(pSpecies->k2max-pSpecies->k)*((*deltamax)/deltastar);
1262  }
1263 
1264  //calculate delta0(deltamax), the overlap where the force is zero
1265  Mdouble delta0 = (k2-pSpecies->k)/k2*(*deltamax);
1266 
1267  //add elastic force
1268  //std::cout << k2*(deltan-(delta0))-pSpecies->k*deltan << std::endl;
1269  if (deltan>deltastar) {
1270  fdotn += pSpecies->k2max*(deltan-(delta0));
1271  } else if (k2*(deltan-(delta0))>=pSpecies->k*deltan){
1272  fdotn += pSpecies->k*deltan;
1273  } else if (k2*(deltan-delta0)>=-pSpecies->kc*deltan){
1274  fdotn += k2*(deltan-delta0);
1275  } else {
1276  fdotn += -pSpecies->kc*deltan;
1277  *deltamax=(k2+pSpecies->kc)/(k2-pSpecies->k)*deltan;
1278  }
1279 
1280  force = normal * fdotn;
1281  // END add elastic force
1282 
1283 
1284  //If tangential forces are present
1285  if (pSpecies->mu) {
1286 
1287  //Compute the tangential component of vrel
1288  Vec3D vrelt=vrel+normal*vdotn;
1289 
1290  //Compute norm of vrelt
1291  Mdouble vdott=vrelt.GetLength();
1292 
1293  //Compute norm of normal force
1294  Mdouble norm_fn = fabs(fdotn);
1295 
1296  if (!pSpecies->kt) { //if no tangential spring
1297  //tangential forces are modelled by a damper of viscosity dispt (sticking),
1298  //but the force is limited by Coulomb friction (sliding):
1299  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1300  if (vdott*pSpecies->dispt <= pSpecies->mus*norm_fn) { //sticking++;
1301  forcet = -pSpecies->dispt * vrelt;
1302  } else { //sliding++;
1303  //set force to Coulomb limit
1304  forcet = -(pSpecies->mu * norm_fn / vdott) * vrelt;
1305  }
1306 
1307  } else { //if with tangential spring
1308  //Retrieve the spring
1309  CTangentialSpring* TangentialSpring = getTangentialSpring(PI, PJ, PJreal);
1310  Vec3D* delta = &(TangentialSpring->delta);
1311 
1312  //Integrate the spring
1314  //(*delta) += vrelt * dt - Dot(*delta,normal)*normal;
1315  (*delta) += (vrelt - Dot(*delta,PI->get_Velocity()-PJ->get_Velocity())*normal/dist) * dt;
1316  deltat = (*delta);
1317 
1318  //Calculate test force including viscous force
1319  forcet = (-pSpecies->dispt) * vrelt - pSpecies->kt * deltat;
1320  Mdouble forcet2 = forcet.GetLength2();
1321 
1322  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
1323  //but the force is limited by Coulomb friction (sliding):
1324  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1325  if( forcet2 <= sqr(pSpecies->mus*norm_fn) ) {
1326  //sticking++;
1327  } else {
1328  //sliding++;
1329  Mdouble norm_forcet = sqrt(forcet2);
1330  forcet *= pSpecies->mu * norm_fn / norm_forcet;
1332  (*delta) = -(forcet + pSpecies->dispt * vrelt)/pSpecies->kt;
1333  //This line should be removed before release it is the old tangential model (the new is shown to be better).
1334  //(*delta) = forcet/(-pSpecies->kt);
1335  }
1336  } //end if tangential spring
1337 
1338  //Add tangential force to total force
1339  force += forcet;
1340 
1341  } //end if tangential forces
1342  } else {//end if contact forces
1343  force = fdotn*normal;
1344  }
1345 
1346  //Make force Hertzian (note: deltan is normalized by the normal distanct of two particles in contact, as in Silbert)
1347  if (pSpecies->get_ForceType()==Hertzian) force *= sqrt(deltan/(PI->get_Radius()+PJ->get_Radius()));
1348 
1349  PI ->add_Force( force);
1350  PJreal->add_Force(-force);
1351 
1352  // Add torque due to tangential forces: t = Cross(l,f), l=dist*Wall.normal
1353  if (pSpecies->mu) {
1354  Vec3D cross = -Cross(normal, force);
1355  PI ->add_Torque(cross * (PI->get_Radius() - .5 * deltan));
1356  PJreal->add_Torque(cross * (PI->get_Radius() - .5 * deltan));
1357  }
1358 
1359  // output for ene and stat files:
1360  if (save_data_ene) {
1361  ene_ela += 0.5 * (pSpecies->k * sqr(deltan) + pSpecies->kt * deltat.GetLength2());
1362  }
1364  Mdouble fdott = forcet.GetLength();
1365  Mdouble deltat_norm = -deltat.GetLength();
1366 
1367  Vec3D centre = 0.5 * (PI->get_Position() + PJ->get_Position());
1370 
1371  if (!PI->isFixed())
1372  {
1373  if(save_data_stat||do_stat_always) gather_statistics_collision(PJreal->get_Index(),PI->get_Index(), centre, deltan, deltat_norm,fdotn,fdott,-normal,-(fdott?forcet/fdott:forcet));
1375  << t << " "
1376  << PJreal->get_Index() << " "
1377  << PI->get_Index() << " "
1378  << centre << " "
1379  << radii_sum-dist << " "
1380  << deltat_norm << " "
1381  << fdotn << " "
1382  << fdott << " "
1383  << -normal << " "
1384  << -(fdott?forcet/fdott:forcet) << std::endl;
1385  }
1386  if (!PJreal->isFixed())
1387  {
1388  if(save_data_stat||do_stat_always) gather_statistics_collision(PI->get_Index(),PJreal->get_Index(), centre, deltan, deltat_norm,fdotn,fdott,normal,(fdott?forcet/fdott:forcet));
1390  << t << " "
1391  << PI->get_Index() << " "
1392  << PJreal->get_Index() << " "
1393  << centre << " "
1394  << radii_sum-dist << " "
1395  << deltat_norm << " "
1396  << fdotn << " "
1397  << fdott << " "
1398  << normal << " "
1399  << (fdott?forcet/fdott:forcet) << std::endl;
1400  }
1401  }
1402  }
1403 
1404  } // end if particle i and j are overlapping
1405 }
1406 
1411 {
1412  if (!CI->isFixed()) {
1414  CI->add_Force(get_gravity() * CI->get_Mass());
1416  compute_walls(CI);
1417  }
1418 }
1419 
1424 {
1425  //No need to compute interactions between periodic particle images and walls
1426  if(pI->get_PeriodicFromParticle()!=NULL)
1427  return;
1428 
1429  for (unsigned int i=0; i<wallHandler.getNumberOfWalls(); i++)
1430  {
1431 
1432  // note: normal points away from particle i
1433  Vec3D normal;
1434  Mdouble dist;
1435  bool touch = wallHandler.getWall(i)->get_distance_and_normal(*pI, dist, normal);
1436 
1437  //If the wall is being touched (I think :Ant)
1438  if (touch)
1439  {
1440 
1442 
1443  Mdouble deltan = std::max(0.0,pI->get_Radius()-dist);
1444 
1445  Vec3D force= Vec3D(0,0,0);;
1446  Vec3D forcet; forcet.set_zero();
1447  Vec3D forcerolling; forcerolling.set_zero();
1448  Vec3D forcetorsion; forcetorsion.set_zero();
1449  Mdouble fdotn = 0;
1450  CTangentialSpring* TangentialSpring = NULL;
1451 
1452  //evaluate shortrange non-contact forces
1453  if (pSpecies->AdhesionForceType!=None)
1454  fdotn += computeShortRangeForceWithWall(pI, i, pSpecies, dist);
1455 
1456  if (deltan>0) //if contact forces
1457  {
1458 
1459 
1460  // Compute the relative velocity vector v_ij
1461  Vec3D vrel;
1462  if (!pSpecies->mu) {
1463  vrel = pI->get_Velocity() - wallHandler.getWall(i)->get_Velocity();
1464  } else {
1465  vrel = pI->get_Velocity() - wallHandler.getWall(i)->get_Velocity() - Cross(normal, pI->get_AngularVelocity()) * dist;
1466  }
1467 
1468  // Compute the projection of vrel onto the normal (can be negative)
1469  Mdouble vdotn = -Dot(vrel, normal);
1470 
1471  //possibly update restitution coefficient
1472  if (pSpecies->useRestitution) pSpecies->update_disp(pI->get_Mass(),1e20);
1473 
1474  // Compute normal force on particle i due to contact
1475  Mdouble a=0, R=0;
1476  if (pSpecies->get_ForceType()==HM||pSpecies->get_ForceType()==HMD) {
1477  //R is twice the effective radius
1478  R = pI->get_Radius();
1479  a = sqrt(deltan*R);
1480  //pSpecies->k stores the elastic modulus
1481  Mdouble kn = 4./3. * pSpecies->k * a; //it's not really kn
1482  fdotn += kn*deltan - 2*pSpecies->disp*sqrt(pI->get_Mass()*2.*pSpecies->k * a)*vdotn;
1483  } else {
1484  fdotn += pSpecies->k*deltan - pSpecies->disp*vdotn;
1485  }
1486  force = normal * (-fdotn);
1487 
1488  //If tangential forces are present
1489  if (pSpecies->mu || pSpecies->murolling || pSpecies->mutorsion) {
1490  //call tangential spring
1491  if (pSpecies->kt || pSpecies->krolling || pSpecies->ktorsion)
1492  TangentialSpring = getTangentialSpringWall(pI, i);
1493 
1494  //Compute norm of normal force
1495  Mdouble norm_fn = fabs(fdotn);
1496 
1497  //calculate sliding friction
1498  if (pSpecies->mu) {
1499  //Compute the tangential component of vrel
1500  Vec3D vrelt=vrel+normal*vdotn;
1501  //Compute norm of vrelt
1502  Mdouble vdott=vrelt.GetLength();
1503 
1504  if (pSpecies->kt) {
1505  Vec3D* delta = &(TangentialSpring->delta);
1506 
1507  //Integrate the spring
1508  (*delta) += vrelt * get_dt(); //no correction because the normal direction is constant
1509  //std::cout << (vrel) << std::endl;
1510  //Calculate test force including viscous force
1511  if (pSpecies->get_ForceType()==HM) {
1512  //pSpecies->kt stores the elastic shear modulus
1513  Mdouble kt = 8. * pSpecies->kt * a;
1514  //std::cout << "kt" << kt << std::endl;
1515  TangentialSpring->SlidingForce += - kt * (vrelt * get_dt());
1516  a = sqrt(deltan*R);
1517  forcet = TangentialSpring->SlidingForce - 2*pSpecies->dispt * sqrt(pI->get_Mass()*kt) * vrelt;
1518  } else if (pSpecies->get_ForceType()==HMD) {
1519  //pSpecies->kt stores the elastic shear modulus
1520  forcet = TangentialSpring->SlidingForce - pSpecies->dispt * vrelt;
1521  Mdouble kt;
1522  if (get_t()<0.034/10) {
1523  // loading
1524  kt = 8. * pSpecies->kt * a * pow(1.001- GetLength(forcet)/pSpecies->mus/fdotn,1./3.);
1525  } else if (Dot(vrelt,forcet)<=0) {
1526  //unloading in opposite direction
1527  kt = 8. * pSpecies->kt * a * pow(.501 - .5 * GetLength(forcet)/pSpecies->mus/fdotn,1./3.);
1528  } else {
1529  //unloading
1530  kt = 8. * pSpecies->kt * a * pow(.501 + .5* GetLength(forcet)/pSpecies->mus/fdotn,1./3.);
1531  }
1532  TangentialSpring->SlidingForce += - kt * (vrelt * get_dt());
1533  forcet = TangentialSpring->SlidingForce - pSpecies->dispt * vrelt;
1534  } else {
1535  forcet = (-pSpecies->dispt) * vrelt - pSpecies->kt * (*delta);
1536  }
1537 
1538  Mdouble forcet2 = forcet.GetLength2();
1539 
1540  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
1541  //but the force is limited by Coulomb friction (sliding):
1542  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1543  double muact=(TangentialSpring->sliding)?(pSpecies->mu):(pSpecies->mus); // select mu from previous sliding mode
1544  if( forcet2 <= sqr(muact*norm_fn) ) {
1545  //sticking++;
1546  TangentialSpring->sliding=false;
1547  } else {
1548  //sliding++;
1549  TangentialSpring->sliding=true;
1550  Mdouble norm_forcet = sqrt(forcet2);
1551  forcet *= pSpecies->mu * norm_fn / norm_forcet;
1552  TangentialSpring->SlidingForce = forcet + pSpecies->dispt * vrelt;
1553  (*delta) = TangentialSpring->SlidingForce/(-pSpecies->kt);
1554  }
1555 
1556  //Add tangential force to total force
1557  force += forcet;
1558 
1559  } else { //if no tangential spring
1560  //tangential forces are modelled by a damper of viscosity dispt (sticking),
1561  //but the force is limited by Coulomb friction (sliding):
1562  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1563  if (vdott*pSpecies->dispt <= pSpecies->mus*norm_fn) { //sticking++;
1564  forcet = -pSpecies->dispt * vrelt;
1565  } else { //sliding++;
1566  //set force to Coulomb limit
1567  forcet = -(pSpecies->mu * norm_fn / vdott) * vrelt;
1568  //std::cout << "sliding " << std::endl;
1569  }
1570  //Add tangential force to total force
1571  force += forcet;
1572  }
1573  }
1574 
1575  //calculate rolling friction
1576  if (pSpecies->murolling) {
1577  //From Luding2008, objective rolling velocity (eq 15) w/o 2.0!
1578  Mdouble reducedRadiusI = pI->get_Radius() - .5 * deltan;
1580  Mdouble reducedRadiusIJ = reducedRadiusI;
1581  Vec3D vrolling=-reducedRadiusIJ * Cross(normal, pI->get_AngularVelocity());
1582  if (pSpecies->krolling) {
1583  Vec3D* RollingSpring = &(TangentialSpring->RollingSpring);
1584 
1585  //Integrate the spring
1586  (*RollingSpring) += vrolling * get_dt();// - Dot(*RollingSpring,normal)*normal;
1587 
1588  //Calculate test force including viscous force
1589  forcerolling = (-pSpecies->disprolling) * vrolling - pSpecies->krolling * (*RollingSpring);
1590  Mdouble forcerolling2 = forcerolling.GetLength2();
1591 
1592  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
1593  //but the force is limited by Coulomb friction (sliding):
1594  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1595  double muact=(TangentialSpring->slidingRolling)?(pSpecies->murolling):(pSpecies->musrolling); // select mu from previous sliding mode
1596  if( forcerolling2 <= sqr(muact*norm_fn) ) {
1597  TangentialSpring->slidingRolling=false;
1598  } else {
1599  TangentialSpring->slidingRolling=true;
1600  forcerolling *= pSpecies->murolling * norm_fn / sqrt(forcerolling2);
1601  (*RollingSpring) = (forcerolling + pSpecies->disprolling * vrolling)/(-pSpecies->krolling);
1602  }
1603 
1604  //Add tangential force to torque
1605  Vec3D Torque = reducedRadiusIJ * Cross(normal, forcerolling);
1606  pI->add_Torque(Torque);
1607  wallHandler.getWall(i)->add_Torque(Torque);
1608 
1609  }
1610  }
1611 
1612  //calculate torsive friction
1613  if (pSpecies->mutorsion) {
1614  //From Luding2008, spin velocity (eq 16) w/o 2.0!
1616  Mdouble RadiusIJ = pI->get_Radius();
1617  Vec3D vtorsion=RadiusIJ*Dot(normal,pI->get_AngularVelocity())*normal;
1618  if (pSpecies->ktorsion) {
1619  //~ std::cout << "Error; not yet implemented" << std::endl;
1620  //~ exit(-1);
1621  Vec3D* TorsionSpring = &(TangentialSpring->TorsionSpring);
1622 
1623  //Integrate the spring
1624  (*TorsionSpring) = Dot((*TorsionSpring) + vtorsion * get_dt(),normal)*normal;
1625 
1626  //Calculate test force including viscous force
1627  forcetorsion = (-pSpecies->disptorsion) * vtorsion - pSpecies->ktorsion * (*TorsionSpring);
1628  Mdouble forcetorsion2 = forcetorsion.GetLength2();
1629 
1630  //tangential forces are modelled by a spring-damper of elastisity kt and viscosity dispt (sticking),
1631  //but the force is limited by Coulomb friction (sliding):
1632  //f_t = -dispt*vrelt, if dispt*vrelt<=mu_s*fdotn, f_t=mu+s*fdotn*t, else
1633  double muact=(TangentialSpring->slidingTorsion)?(pSpecies->mutorsion):(pSpecies->mustorsion); // select mu from previous
1634  if( forcetorsion2 <= sqr(muact*norm_fn) ) {
1635  //sticking++;
1636  TangentialSpring->slidingTorsion=false;
1637  } else {
1638  //sliding++;
1639  TangentialSpring->slidingTorsion=true;
1640  // std::cout << "torsion sliding " << std::endl;
1641  forcetorsion *= pSpecies->mutorsion * norm_fn / sqrt(forcetorsion2);
1642  (*TorsionSpring) = (forcetorsion + pSpecies->disptorsion * vtorsion)/(-pSpecies->ktorsion);
1643  }
1644 
1645  //Add tangential force to torque
1646  Vec3D Torque = RadiusIJ * forcetorsion;
1647 
1648  if (pSpecies->get_ForceType()==HM||pSpecies->get_ForceType()==HMD) {
1649  //R is twice the effective radius
1650  R = pI->get_Radius();
1651  a = sqrt(deltan*R);
1652  Torque = 20 * a * forcetorsion;
1653  }
1654 
1655  pI->add_Torque(Torque);
1656  wallHandler.getWall(i)->add_Torque(Torque);
1657  //std::cout << " " << Torque.Z << std::endl;
1658  }
1659  }
1660 
1661  } //end if tangential forces
1662  } else {//end if contact forces
1663  force += (-fdotn)*normal;
1664  }
1665 
1666  //Make force Hertzian (note: deltan is normalized by the normal distanct of two particles in contact, as in Silbert)
1667  if (pSpecies->get_ForceType()==Hertzian) force *= sqrt(deltan/(2.0*pI->get_Radius()));
1668 
1669  //Add forces to total force
1670  pI->add_Force(force);
1671  wallHandler.getWall(i)->add_Force(-force);
1672 
1673  if (pSpecies->mu) pI->set_Torque(pI->get_Torque()+Cross(normal, force) * dist);
1674  // Add torque due to tangential forces: t = Cross(l,f), l=dist*Wall.normal
1675 
1676  if (get_save_data_ene()) {
1677  add_ene_ela(0.5 * (pSpecies->k * sqr(deltan) + (TangentialSpring?
1678  (pSpecies->kt * TangentialSpring->delta.GetLength2()
1679  +pSpecies->krolling * TangentialSpring->RollingSpring.GetLength2()
1680  +pSpecies->ktorsion * TangentialSpring->TorsionSpring.GetLength2()):0.0)));
1681  }
1683  {
1684 
1685  deltan = pI->get_Radius()-dist;
1686  Mdouble fdott = forcet.GetLength();
1687  Mdouble deltat_norm = TangentialSpring?(-TangentialSpring->delta.GetLength()):0.0;
1688 
1689  if (!pI->isFixed())
1690  {
1691  if(get_save_data_stat()||get_do_stat_always()) gather_statistics_collision(pI->get_Index(),-(i+1), pI->get_Position() + normal*(pI->get_Radius()-deltan), deltan, deltat_norm,fdotn,fdott,normal,-(fdott?forcet/fdott:forcet));
1693  << get_t() << " "
1694  << pI->get_Index() << " "
1695  << -(static_cast<int>(i)+1) << " "
1696  << pI->get_Position() + normal*(pI->get_Radius()-deltan) << " "
1697  << deltan << " "
1698  << deltat_norm << " "
1699  << fdotn << " "
1700  << fdott << " "
1701  << normal << " "
1702  << -(fdott?forcet/fdott:forcet) << std::endl;
1703  }
1704  }
1705 
1706  } // end if particle i touches the wall
1707 
1708  }//end if for wall i
1709 }
1710 
1712  Mdouble fdotn;
1713  if (pSpecies->AdhesionForceType==LinearReversible)
1714  {
1715  fdotn = std::min(0.0,pSpecies->k0*std::max(dist-PI->get_Radius()-PJ->get_Radius(),0.0)-pSpecies->f0);
1716  }
1717  else if (pSpecies->AdhesionForceType==LinearIrreversible)
1718  {
1719  TangentialSpringParticle* TSParticleI=dynamic_cast<TangentialSpringParticle*>(PI);
1720  TangentialSpringParticle* TSParticleJ=dynamic_cast<TangentialSpringParticle*>(PJ);
1721  //First check if particle I has a spring stores that is connected to particle J
1722  CTangentialSpring* TangentialSpring = TSParticleI->get_TangentialSprings().select_particle_spring(PJreal->get_Index(), get_t(), get_dt());
1723  if(TangentialSpring==NULL)
1724  {
1725  //Then check if particle J has a spring stored that is connected to particle I
1726  TangentialSpring = TSParticleJ->get_TangentialSprings().select_particle_spring(PI->get_Index(), get_t(), get_dt());
1727  }
1728  if(TangentialSpring==NULL)
1729  {
1730  fdotn = (PI->get_Radius()+PJ->get_Radius()>dist)?-pSpecies->f0:0.0;
1731  }
1732  else
1733  {
1734  fdotn = std::min(0.0,pSpecies->k0*std::max(dist-PI->get_Radius()-PJ->get_Radius(),0.0)-pSpecies->f0);
1735  }
1736  }
1737  else
1738  {
1739  fdotn=0;
1740  }
1741  return fdotn;
1742 }
1743 
1745  Mdouble fdotn;
1746  if (pSpecies->AdhesionForceType==LinearReversible)
1747  {
1748  fdotn = std::min(0.0,pSpecies->k0*std::max(dist-pI->get_Radius(),0.0)-pSpecies->f0);
1749  }
1750  else if (pSpecies->AdhesionForceType==LinearIrreversible)
1751  {
1752  TangentialSpringParticle* TSParticle=dynamic_cast<TangentialSpringParticle*>(pI);
1753  CTangentialSpring* TangentialSpring = TSParticle->get_TangentialSprings().select_wall_spring(wall, get_t(), get_dt());
1754  if(TangentialSpring==NULL)
1755  {
1756  fdotn = (pI->get_Radius()>dist)?-pSpecies->f0:0.0;
1757  }
1758  else
1759  {
1760  fdotn = std::min(0.0,pSpecies->k0*std::max(dist-pI->get_Radius(),0.0)-pSpecies->f0);
1761  }
1762  }
1763  else
1764  {
1765  fdotn=0;
1766  }
1767  return fdotn;
1768 }
1769 
1774 {
1775 #ifdef USE_SIMPLE_VERLET_INTEGRATION
1776 
1777 #else //use velocity verlet
1778  iP->accelerate(iP->get_Force()*iP->get_InvMass()*0.5*dt);
1779  iP->set_Displacement(iP->get_Velocity()*dt);
1780  iP->move(iP->get_Displacement());
1782  if (rotation)
1783  {
1784  iP->angularAccelerate(iP->get_Torque()*iP->get_InvInertia()*0.5*dt);
1785  iP->rotate(iP->get_AngularVelocity()*dt);
1786  }
1787 #endif
1788 #ifdef FOLLOWPARTICLE
1789  if(iP->get_Index()==FPID)
1790  std::cout<<"In integration before time="<<get_t()<<", particle "<<FPID<<": "<<*iP<<std::endl;
1791 #endif
1792 }
1793 
1795 {
1796  for(std::vector<BaseBoundary*>::iterator B = boundaryHandler.begin(); B!=boundaryHandler.end(); ++B)
1797  {
1798  for (std::vector<BaseParticle*>::iterator P = particleHandler.begin(); P!=particleHandler.end(); ++P)
1799  {
1800  if((*B)->checkBoundaryAfterParticleMoved(*P,particleHandler)) //Returns true if the particle is deleted
1801  --P;
1802  }
1803  }
1804 }
1805 
1806 void MD::print(std::ostream& os, bool print_all) {
1807  os << "problem_name:" << problem_name.str().c_str() << std::endl;
1808  os << " t:" << t << " dt:" << dt << ", tmax:" << tmax << ", save_count_data:" << save_count_data << ", save_count_ene:" << save_count_ene << ", save_count_stat:" << save_count_stat << ", save_count_fstat:" << save_count_fstat << std::endl;
1809  os << " x:[" << xmin << "," << xmax << "], y:[" << ymin << "," << ymax << "], z:[" << zmin << "," << zmax << "]" << std::endl;
1810  os << " dim:" << dim << ", gravity:" << gravity << std::endl;
1811  if (Species.size()==1) {
1812  os << " "; Species[0].print(os); os << std::endl;
1813  } else {
1814  os << " Species: size:" << Species.size() << std::endl;
1815  for (unsigned int i=0; i<Species.size(); i++) {
1816  os << " "; Species[i].print(os); os << std::endl;
1817  for (unsigned int j=0; j<Species[i].MixedSpecies.size(); j++) { os << " "; Species[i].MixedSpecies[j].print(os); os << std::endl; }
1818  }
1819  }
1820  os << " options_fstat=" << options_fstat
1821  << " , options_data=" << options_data
1822  << " , options_ene=" << options_ene
1823  << " , options_restart=" << options_restart << std::endl;
1824  os << " Particles: N:" << particleHandler.getNumberOfObjects() << ", Nmax:" << particleHandler.getStorageCapacity() << std::endl;
1825  if (print_all) for (unsigned int i=0; i<particleHandler.getNumberOfObjects(); i++) { os << " "; particleHandler.getObject(i)->print(os); os << std::endl; }
1826  os << " Walls: NWall:" << wallHandler.getNumberOfWalls() << ", NBoundary:" << boundaryHandler.getNumberOfObjects() << std::endl;
1827  for (unsigned int i=0; i<wallHandler.getNumberOfWalls(); i++) { os << " "; wallHandler.getWall(i)->print(os); os << std::endl; }
1828  for (unsigned int i=0; i<boundaryHandler.getNumberOfObjects(); i++) { os << " "; boundaryHandler.getObject(i)->print(os); os << std::endl; }
1829  }
1830 
1831 
1833  Species.push_back(S);
1834  unsigned int n = Species.size();
1835  Species.back().MixedSpecies.resize(n-1);
1836  for (unsigned int i=0; i<n-1; i++)
1837  Species.back().MixedSpecies[i].mix(Species[i],Species.back());
1838 }
1839 
1844 {
1845 #ifdef USE_SIMPLE_VERLET_INTEGRATION
1846 
1847  static Vec3D xtemp, atemp;
1849  xtemp=pI->get_Position();
1850  atemp=pI->get_Force()*pI->get_InvMass();
1851  pI->set_Position(xtemp*2.0-pI->PrevPosition+atemp*dt*dt);
1852  pI->set_Velocity((pI->get_Position()-pI->PrevPosition)/(2*dt)+atemp*dt);
1853  pI->PrevPosition=xtemp;
1854  if (rotation) {
1855  pI->angularAccelerate(pI->get_Torque()*pI->get_InvInertia()*dt);
1856  pI->rotate(pI->get_AngularVelocity()*dt);
1857  }
1858 
1859  // This shifts particles that moved through periodic walls
1861  for (unsigned int j=0; j<boundaryHandler.getNumberOfObjects(); j++)
1862  {
1864  //Note, checking the dynamic cast allows you to detect if the wall is of a certain type (or inherited from this type).
1865  if(b0) //If the dyamic_cast succeeds
1866  if (b0->distance(*iP)<0)
1867  {
1868  b0->shift_position(iP->get_Position());
1870  {
1873  }
1874  }
1875  }
1876 
1877 #else //use velocity verlet
1878  pI->accelerate(pI->get_Force()*pI->get_InvMass()*0.5*dt);
1879  if (rotation) pI->angularAccelerate(pI->get_Torque()*pI->get_InvInertia()*0.5*dt);;
1880 #endif
1881 #ifdef FOLLOWPARTICLE
1882  if(pI->get_Index()==FPID)
1883  std::cout<<"In integration after time="<<get_t()<<", particle "<<FPID<<": "<<*pI<<std::endl;
1884 #endif
1885 }
1886 
1890 void MD::statistics_from_restart_data(const char* name)
1891 {
1893  //This function loads all MD data
1895 
1896  //This creates the file statistics will be saved to
1897  stat_filename.str("");
1898  stat_filename << name << ".stat";
1899  stat_file.open( stat_filename.str().c_str() , std::fstream::out);
1900 
1901 
1902  // Sets up the initial conditions for the simulation
1903  // setup_particles_initial_conditions();
1904  // Setup the previous position arrays and mass of each particle.
1906  // Other routines required to jump-start the simulation
1910  start_ene();
1911 
1912  while (load_from_data_file(data_filename.str().c_str())) {
1917  save_data_data = true;
1918  save_data_ene = true;
1919  save_data_stat = true;
1920  save_data_fstat= true;
1924  output_ene();
1925  std::cout << std::setprecision(6) << t << std::endl;
1926  }
1927 
1928  data_file.close();
1929  stat_file.close();
1930 }
1931 
1936 {
1938  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it)
1939  {
1940  (*it)->set_Force(Vec3D(0.0,0.0,0.0));
1941  (*it)->set_Torque(Vec3D(0.0,0.0,0.0));
1942  }
1943  for (std::vector<BaseWall*>::iterator it = wallHandler.begin(); it!=wallHandler.end(); ++it)
1944  {
1945  (*it)->set_Force(Vec3D(0.0,0.0,0.0));
1946  (*it)->set_Torque(Vec3D(0.0,0.0,0.0));
1947  } //end reset forces loop
1948 
1949 
1950  #ifdef DEBUG_OUTPUT
1951  std::cerr << "Have all forces set to zero " << std::endl;
1952  #endif
1953 
1955 
1956  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it)
1957  {
1958 
1961  //end inner loop over contacts.
1962 
1964 
1965  }
1966 
1967 #ifdef ContactListHgrid
1968  PossibleContact* Curr=possibleContactList.getFirstPossibleContact();
1969  while(Curr)
1970  {
1971  compute_internal_forces(Curr->get_P1(),Curr->get_P2());
1972  Curr=Curr->get_Next();
1973  }
1974 #endif
1975  //end outer loop over contacts.
1976 
1977 }
1978 
1979 
1981  broad_phase(i);
1982 }
1983 
1985 void MD::write(std::ostream& os) {
1986  os
1987  << "restart_version " << 3
1988  << std::endl
1989  << "name " << problem_name.str()
1990  << std::endl
1991  << "xmin " << xmin << " xmax " << xmax
1992  << " ymin " << ymin << " ymax " << ymax
1993  << " zmin " << zmin << " zmax " << zmax
1994  << std::endl
1995  << "dt " << dt
1996  << " t " << t
1997  << " tmax " << tmax
1998  << " save_count_data " << save_count_data
1999  << " save_count_ene " << save_count_ene
2000  << " save_count_stat " << save_count_fstat
2001  << " save_count_fstat " << save_count_fstat
2002  << std::endl
2003  << "dim " << dim
2004  << " gravity " << gravity
2005  << std::endl
2006  << "options_fstat " << options_fstat
2007  << " options_data " << options_data
2008  << " options_ene " << options_ene
2009  << " options_restart " << options_restart
2010  << std::endl;
2011  os<< "Species " << Species.size() << std::endl;
2012  for (std::vector<CSpecies>::iterator it = Species.begin(); it!=Species.end(); ++it) {
2013  os << (*it) << std::endl;
2014  for (std::vector<CSpecies>::iterator it2 = it->MixedSpecies.begin(); it2!=it->MixedSpecies.end(); ++it2) os << (*it2) << " (mixed)" << std::endl;
2015  }
2016  os<< "Walls " << wallHandler.getNumberOfWalls() << std::endl;
2017  for (std::vector<BaseWall*>::iterator it = wallHandler.begin(); it!=wallHandler.end(); ++it) os << (**it) << std::endl;
2018  os<< "Boundaries " << boundaryHandler.getNumberOfObjects() << std::endl;
2019  for (std::vector<BaseBoundary*>::iterator it = boundaryHandler.begin(); it!=boundaryHandler.end(); ++it) os << (**it) << std::endl;
2020  os<< "Particles " << particleHandler.getNumberOfObjects() << std::endl;
2021  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) os << (**it) << std::endl;
2022  //should be optional: os << "FixedParticles " << data_FixedParticles << std::endl;
2023 }
2024 
2026 void MD::read(std::istream& is)
2027 {
2028  std::string dummy;
2029  is >> dummy;
2030  if (strcmp(dummy.c_str(),"restart_version"))
2031  {
2032  dim = atoi(dummy.c_str());
2033  restart_version = 1;
2034  read_v1(is);
2035  }
2036  else
2037  {
2038  is >> restart_version
2039  >> dummy >> dummy;
2040  problem_name.str(dummy);
2041  if(restart_version==2)
2042  {
2043  read_v2(is);
2044  }
2045  else
2046  {
2047  //std::cout << "version 3" << std::endl;
2048  is >> dummy >> xmin
2049  >> dummy >> xmax
2050  >> dummy >> ymin
2051  >> dummy >> ymax
2052  >> dummy >> zmin
2053  >> dummy >> zmax
2054  >> dummy >> dt
2055  >> dummy >> t
2056  >> dummy >> tmax
2057  >> dummy >> save_count_data
2058  >> dummy >> save_count_ene
2059  >> dummy >> save_count_stat
2060  >> dummy >> save_count_fstat
2061  >> dummy >> dim
2062  >> dummy >> gravity
2063  >> dummy >> options_fstat
2064  >> dummy >> options_data
2065  >> dummy >> options_ene
2066  >> dummy;
2067  //this is optional to allow restart files with and without options_restart
2068  if (!strcmp(dummy.c_str(),"options_restart")) is >> options_restart >> dummy;
2069  unsigned int N;
2070  is >> N;
2071  Species.resize(0); //to clear the Species vector
2072  Species.resize(N);
2073  //please don't change this code to iterators; the mixed species requires indexing
2074  //old code: for (vector<CSpecies>::iterator it = Species.begin(); it!=Species.end(); ++it) it->read(is);
2075  for (unsigned int i=0; i<N; i++) {
2076  Species[i].read(is);
2077  Species[i].MixedSpecies.resize(i);
2078  for (unsigned int j=0; j<i; j++) {
2079  Species[i].MixedSpecies[j].read(is);
2080  }
2081  }
2082 
2083  std::stringstream line (std::stringstream::in | std::stringstream::out);
2084 
2085  is >> dummy >> N;
2086  wallHandler.clear();
2087  getLineFromStringStream(is,line);
2088  for (unsigned int i=0;i<N;i++)
2089  {
2090  getLineFromStringStream(is,line);
2091  wallHandler.readWall(line);
2092  }
2093 
2094  is >> dummy >> N;
2096  getLineFromStringStream(is,line);
2097  for (unsigned int i=0;i<N;i++)
2098  {
2099  getLineFromStringStream(is,line);
2101  }
2102 
2103  is >> dummy >> N;
2105  getLineFromStringStream(is,line);
2106  for (unsigned int i=0;i<N;i++)
2107  {
2108  getLineFromStringStream(is,line);
2111  }
2112 
2113  //After the lines storing particle data, an optional variable 'FixedParticles' can be read in, which fixes the first 'FixedParticles' particles
2114  if (is.peek()==70) is >> dummy >> data_FixedParticles;
2115  }
2116  }
2117 }
2118 
2119 
2120 
2121 void MD::read_v2(std::istream& is)
2122 {
2123  std::string dummy;
2124  //std::cout << "version 2" << std::endl;
2125  is >> dummy >> xmin
2126  >> dummy >> xmax
2127  >> dummy >> ymin
2128  >> dummy >> ymax
2129  >> dummy >> zmin
2130  >> dummy >> zmax
2131  >> dummy >> dt
2132  >> dummy >> t
2133  >> dummy >> tmax
2134  >> dummy >> save_count_data
2135  >> dummy >> dim
2136  >> dummy >> gravity
2137  >> dummy >> options_fstat
2138  >> dummy >> options_data
2139  >> dummy >> options_ene
2140  >> dummy;
2144 
2145  //this is optional to allow restart files with and without options_restart
2146  if (!strcmp(dummy.c_str(),"options_restart")) is >> options_restart >> dummy;
2147 
2148  unsigned int N;
2149 
2150  is >> N;
2151  Species.resize(N);
2152  //please don't change this code to iterators; the mixed species requires indexing
2153  //old code: for (vector<CSpecies>::iterator it = Species.begin(); it!=Species.end(); ++it) it->read(is);
2154  for (unsigned int i=0; i<N; i++) {
2155  Species[i].read(is);
2156  Species[i].MixedSpecies.resize(i);
2157  for (unsigned int j=0; j<i; j++) {
2158  Species[i].MixedSpecies[j].read(is);
2159  }
2160  }
2161 
2162  std::stringstream line (std::stringstream::in | std::stringstream::out);
2163 
2164  is >> dummy >> N;
2165  wallHandler.clear();
2166  getLineFromStringStream(is,line);
2167  for (unsigned int i=0;i<N;i++)
2168  {
2169  getLineFromStringStream(is,line);
2170  wallHandler.readWall(line);
2171  }
2172 
2173  is >> dummy >> N;
2175  getLineFromStringStream(is,line);
2176  for (unsigned int i=0;i<N;i++)
2177  {
2178  getLineFromStringStream(is,line);
2179  boundaryHandler.readObject(line);
2180  }
2181 
2182  is >> dummy >> N;
2184  getLineFromStringStream(is,line);
2185  for (unsigned int i=0;i<N;i++)
2186  {
2187  getLineFromStringStream(is,line);
2190  }
2191 
2192  //After the lines storing particle data, an optional variable 'FixedParticles' can be read in, which fixes the first 'FixedParticles' particles
2193  if (is.peek()==70) is >> dummy >> data_FixedParticles;
2194 }
2195 
2196 
2198 void MD::write_v1(std::ostream& os)
2199 {
2200  os << dim << " " << gravity << " "
2201  << xmin << " " << xmax << " " << ymin << " " << ymax << " " << zmin << " " << zmax << " "
2202  << dt << " " << t << " " << tmax << " "
2203  << save_count_data << " " << max_radius << " "
2204  << problem_name.str() << " "
2205  << Species.size() << " "
2206  << particleHandler.getNumberOfObjects() << " "
2207  << wallHandler.getNumberOfWalls() << " "
2208  << boundaryHandler.getNumberOfObjects() << std::endl;
2209  os << options_fstat << " " << options_data << " " << options_ene << std::endl;
2210  for (std::vector<CSpecies>::iterator it = Species.begin(); it!=Species.end(); ++it) os << (*it) << std::endl;
2211  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it) os << (**it) << std::endl;
2212  for (std::vector<BaseWall*>::iterator it = wallHandler.begin(); it!=wallHandler.end(); ++it) os << (**it) << std::endl;
2213  for (std::vector<BaseBoundary*>::iterator it = boundaryHandler.begin(); it!=boundaryHandler.end(); ++it) os << (**it) << std::endl;
2214 }
2215 
2217 void MD::read_v1(std::istream& is)
2218 {
2219  std::cout << "reading restart data version 1" << std::endl;
2220  is >> gravity
2221  >> xmin >> xmax >> ymin >> ymax >> zmin >> zmax
2222  >> dt >> t >> tmax
2227  std::string str;
2228  is >> str;
2229  problem_name.str(str);
2230  int N;
2231  unsigned int NParticles, NWalls, NBoundarys;
2232  is >> N; Species.resize(N);
2233  is >> NParticles; particleHandler.setStorageCapacity(NParticles);
2234  is >> NWalls; wallHandler.setStorageCapacity(NWalls);
2235  is >> NBoundarys; boundaryHandler.setStorageCapacity(NBoundarys);
2236  is >> options_fstat >> options_data >> options_ene;
2237  for (std::vector<CSpecies>::iterator it = Species.begin(); it!=Species.end(); ++it) is >> (*it);
2238 
2239  std::stringstream line (std::stringstream::in | std::stringstream::out);
2240  getLineFromStringStream(is,line);
2241 
2242  for (unsigned int i=0;i<NParticles;i++)
2243  {
2244  getLineFromStringStream(is,line);
2247  }
2248 
2249  for (unsigned int i=0;i<NWalls;i++)
2250  {
2251  getLineFromStringStream(is,line);
2252  wallHandler.readWall(line);
2253  }
2254 
2255  for (unsigned int i=0;i<NBoundarys;i++)
2256  {
2257  getLineFromStringStream(is,line);
2259  }
2260 }
2261 
2262 
2267 {
2268  #ifdef DEBUG_OUTPUT
2269  std::cerr << "Entered solve" << std::endl;
2270  #endif
2271  #ifdef ContactListHgrid
2272  std::cout << "Using ContactListHgrid"<<std::endl;
2273  #endif
2274 
2276 
2278  //if (get_counter()) std::cout << "Count: " << get_counter() << std::endl;
2279  //else std::cout << "Started to solve ..." << std::endl;
2280 
2282  if (get_counter()>0) problem_name << "." << get_counter();
2283 
2288  if (!restarted) {
2289  t=0;
2291  #ifdef DEBUG_OUTPUT
2292  std::cerr << "Have created the particles initial conditions " << std::endl;
2293  #endif
2294  }
2295 
2296 
2299 
2300  //undo append if data file does not exist
2301  //~ std::cout << " get_data_filename()" << get_data_filename() << ", append" << append << ", access" << access(get_data_filename().c_str(), F_OK ) << std::endl;
2302  //~ if (append && (access(get_data_filename().c_str(), F_OK ) == -1) ) {
2303  //~ append = false;
2304  //~ std::cerr << "Warning: cannot append because data file does not exist; set append to false." << std::endl;
2305  //~ }
2306  if (get_append()) {
2307  if (get_options_data()==2) increase_counter_data(std::fstream::out);
2308  if (get_options_ene()==2) increase_counter_ene(std::fstream::out);
2309  if (get_options_stat()==2) increase_counter_stat(std::fstream::out);
2310  if (get_options_fstat()==2) increase_counter_fstat(std::fstream::out);
2311  }
2312 
2313  std::fstream::openmode mode;
2314  if (append) mode=std::fstream::out|std::fstream::app;
2315  else mode=std::fstream::out;
2316 
2318  if(!open_data_file(mode)) {std::cerr << "Problem opening data file aborting" << std::endl; exit(-1);}
2319 
2321  set_ene_filename();
2322 
2324  if(!open_ene_file(mode)){std::cerr << "Problem opening ene file aborting" << std::endl; exit(-1);}
2325 
2328 
2330  if(!open_fstat_file(mode)){std::cerr << "Problem opening fstat file aborting" << std::endl; exit(-1);}
2331 
2333  #ifdef USE_SIMPLE_VERLET_INTEGRATION
2334  std::cout << "using simple verlet integration" << std::endl;
2335  for (int i = 0;i<Particles.size();i++)
2337  #endif
2338 
2341 
2347 
2348  ene_ela = 0;
2349  if (!append) start_ene();
2350 
2351  //needed for output_statistics
2352  save_data_data =false;
2353  save_data_ene =false;
2354  save_data_stat =false;
2355  save_data_fstat=false;
2356 
2362  Mdouble dt_=dt; dt=0; compute_all_forces(); dt=dt_;
2366  #ifdef DEBUG_OUTPUT
2367  std::cerr << "Have computed the initial values for the forces " << std::endl;
2368  #endif
2369 
2370  if (append) {
2371  save_data_data =false;
2372  save_data_ene =false;
2373  save_data_stat =false;
2374  save_data_fstat=false;
2375  } else {
2376  save_data_data =true;
2377  save_data_ene =true;
2378  save_data_stat =true;
2379  save_data_fstat=true;
2380  }
2381 
2382  int count_data=1;
2383  int count_ene=1;
2384  int count_stat=1;
2385  int count_fstat=1;
2386  //create .disp file if .data file is created
2389  //if ((get_options_data()) && (xballsSupportOn()=="ON")) create_xballs_script();
2390 
2391  ene_ela = 0;
2393  while (t-dt<tmax&&continue_solve())
2394  {
2395  for (std::vector<BaseBoundary*>::iterator it = boundaryHandler.begin(); it!=boundaryHandler.end(); ++it)
2396  {
2397  (*it)->checkBoundaryActionsBeforeTimeStep(particleHandler,wallHandler,random);
2398  }
2401  if (save_data_data)
2402  {
2403  if (get_options_data()==2) increase_counter_data(std::fstream::out);
2405  }
2406  if (save_data_ene)
2407  {
2408  if (get_options_ene()==2) increase_counter_ene(std::fstream::out);
2409  }
2410  if(save_data_stat)
2411  {
2412  if (get_options_stat()==2) increase_counter_stat(std::fstream::out);
2413  }
2414  if (save_data_fstat)
2415  {
2416  if (get_options_fstat()==2) increase_counter_fstat(std::fstream::out);
2417  }
2418 
2420  rotation=false;
2421  for (unsigned int i=0;i<Species.size();i++) {
2422  if (Species[i].get_mu()||Species[i].get_murolling()||Species[i].get_mutorsion())
2423  rotation = true;
2424  for (unsigned int j=0;j<Species[i].MixedSpecies.size();j++) {
2425  if (Species[i].MixedSpecies[j].get_mu()||Species[i].MixedSpecies[j].get_murolling()||Species[i].MixedSpecies[j].get_mutorsion())
2426  rotation = true;
2427  }
2428  }
2429 
2432  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it)
2433  {
2435  }
2438 
2442 
2444 
2448 
2450 
2452 
2453 
2457 
2460  for (std::vector<BaseParticle*>::iterator it = particleHandler.begin(); it!=particleHandler.end(); ++it)
2461  {
2463  }
2466 
2467  if (save_data_ene) output_ene();
2468 
2470 
2471  t+=dt;
2472 
2473  //To write the last time step (acutaly data is written at t+0.5*dt where t alreay is larger then tmax)
2474  if (count_data == save_count_data || t>tmax) //write data
2475  {
2476  save_data_data=true;
2477  count_data=1;
2478  cout_time();
2479  }
2480  else
2481  {
2482  save_data_data=false;
2483  count_data++;
2484  }
2485  if (count_ene == save_count_ene || t>tmax) //write data
2486  {
2487  save_data_ene=true;
2488  count_ene=1;
2489  }
2490  else
2491  {
2492  save_data_ene=false;
2493  count_ene++;
2494  }
2495  if (count_fstat == save_count_fstat || t>tmax) //write data
2496  {
2497  save_data_fstat=true;
2498  count_fstat=1;
2499  }
2500  else
2501  {
2502  save_data_fstat=false;
2503  count_fstat++;
2504  }
2505  if (count_stat == save_count_stat || t>tmax) //write data
2506  {
2507  save_data_stat=true;
2508  count_stat=1;
2509  }
2510  else
2511  {
2512  save_data_stat=false;
2513  count_stat++;
2514  }
2515 
2516  }
2517  //end loop over interaction count
2519 
2520  std::cout << std::endl;
2521  //To make sure get_t gets the correct time for outputting statistics
2523 
2524  data_file.close();
2525 
2526  ene_file.close();
2527 
2528  fstat_file.close();
2529 
2530 }
2531 
2535 int MD::readArguments(unsigned int argc, char *argv[])
2536 {
2537  bool isRead = true;
2538  for (unsigned int i = 1; i<argc; i+=2) {
2539  std::cout << "interpreting input argument " << argv[i];
2540  for (unsigned int j = i+1; j<argc; j++) {
2541  if (argv[j][0]=='-') break;
2542  std::cout << " " << argv[j];
2543  }
2544  std::cout << std::endl;
2545  isRead &= readNextArgument(i, argc, argv);
2546  if (!isRead) {
2547  std::cerr << "Warning: not all arguments read correctly!" << std::endl;
2548  exit(-10);
2549  }
2550  }
2551  return isRead;
2552 }
2553 
2554 int MD::readNextArgument(unsigned int& i, unsigned int argc, char *argv[])
2555 {
2557  if (!strcmp(argv[i],"-name")) {
2558  set_name(argv[i+1]);
2559  } else if (!strcmp(argv[i],"-xmin")) {
2560  set_xmin(atof(argv[i+1]));
2561  } else if (!strcmp(argv[i],"-ymin")) {
2562  set_ymin(atof(argv[i+1]));
2563  } else if (!strcmp(argv[i],"-zmin")) {
2564  set_zmin(atof(argv[i+1]));
2565  } else if (!strcmp(argv[i],"-xmax")) {
2566  set_xmax(atof(argv[i+1]));
2567  } else if (!strcmp(argv[i],"-ymax")) {
2568  set_ymax(atof(argv[i+1]));
2569  } else if (!strcmp(argv[i],"-zmax")) {
2570  set_zmax(atof(argv[i+1]));
2571  //} else if (!strcmp(argv[i],"-svn")) {
2572  // std::cout << "svn version " << SVN_VERSION << std::endl;
2573  // i--;
2574  } else if (!strcmp(argv[i],"-dt")) {
2575  Mdouble old=get_dt();
2576  set_dt(atof(argv[i+1]));
2577  std::cout << " reset dt from " << old << " to " << get_dt() << std::endl;
2578  } else if (!strcmp(argv[i],"-Hertzian")) {
2579  Species[0].set_ForceType(Hertzian);
2580  i--;
2581  } else if (!strcmp(argv[i],"-tmax")) {
2582  Mdouble old = get_tmax();
2583  set_tmax(atof(argv[i+1]));
2584  std::cout << " reset tmax from " << old << " to " << get_tmax() << std::endl;
2585  } else if (!strcmp(argv[i],"-save_count") || !strcmp(argv[i],"-savecount")) {
2586  set_savecount(atoi(argv[i+1]));
2587  } else if (!strcmp(argv[i],"-save_count_data")) {
2588  set_save_count_data(atoi(argv[i+1]));
2589  } else if (!strcmp(argv[i],"-save_count_fstat")) {
2590  set_save_count_fstat(atoi(argv[i+1]));
2591  } else if (!strcmp(argv[i],"-save_count_stat")) {
2592  set_save_count_stat(atoi(argv[i+1]));
2593  } else if (!strcmp(argv[i],"-save_count_ene")) {
2594  set_save_count_ene(atoi(argv[i+1]));
2595  } else if (!strcmp(argv[i],"-dim")) {
2596  set_dim(atoi(argv[i+1]));
2597  } else if (!strcmp(argv[i],"-gravity")) {
2599  set_gravity(Vec3D(atof(argv[i+1]),atof(argv[i+2]),atof(argv[i+3])));
2600  i+=2;
2601  } else if (!strcmp(argv[i],"-options_fstat")) {
2602  set_options_fstat(atoi(argv[i+1]));
2603  } else if (!strcmp(argv[i],"-options_restart")) {
2604  set_options_restart(atoi(argv[i+1]));
2605  } else if (!strcmp(argv[i],"-options_data")) {
2606  set_options_data(atoi(argv[i+1]));
2607  } else if (!strcmp(argv[i],"-options_stat")) {
2608  set_options_stat(atoi(argv[i+1]));
2609  } else if (!strcmp(argv[i],"-options_ene")) {
2610  set_options_ene(atoi(argv[i+1]));
2611  } else if (!strcmp(argv[i],"-auto_number")) {
2612  auto_number();
2613  i--;
2614  } else if (!strcmp(argv[i],"-number_of_saves")) {
2615  set_number_of_saves_all(atof(argv[i+1]));
2616  } else if (!strcmp(argv[i],"-restart")||!strcmp(argv[i],"-r")) {
2620  std::string filename;
2621 
2622  //use default filename if no argument is given
2623  if (i+1>=argc||argv[i+1][0]=='-') {
2624  i--;
2625  filename = get_name();
2626  std::cout << get_name() << std::endl;
2627  } else filename = argv[i+1];
2628 
2629  //add ".restart" if necessary
2630  const char* fileextension = (filename.c_str()+std::max(0,(int)filename.length()-8));
2631  if (strcmp(fileextension,".restart"))
2632  filename=filename+".restart";
2633 
2634  std::cout << "restart from " << filename << std::endl;
2635  load_restart_data(filename);
2636  } else if (!strcmp(argv[i],"-data")) {
2637  std::string filename = argv[i+1];
2638  load_from_data_file(filename.c_str());
2639  } else if (!strcmp(argv[i],"-k")) {
2640  Mdouble old = get_k();
2641  set_k(atof(argv[i+1]));
2642  std::cout << " reset k from " << old << " to " << get_k() << std::endl;
2643  } else if (!strcmp(argv[i],"-disp")) {
2644  Mdouble old = get_disp();
2645  set_disp(atof(argv[i+1]));
2646  std::cout << " reset disp from " << old << " to " << get_disp() << std::endl;
2647  } else if (!strcmp(argv[i],"-kt")) {
2648  Mdouble old = get_kt();
2649  set_kt(atof(argv[i+1]));
2650  std::cout << " reset kt from " << old << " to " << get_kt() << std::endl;
2651  } else if (!strcmp(argv[i],"-dispt")) {
2652  Mdouble old = get_dispt();
2653  set_dispt(atof(argv[i+1]));
2654  std::cout << " reset dispt from " << old << " to " << get_dispt() << std::endl;
2655  } else if (!strcmp(argv[i],"-krolling")) {
2656  Mdouble old = get_krolling();
2657  set_krolling(atof(argv[i+1]));
2658  std::cout << " reset krolling from " << old << " to " << get_krolling() << std::endl;
2659  } else if (!strcmp(argv[i],"-disprolling")) {
2660  Mdouble old = get_disprolling();
2661  set_disprolling(atof(argv[i+1]));
2662  std::cout << " reset disprolling from " << old << " to " << get_disprolling() << std::endl;
2663  } else if (!strcmp(argv[i],"-mu")) {
2664  Mdouble old = get_mu();
2665  set_mu(atof(argv[i+1]));
2666  std::cout << " reset mu from " << old << " to " << get_mu() << std::endl;
2667  } else if (!strcmp(argv[i],"-murolling")) {
2668  Mdouble old = get_mu();
2669  set_murolling(atof(argv[i+1]));
2670  std::cout << " reset murolling from " << old << " to " << get_murolling() << std::endl;
2671  } else if (!strcmp(argv[i],"-randomise") || !strcmp(argv[i],"-randomize")) {
2672  random.randomise();
2673  i--;
2674  } else if (!strcmp(argv[i],"-k0")) {
2675  Mdouble old = Species[0].get_k0();
2676  Species[0].set_k0(atof(argv[i+1]));
2677  std::cout << " reset k0 from " << old << " to " << Species[0].get_k0() << std::endl;
2678  } else if (!strcmp(argv[i],"-f0")) {
2679  Mdouble old = Species[0].get_f0();
2680  Species[0].set_f0(atof(argv[i+1]));
2681  std::cout << " reset f0 from " << old << " to " << Species[0].get_f0() << std::endl;
2682  } else if (!strcmp(argv[i],"-AdhesionForceType")) {
2683  Mdouble old = Species[0].get_AdhesionForceType();
2684  Species[0].set_AdhesionForceType(argv[i+1]);
2685  std::cout << " reset AdhesionForceType from " << old << " to " << Species[0].get_AdhesionForceType() << std::endl;
2686  } else if (!strcmp(argv[i],"-append")) {
2687  set_append(true);
2688  i--;
2689  } else if (!strcmp(argv[i],"-fixedParticles")) {
2690  set_FixedParticles(atof(argv[i+1]));
2691  } else if (!strcmp(argv[i],"-rho")) {
2692  set_rho(atof(argv[i+1]));
2693  } else if (!strcmp(argv[i],"-dim_particle")) {
2694  set_dim_particle(atoi(argv[i+1]));
2695  } else if (!strcmp(argv[i],"-counter")) {
2696  set_counter(atoi(argv[i+1]));
2697  } else return false;
2698  return true; //returns true if argv is found
2699 }
2700 
2701 
2704  {
2705  int R=0;
2707  {
2708  removeParticle(i);
2709  R++;
2710  }
2711  if(R!=PeriodicCreated)
2712  {
2713  std::cerr<<"ERROR :: Periodic Particles Removed not equal to Periodic Particles Created, it created "<<PeriodicCreated<<" Particles, but removed "<<R<<std::endl<<std::endl;
2714  exit(-1);
2715  }
2716  }
2717 
2720  {
2721 // std::cout<<"Largest R="<<particleHandler.getLargestParticle()->get_Radius()<<std::endl;
2722  int C=0;
2723  for (unsigned int k=0; k<boundaryHandler.getNumberOfObjects(); k++)
2724  {
2725 // std::cout<<"Checking wall number: "<<k<<std::endl;
2726  int N=particleHandler.getNumberOfObjects(); //Required because the number of particles increaeses
2727  for (int i=0; i<N; i++)
2728  {
2729 // std::cout<<"Particle number: "<<i<<std::endl;
2731  }
2732  }
2733  return C;
2734  }
std::fstream fstat_file
Definition: STD_save.h:254
bool save_data_fstat
Definition: MD.h:681
bool find_next_data_file(Mdouble tmin, bool verbose=true)
Definition: MD.cc:426
Definition: CSpecies.h:29
Mdouble k0
Definition: CSpecies.h:508
virtual void cout_time()
std::couts time
Definition: MD.h:621
void set_save_count_stat(int new_)
Definition: MD.h:159
Mdouble k2max
Definition: CSpecies.h:500
Mdouble get_zmin()
Gets zmin.
Definition: MD.h:313
std::string xballs_additional_arguments
Definition: MD.h:698
virtual void setup_particles_initial_conditions()
This function allows the initial conditions of the particles to be set, by default locations is rando...
Definition: MD.cc:120
void set_ene_ela(Mdouble new_)
Sets ene_ela.
Definition: MD.h:397
void set_krolling(Mdouble new_, unsigned int indSpecies=0)
Allows the spring constant to be changed.
Definition: MD.h:212
virtual void output_ene()
This function outputs statistical data - The default is to compute the rotational kinetic engergy...
Definition: MD.cc:175
void add_Torque(const Vec3D &_new)
void set_zmax(Mdouble new_zmax)
Sets ymax and walls, assuming the standard definition of walls as in the default constructor.
Definition: MD.h:334
std::stringstream stat_filename
Definition: STD_save.h:247
unsigned int options_restart
Definition: STD_save.h:266
Mdouble X
Definition: Vector.h:44
bool open_fstat_file(std::fstream::openmode mode=std::fstream::out)
Definition: STD_save.h:184
void set_counter(int new_counter)
This set the counter, overriding the defaults.
Definition: STD_save.cc:78
CTangentialSpring * getTangentialSpring(BaseParticle *PI, BaseParticle *PJ, BaseParticle *PJreal)
Definition: MD.cc:706
void readWall(std::istream &is)
Reads BaseWall into the WallHandler from restart data.
Definition: WallHandler.cc:133
int format
Definition: MD.h:699
virtual void read_v1(std::istream &is)
Reads all MD data.
Definition: MD.cc:2217
std::fstream stat_file
Definition: STD_save.h:253
Mdouble depth
Definition: CSpecies.h:502
Mdouble get_disprolling(unsigned int indSpecies=0)
Allows the tangential viscosity to be accessed.
Definition: MD.h:230
CSpecies * get_MixedSpecies(int i, int j)
Allows the mixed species to be accessed.
Definition: MD.h:131
void set_restarted(bool new_)
Definition: MD.h:383
int get_file_counter()
Definition: STD_save.h:234
const Vec3D & get_Velocity() const
Particle * get_P2()
bool load_par_ini_file(const char *filename)
allows the user to read par.ini files (useful to read MDCLR files)
Definition: MD.cc:271
std::stringstream data_filename
These store the save file names, by default they are derived from problem_name.
Definition: STD_save.h:246
Mdouble get_dispt(unsigned int indSpecies=0)
Allows the tangential viscosity to be accessed.
Definition: MD.h:226
Mdouble disptorsion
Definition: CSpecies.h:416
void set_append(bool new_)
Sets restarted.
Definition: MD.h:391
Mdouble get_InteractionRadius() const
void rotate(const Vec3D &_new)
Mdouble get_ene_ela()
Gets ene_ela.
Definition: MD.h:395
bool get_append()
Gets restarted.
Definition: MD.h:389
void compute_particle_mass(std::vector< CSpecies > &Species)
Compute Particle mass function, which required a reference to the Species vector. It copmuters the Pa...
virtual void start_ene()
Functions for ene file.
Definition: MD.cc:127
void add_ene_ela(Mdouble new_)
Sets ene_ela.
Definition: MD.h:399
int get_IndSpecies() const
Mdouble get_dt()
Allows the time step dt to be accessed.
Definition: MD.h:339
void getLineFromStringStream(std::istream &in, std::stringstream &out)
void copyAndAddObject(const T &O)
Creates a copy of a Object and adds it to the BaseHandler.
Definition: BaseHandler.h:93
int read_dim_from_data_file()
Definition: MD.cc:628
bool restarted
Definition: MD.h:701
void reset_TangentialSprings()
sets the history parameter TangentialSprings of all particles to zero
Definition: MD.h:644
void set_zmin(Mdouble new_zmin)
Sets ymin and walls, assuming the standard definition of walls as in the default constructor.
Definition: MD.h:324
T * getObject(const unsigned int id) const
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:176
void setStorageCapacity(const unsigned int N)
Sets the storage capacity of this WallHandler.
Definition: WallHandler.cc:236
void setStorageCapacity(const unsigned int N)
Sets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:213
virtual void do_integration_after_force_computation(BaseParticle *pI)
This is were the integration is done.
Definition: MD.cc:1843
int save_restart_data_counter
Definition: MD.h:723
Mdouble mus
Definition: CSpecies.h:418
void angularAccelerate(const Vec3D &_new)
void set_options_data(unsigned int new_)
Definition: STD_save.h:161
T * getLastObject() const
Gets a pointer to the last Object in this BaseHandler.
Definition: BaseHandler.h:192
Mdouble xballs_scale
Definition: MD.h:697
void set_dt()
Sets dt to 1/50-th of the smallest possible collision time.
Definition: MD.h:447
void set_options_restart(unsigned int new_)
Definition: STD_save.h:167
void set_savecount(int new_)
Allows the number of time steps between saves to be changed, see also set_number_of_saves.
Definition: MD.h:155
void set_fstat_filename()
Definition: STD_save.h:143
BaseParticle * get_PeriodicFromParticle() const
Mdouble disp
Definition: CSpecies.h:413
const std::vector< T * >::const_iterator begin() const
Gets the begin of the const_iterator over all Object in this BaseHandler.
Definition: BaseHandler.h:220
virtual void HGRID_update_move(BaseParticle *, Mdouble)
Definition: MD.h:594
bool load_from_data_file(const char *filename, unsigned int format=0)
This allows particle data to be reloaded from data files.
Definition: MD.cc:250
unsigned int options_fstat
Indicators if files are created or not 0: file will not be created 1: file will be written in one fil...
Definition: STD_save.h:262
Matrix3D Cross(const Vec3D &A, const Matrix3D &B)
Definition: Matrix.h:198
#define sqr(a)
Definition: ExtendedMath.h:36
bool rotation
Definition: MD.h:721
virtual void actions_after_solve()
This is actions at the end of the code, but before the files are closed.
Definition: MD.h:567
int dim
The dimension of the simulation.
Definition: MD.h:660
virtual void broad_phase(BaseParticle *i)
Broad phase of contact detection goes here. Default check all contacts.
Definition: MD.h:605
bool do_stat_always
Definition: MD.h:683
virtual void compute_external_forces(BaseParticle *PI)
This is were the computation of external forces takes place (e.g. gravity)
Definition: MD.cc:1410
void set_xmin(Mdouble new_xmin)
Sets xmin and walls, assuming the standard definition of walls as in the default constructor.
Definition: MD.h:318
virtual void print(std::ostream &os) const
Particle print function, which accepts an os std::stringstream as input.
void set_tmax(Mdouble new_tmax)
Allows the upper time limit to be changed.
Definition: MD.h:142
unsigned int get_options_fstat(void)
Definition: STD_save.h:159
bool useRestitution
Definition: CSpecies.h:504
virtual BaseParticle * getLargestParticle()
Definition: MD.h:419
void readObject(std::istream &is)
Reads BaseParticle into the ParticleHandler from restart data.
void Remove_Duplicate_Periodic_Particles()
Remove periodic duplicate Particles (i.e. removes particles created by Check_and_Duplicate_Periodic_P...
Definition: MD.cc:2703
void constructor()
A public constructor, which sets defaults so the problem can be solved off the shelf.
Definition: MD.cc:50
int readArguments(unsigned int argc, char *argv[])
Can interpret main function input arguments that are passed by the driver codes.
Definition: MD.cc:2535
std::vector< CSpecies > Species
These are the particle parameters like dissipation etc.
Definition: MD.h:655
void set_data_filename()
Definition: STD_save.h:144
Mdouble get_krolling(int indSpecies=0)
Allows the spring constant to be accessed.
Definition: MD.h:214
bool get_save_data_stat()
Definition: MD.h:268
int get_Index() const
Mdouble get_InvInertia() const
CDeltaMaxs & get_DeltaMaxs()
virtual void write(std::ostream &os)
Writes all MD data.
Definition: MD.cc:1985
AdhesionForceTypes AdhesionForceType
Definition: CSpecies.h:507
void solve()
The work horse of the code.
Definition: MD.cc:2266
virtual void HGRID_RemoveParticleFromHgrid(BaseParticle *obj UNUSED)
Definition: MD.h:560
Mdouble * select_particle(int P, Mdouble time_, Mdouble dt)
Function selects the tangential spring vector for particle-particle interations (also removed not use...
Definition: CDeltaMax.h:111
Mdouble get_murolling(unsigned int indSpecies=0)
Allows the Coulomb friction coefficient to be accessed.
Definition: MD.h:251
CTangentialSprings & get_TangentialSprings()
const Vec3D & get_Force() const
PossibleContact * get_Next()
void set_murolling(Mdouble new_, unsigned int indSpecies=0)
Allows the Coulomb friction coefficient to be changed.
Definition: MD.h:249
void removeLastObject()
Removes the last Object from the BaseHandler.
Definition: BaseHandler.h:147
void set_t(Mdouble new_t)
Access function for the time.
Definition: MD.h:110
bool get_save_data_fstat()
Definition: MD.h:267
void randomise()
sets the random variables such that they differ for each run
Definition: RNG.h:59
RNG random
Definition: MD.h:515
Mdouble get_ymax()
Gets ymax.
Definition: MD.h:311
Mdouble computeShortRangeForceWithParticle(BaseParticle *PI, BaseParticle *PJ, BaseParticle *PJreal, CSpecies *pSpecies, Mdouble dist)
Definition: MD.cc:1711
WallHandler wallHandler
Definition: MD.h:708
std::stringstream problem_name
Stores the problem_name.
Definition: STD_save.h:242
friend Mdouble GetLength2(const Vec3D &A)
Definition: Vector.h:183
virtual void save_restart_data()
Stores all MD data.
Definition: MD.cc:654
Vec3D delta
stores the spring
bool isFixed()
Is fixed Particle function. It returns wether a Particle is fixed or not, by cheking its inverse Mass...
Defines a pair of periodic walls. The particles are in {x: position_left<=normal*x
Mdouble get_Radius() const
void clear()
Empties the whole ParticleHandler by removing all BaseParticle.
virtual void gather_statistics_collision(int index1 UNUSED, int index2 UNUSED, Vec3D Contact UNUSED, Mdouble delta UNUSED, Mdouble ctheta UNUSED, Mdouble fdotn UNUSED, Mdouble fdott UNUSED, Vec3D P1_P2_normal_ UNUSED, Vec3D P1_P2_tangential UNUSED)
Definition: MD.h:584
virtual bool continue_solve()
Definition: MD.h:630
CTangentialSpring * select_wall_spring(int W, Mdouble time_, Mdouble dt)
Function selects the tangential spring vector for particle-particle interations (also removed not use...
Mdouble get_Mass() const
Mdouble kt
Definition: CSpecies.h:410
int restart_version
Definition: MD.h:700
Mdouble mu
Definition: CSpecies.h:417
int xballs_cmode
Definition: MD.h:695
void set_options_fstat(unsigned int new_)
set and get for file options
Definition: STD_save.h:158
Definition: CSpecies.h:30
void readObject(std::istream &is)
Reads BaseBoundary into the BoundaryHandler from restart data.
std::fstream data_file
Stream used for data files.
Definition: STD_save.h:252
void compute_particle_masses()
Computes the mass of each particle.
Definition: MD.h:618
virtual void set_initial_pressures_for_pressure_controlled_walls()
Definition: MD.h:587
bool save_data_ene
Definition: MD.h:680
void set_save_count_fstat(int new_)
Definition: MD.h:160
void set_kt(Mdouble new_, unsigned int indSpecies=0)
Allows the spring constant to be changed.
Definition: MD.h:208
Mdouble get_InvMass() const
ParticleHandler particleHandler
Definition: MD.h:707
BoundaryHandler boundaryHandler
Definition: MD.h:709
Mdouble dt
These are numerical constants like the time step size.
Definition: MD.h:671
bool get_save_data_ene()
Definition: MD.h:266
virtual void output_xballs_data_particle(int i)
This function outputs the location and velocity of the particle in a format the xballs progream can r...
Definition: MD_xballs.icc:30
const std::vector< BaseWall * >::const_iterator begin() const
Gets the begin of the const_iterator over all BaseWall in this WallHandler.
Definition: WallHandler.cc:242
virtual void process_statistics(bool usethese UNUSED)
Definition: MD.h:585
virtual void actions_after_time_step()
This is action after the time step is finished.
Definition: MD.h:570
virtual void do_integration_before_force_computation(BaseParticle *pI)
This is were the integration is done.
Definition: MD.cc:1773
Mdouble xmax
Definition: MD.h:668
Mdouble get_t()
Access function for the time.
Definition: MD.h:108
Mdouble get_ymin()
Gets ymin.
Definition: MD.h:309
const std::vector< BaseWall * >::const_iterator end() const
Gets the end of the const_iterator over all BaseWall in this WallHandler.
Definition: WallHandler.cc:254
virtual void actions_before_time_loop()
This is actions before the start of the main time loop.
Definition: MD.h:545
void statistics_from_restart_data(const char *name)
Loads all MD data and plots statistics for all timesteps in the .data file.
Definition: MD.cc:1890
Mdouble distance(BaseParticle &P)
Returns the distance of the wall to the particle, and sets left_wall = true, if the left wall is the ...
unsigned int get_options_data(void)
Definition: STD_save.h:162
virtual void fstat_header()
Definition: MD.cc:145
Mdouble max_radius
Definition: MD.h:665
virtual void finish_statistics()
Definition: MD.h:586
Mdouble t
This stores the current time.
Definition: MD.h:687
int save_count_ene
Definition: MD.h:676
Mdouble zmax
Definition: MD.h:668
Mdouble get_xmin()
Get xmin.
Definition: MD.h:305
void copyAndAddWall(const BaseWall &B)
Creates a copy of a BaseWall and adds it to the WallHandler.
Definition: WallHandler.cc:84
double Mdouble
Definition: ExtendedMath.h:33
Mdouble computeShortRangeForceWithWall(BaseParticle *pI, int wall, CSpecies *pSpecies, Mdouble dist)
Definition: MD.cc:1744
Mdouble mustorsion
Definition: CSpecies.h:422
void set_save_count_data(int new_)
Definition: MD.h:157
virtual int readNextArgument(unsigned int &i, unsigned int argc, char *argv[])
Definition: MD.cc:2554
bool increase_counter_fstat(std::fstream::openmode mode)
Definition: STD_save.h:217
void setSpecies(std::vector< CSpecies > *)
void set_do_stat_always(bool new_)
Sets how often the data is saved using the number of saves wanted, tmax, and dt. See also set_savecou...
Definition: MD.h:170
void set_dim_particle(int new_, unsigned int indSpecies=0)
Allows the dimension of the particle (f.e. for mass) to be changed.
Definition: MD.h:261
virtual bool get_HGRID_UpdateEachTimeStep()
Definition: MD.h:561
unsigned int getNumberOfWalls() const
Gets the number of BaseWalls in this WallHandler.
Definition: WallHandler.cc:224
virtual void HGRID_actions_after_integration()
Definition: MD.h:596
Mdouble get_k(int indSpecies=0)
Allows the spring constant to be accessed.
Definition: MD.h:206
bool append
Definition: MD.h:720
CTangentialSpring * getTangentialSpringWall(BaseParticle *pI, int w)
Definition: MD.cc:741
Mdouble k
Definition: CSpecies.h:409
const std::vector< T * >::const_iterator end() const
Gets the end of the const_iterator over all BaseBoundary in this BaseHandler.
Definition: BaseHandler.h:233
void set_save_count_all(int new_)
Definition: MD.h:156
virtual void actions_before_time_step()
This is action before the time step is started.
Definition: MD.h:564
Stores the tangential spring needed to compute a tangential elastic force between particles PI...
void add_Force(const Vec3D &_new)
virtual void initialize_statistics()
Functions for statistics.
Definition: MD.h:582
Mdouble get_kt(int indSpecies=0)
Allows the spring constant to be accessed.
Definition: MD.h:210
Mdouble f0
Definition: CSpecies.h:509
void set_FixedParticles(unsigned int n)
Definition: MD.h:613
bool save_data_stat
Definition: MD.h:682
virtual void compute_all_forces()
This does the force computation.
Definition: MD.cc:1935
CTangentialSpring * create_new(int P, Mdouble time_, Mdouble dt)
virtual void HGRID_UpdateParticleInHgrid(BaseParticle *obj UNUSED)
Definition: MD.h:559
Definition: CSpecies.h:29
void set_ymax(Mdouble new_ymax)
Sets ymax and walls, assuming the standard definition of walls as in the default constructor.
Definition: MD.h:331
Mdouble get_tmax()
Allows the upper time limit to be accessed.
Definition: MD.h:144
const Vec3D & get_Displacement() const
void move(const Vec3D &_new)
virtual void output_statistics()
Definition: MD.h:583
int PeriodicCreated
Definition: MD.h:722
unsigned int options_ene
Definition: STD_save.h:265
void shift_position(BaseParticle *F0)
shifts the particle (after distance set the left_wall value)
virtual void write_v1(std::ostream &os)
Writes all MD data.
Definition: MD.cc:2198
bool open_data_file(std::fstream::openmode mode=std::fstream::out)
Definition: STD_save.h:187
virtual void print(std::ostream &os UNUSED) const =0
outputs boundary
unsigned int get_options_ene(void)
Definition: STD_save.h:171
unsigned int getNumberOfObjects() const
Gets the number of Object in this BaseHandler.
Definition: BaseHandler.h:199
const Vec3D & get_Position() const
void set_mu(Mdouble new_, unsigned int indSpecies=0)
Allows the Coulomb friction coefficient to be changed.
Definition: MD.h:245
bool save_data_data
Definition: MD.h:679
int save_count_stat
Definition: MD.h:677
void set(Vec3D normal_, Mdouble position_)
Defines a standard wall, given an outward normal vector s. t. normal*x=position.
Definition: InfiniteWall.h:75
virtual bool get_distance_and_normal(BaseParticle &P UNUSED, Mdouble &distance UNUSED, Vec3D &normal_return UNUSED)=0
Mdouble mutorsion
Definition: CSpecies.h:421
virtual int createPeriodicParticles(BaseParticle *P UNUSED, ParticleHandler &pH UNUSED)
Definition: BaseBoundary.h:43
Mdouble murolling
Definition: CSpecies.h:419
Mdouble get_disp(unsigned int indSpecies=0)
Allows the normal dissipation to be accessed.
Definition: MD.h:239
Mdouble Y
Definition: Vector.h:44
unsigned int get_options_stat(void)
Definition: STD_save.h:165
unsigned int get_options_restart(void)
Definition: STD_save.h:168
CTangentialSpring * select_particle_spring(int P, Mdouble time_, Mdouble dt)
Function selects the tangential spring vector for particle-particle interations (also removed not use...
void set_rho(Mdouble new_, unsigned int indSpecies=0)
Allows the density to be changed.
Definition: MD.h:220
virtual void read(std::istream &is)
Reads all MD data.
Definition: MD.cc:2026
void set_zero()
Definition: Vector.h:55
Mdouble kc
Definition: CSpecies.h:501
Mdouble krolling
Definition: CSpecies.h:411
void add_Force(Vec3D _new)
Definition: BaseWall.h:110
virtual void print(std::ostream &os UNUSED) const =0
void add_Species(void)
Definition: MD.h:505
virtual Vec3D get_Velocity() const =0
void set_Velocity(const Vec3D &_new)
CTangentialSpring * create_new_wall(int W, Mdouble time_, Mdouble dt)
int get_counter()
This returns the current value of the counter.
Definition: STD_save.cc:85
virtual void HGRID_actions_before_integration()
Definition: MD.h:595
const Vec3D & get_Torque() const
virtual void output_xballs_data()
Output xball data for Particle i.
Definition: MD.cc:209
Mdouble get_mu(unsigned int indSpecies=0)
Allows the Coulomb friction coefficient to be accessed.
Definition: MD.h:247
void set_name(const char *name)
Sets the name of the problem, used for the same data files.
Definition: MD.h:342
Vec3D SlidingForce
Stores the force (for some non-linear, hysteretic spring models)
virtual void read_v2(std::istream &is)
Definition: MD.cc:2121
void set_file_counter(int new_)
Definition: STD_save.h:233
virtual void removeParticle(int iP)
Definition: MD.h:420
int load_restart_data()
Loads all MD data.
Definition: MD.cc:685
std::string get_data_filename()
Definition: STD_save.h:149
void set_Displacement(const Vec3D &_new)
virtual void HGRID_actions_before_time_loop()
This is actions before the start of the main time loop.
Definition: MD.h:552
Vec3D gravity
Gravitational acceleration.
Definition: MD.h:663
int indSpecies
Definition: BaseWall.h:36
Mdouble musrolling
Definition: CSpecies.h:420
This is a class defining walls.
Definition: InfiniteWall.h:42
Mdouble ene_ela
used in force calculations
Definition: MD.h:690
void set_number_of_saves_all(Mdouble N)
Definition: MD.h:172
void set_Torque(const Vec3D &_new)
Mdouble GetLength() const
Definition: Vector.h:248
ParticleHandler & getParticleHandler()
Definition: MD.h:147
Mdouble disprolling
Definition: CSpecies.h:415
void compute_plastic_internal_forces(BaseParticle *P1, BaseParticle *P2)
Computes plastic forces between particles.
Definition: MD.cc:1139
bool increase_counter_ene(std::fstream::openmode mode)
Definition: STD_save.h:228
Mdouble xballs_vscale
Definition: MD.h:696
int save_count_fstat
Definition: MD.h:678
void set_dim(int new_dim)
Allows the dimension of the simulation to be changed.
Definition: MD.h:367
virtual void HGRID_actions_before_time_step()
This is action before the time step is started.
Definition: MD.h:555
void set(Vec3D normal_, Mdouble position_left_, Mdouble position_right_)
Defines a periodic wall, given a normal vector s.t.
ForceTypes get_ForceType() const
Definition: CSpecies.h:430
bool increase_counter_data(std::fstream::openmode mode)
Definition: STD_save.h:221
Mdouble tmax
Definition: MD.h:672
Mdouble get_xmax()
Get xmax.
Definition: MD.h:307
unsigned int getStorageCapacity() const
Gets the storage capacity of this BaseHandler.
Definition: BaseHandler.h:206
std::string get_name()
Allows the problem_name to be accessed.
Definition: STD_save.h:127
Mdouble xmin
These store the size of the domain, assume walls at the ends.
Definition: MD.h:668
Mdouble get_k2max(unsigned int indSpecies=0)
Definition: MD.h:194
virtual BaseParticle * getSmallestParticle()
Definition: MD.h:418
void set_gravity(Vec3D new_gravity)
Allows the gravitational acceleration to be changed.
Definition: MD.h:362
BaseWall * getWall(const unsigned int id) const
Gets a pointer to the BaseWall at the specified index in the WallHandler.
Definition: WallHandler.cc:203
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:40
virtual void checkInteractionWithBoundaries()
Definition: MD.cc:1794
void set_disprolling(Mdouble new_, unsigned int indSpecies=0)
Allows the tangential viscosity to be changed.
Definition: MD.h:228
unsigned int options_data
Definition: STD_save.h:263
bool read_next_from_data_file(unsigned int format=0)
by default format do not pass an argument; only specify format if you have to read a special format (...
Definition: MD.cc:453
Vec3D get_gravity()
Allows the gravitational acceleration to be accessed.
Definition: MD.h:364
void auto_number()
Definition: STD_save.h:116
void set_ymin(Mdouble new_ymin)
Definition: MD.h:320
void set_options_stat(unsigned int new_)
Definition: STD_save.h:164
bool increase_counter_stat(std::fstream::openmode mode)
Definition: STD_save.h:224
Stores properties of the particles and the contact models such as the elastic modulus.
Definition: CSpecies.h:56
void set_Position(const Vec3D &_new)
void accelerate(const Vec3D &_new)
virtual void compute_walls(BaseParticle *PI)
This is were the walls are.
Definition: MD.cc:1423
bool open_ene_file(std::fstream::openmode mode=std::fstream::out)
Definition: STD_save.h:193
void set_dispt(Mdouble new_, unsigned int indSpecies=0)
Allows the tangential viscosity to be changed.
Definition: MD.h:224
int save_count_data
These are informations for saving.
Definition: MD.h:675
Mdouble Z
Definition: Vector.h:44
Mdouble ymin
Definition: MD.h:668
void set_ene_filename()
Definition: STD_save.h:146
void update_disp(Mdouble mass1, Mdouble mass2)
Definition: CSpecies.h:165
Mdouble get_zmax()
Gets zmax.
Definition: MD.h:315
void clear()
Empties the whole WallHandler by removing all BaseWall.
Definition: WallHandler.cc:127
void set_k(Mdouble new_, unsigned int indSpecies=0)
Allows the spring constant to be changed.
Definition: MD.h:204
int Check_and_Duplicate_Periodic_Particles()
Calls Check_and_Duplicate_Periodic_Particle for all Particles curently in Particles[] and returns the...
Definition: MD.cc:2719
Mdouble ktorsion
Definition: CSpecies.h:412
void add_Torque(Vec3D _new)
Definition: BaseWall.h:111
virtual void compute_internal_forces(BaseParticle *i)
Computes the forces between particles (internal in the sence that the sum over all these forces is ze...
Definition: MD.cc:1980
void clear()
Empties the whole BaseHandler by removing all Object.
Definition: BaseHandler.h:162
Mdouble zmin
Definition: MD.h:668
Mdouble dispt
Definition: CSpecies.h:414
Mdouble ymax
Definition: MD.h:668
void set_save_count_ene(int new_)
Definition: MD.h:158
virtual void print(std::ostream &os, bool print_all=false)
Outputs MD.
Definition: MD.cc:1806
void set_RandomSeed(Mdouble new_seed)
This is the seed for the random number generator.
Definition: RNG.h:46
void fixParticle()
Fix Particle function. It fixes a Particle by setting its inverse mass and inertia and velocities to ...
bool get_do_stat_always()
Definition: MD.h:269
std::fstream ene_file
Definition: STD_save.h:255
Particle * get_P1()
void set_disp(Mdouble new_, unsigned int indSpecies=0)
Allows the normal dissipation to be changed.
Definition: MD.h:237
const Vec3D & get_AngularVelocity() const
void set_options_ene(unsigned int new_)
Definition: STD_save.h:170
void set_xmax(Mdouble new_xmax)
Sets xmax and walls, assuming the standard definition of walls as in the default constructor.
Definition: MD.h:328
int data_FixedParticles
Definition: MD.h:702
virtual void create_xballs_script()
This creates a scipt which can be used to load the xballs problem to display the data just generated...
Definition: MD_xballs.icc:84