MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InteractionHandler.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 #include <iostream>
26 #include <iomanip>
27 #include <string>
28 #include <stdlib.h>
29 #include "Particles/BaseParticle.h"
30 #include "InteractionHandler.h"
31 #include "SpeciesHandler.h"
32 #include "Species/BaseSpecies.h"
34 #include "DPMBase.h"
35 
40 {
42  logger(DEBUG, "InteractionHandler::InteractionHandler() finished");
43 }
44 
53 {
54  writeVTK_ = IH.writeVTK_;
55  //By default interactions are not copied.
56  logger(DEBUG, "InteractionHandler::InteractionHandler(const "
57  "InteractionHandler &IH) finished, please note that no interactions"
58  " have been copied.");
59 }
60 
65 {
66  if (this != &rhs)
67  {
68  clear();
69  }
70  writeVTK_ = rhs.writeVTK_;
71  logger(DEBUG, "InteractionHandler::operator =(const InteractionHandler& rhs) finished.");
72  return *this;
73 }
74 
76 {
77  logger(DEBUG, "InteractionHandler::~InteractionHandler() finished");
78 }
79 
84 {
85  //Puts the particle in the Particle list
87  //set the particleHandler pointer
88  I->setHandler(this);
89 }
90 
97 {
98  //for particle-particle collision it is assumed BaseInteractable P has a lower index then I, so we only have to check for I, not P
99  for (BaseInteraction* i : P->getInteractions())
100  {
101  if (i->getI() == I)
102  {
103  return i;
104  }
105  }
106  return nullptr;
107 }
108 
118 {
120 
121  //std::cout << "Trying to reconnect to BaseInteraction between P=" << P->getId() << " and " << I->getId() << std::endl;
123  if (C == nullptr)
124  {
125  C = species->getNewInteraction(P, I, timeStamp);
126  addObject(C);
127  //std::cout << "Creating new interaction with index=" << getLastObject()->getIndex() << " id=" << getLastObject()->getId() << std::endl;
128  }
129 
130  //set timeStamp
131  C->setTimeStamp(timeStamp);
132 
134  //set species of collision
135  C->setSpecies(species);
136 
137  return C;
138 }
139 
150 {
151  BaseInteraction* c = nullptr;
152  Mdouble dNormalMax = 0.9; //minimal agreement required
153  for (const auto& i : P->getInteractions())
154  {
155  if (i->getI() == I && i->getTimeStamp() != timeStamp)
156  {
157  const Mdouble dNormal = Vec3D::dot(normal, i->getNormal());
158  if (dNormal > dNormalMax)
159  {
160  c = i;
161  dNormalMax = dNormal;
162  }
163  }
164  }
165 
167 
168  if (c)
169  {
170  c->setTimeStamp(timeStamp);
171  } else
172  {
173  c = species->getNewInteraction(P, I, timeStamp);
174  c->setSpecies(species);
175  addObject(c);
176  //logger(INFO,"new interaction t=%: i=%, n=%",timeStamp,getNumberOfObjects(),normal);
177  }
178 
179  return c;
180 }
181 
201 {
202  BaseInteraction* iMain = getObject(id);
203 
204  BaseParticle* P = dynamic_cast<BaseParticle*>(iMain->getP());
205  BaseParticle* I = dynamic_cast<BaseParticle*>(iMain->getI());
206  if (P != nullptr && I != nullptr) //check that both P and I are particles (not walls)
207  {
209  if (realI != nullptr && !P->getPeriodicFromParticle()) //check that P is a real and I is a ghost particle
210  {
211  if (P->getIndex() < realI->getIndex())
212  {
213  BaseInteraction* iOther = getExistingInteraction(P, realI);
214  //You have to also check for existing interactions of the particles in reverse order since the copySwitchPointer function can revert the order of the particles
216  if (iOther == nullptr)
217  {
218  iOther = getExistingInteraction(realI, P);
219  }
220  if (iOther != nullptr) //if the interaction existed before the ghost particles were created
221  {
222  //Here we decide which of the two interactions should be kept:
223  //the interaction between the two real particles (iMain), or
224  //the interaction between the real and a ghost particle (iOther).
225  //It picks the one for which a collision has happened,
226  //i.e. the one with the newer timeStamp.
228  if (iOther->getTimeStamp() < iMain->getTimeStamp()) //if the interaction has been active during the last computeForce routine, make this the new (real) interaction.
229 
230  {
231  iMain->setI(realI);
232  removeObject(iOther->getIndex());
233  return;
234  }
235  else //if the interaction has not been active during the last computeForce routine
236  {
238  return;
239  }
240  }
241  else //if the interaction has been created during the last computeForce routine, make this a new (real) interaction.
242  {
243  iMain->setI(realI);
244  return;
245  }
246  }
247  }
248  }
249  //this point is reached if either P or I are walls, or P and I are both ghost particles; in these cases, the interaction gets deleted
251 }
252 
261 {
262  //std::cout<<"void InteractionHandler::eraseOldInteractions(Mdouble lastTimeStep)"<<std::endl;
263  //std::cout<<"Current interactions="<<getNumberOfObjects()<<std::endl;
264  //Remove_if reconstructs the vector with only elements passing the check_spring_time function
265  //Erase removes the end of the vector
267  for (unsigned int id = 0; id < getNumberOfObjects(); id++)
268  {
269  if (getObject(id)->getTimeStamp() <= lastTimeStep)
270  {
271  getObject(id)->actionsOnErase();
272  removeObject(id);
273  --id;
274  }
275  }
276 }
277 
279 {
280  for (auto i: *this)
281  {
282  i->actionsAfterTimeStep();
283  }
284 }
285 
290 {
291  Mdouble sum = 0;
292  for (BaseInteraction* const p : objects_)
293  {
294  sum += p->getOverlap();
295  }
296  return sum / getNumberOfObjects();
297 }
298 
302 std::string InteractionHandler::getName() const
303 {
304  return "InteractionHandler";
305 }
306 
311 void InteractionHandler::write(std::ostream& os) const
312 {
313  os << "Interactions " << getNumberOfObjects() << std::endl;
314  for (BaseInteraction* i : objects_)
315  os << (*i) << std::endl;
316 }
317 
321 void InteractionHandler::readObject(std::istream& is)
322 {
323  std::string type, dummy, idType;
324  unsigned int id0, id1;
325  Mdouble timeStamp;
326 
327  std::stringstream line(std::stringstream::in | std::stringstream::out);
329 
330  line >> type >> idType >> id0 >> id1 >> dummy >> timeStamp;
331  logger(VERBOSE, "InteractionHandler::readObject(is): reading type % % %", type, id0, id1);
333  BaseInteraction* C;
334  if (idType.compare("particleIds") == 0) {
335 // C = getDPMBase()->particleHandler.getObjectById(id1)->getInteractionWith(getDPMBase()->particleHandler.getObjectById(id0), timeStamp, this)[0];
336  C = getInteraction(getDPMBase()->particleHandler.getObjectById(id0),
337  getDPMBase()->particleHandler.getObjectById(id1), timeStamp);
338  }
339  else {
340 // C = getDPMBase()->wallHandler.getObjectById(id1)->getInteractionWith(getDPMBase()->particleHandler.getObjectById(id0), timeStamp, this)[0];
341  C = getInteraction(getDPMBase()->particleHandler.getObjectById(id0),
342  getDPMBase()->wallHandler.getObjectById(id1), timeStamp);
343  }
344  line >> (*C);
345 }
346 
354 {
356  return;
357 
358  static unsigned fileCounter = 0;
359  const std::string fileName = getDPMBase()->getName() + "Interaction_" +
360  std::to_string(fileCounter++) + ".vtu";
361  logger(INFO, "writing % (t=%, N=%)", fileName, getDPMBase()->getTime(), this->getNumberOfObjects());
362 
363  std::fstream file;
364  file.open(fileName.c_str(), std::ios::out);
365  if (file.fail())
366  {
368  logger(WARN, "Error in writeToFile: file % could not be opened", fileName);
369  }
370 
371  file << "<?xml version=\"1.0\"?>\n\n";
372  file << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
373  file << "<UnstructuredGrid>\n";
374  file << "<Piece NumberOfPoints=\"" << this->getNumberOfObjects() << "\" NumberOfCells=\"" << 0 << "\">\n";
375  file << "<Points>\n";
376  file << " <DataArray type=\"Float32\" Name=\"Position\" NumberOfComponents=\"3\" format=\"ascii\">\n";
377  for (const auto &p: *this)
378  {
379  file << '\t' << p->getContactPoint() << '\n';
380  }
381  file << " </DataArray>\n";
382  file << "</Points>\n";
383  file << "<PointData Vectors=\"vector\">\n";
384  file << " <DataArray type=\"Float32\" Name=\"Normal\" NumberOfComponents=\"3\" format=\"ascii\">\n";
385  // Add velocity
386  for (const auto &p: *this)
387  {
388  file << '\t' << p->getNormal() << '\n';
389  }
390  file << " </DataArray>\n";
391  file << " <DataArray type=\"Float32\" Name=\"Overlap\" format=\"ascii\">\n";
392  // Add radius
393  for (const auto &p: *this)
394  {
395  file << '\t' << p->getOverlap() << '\n';
396  }
397  file << " </DataArray>\n";
398  file << " <DataArray type=\"Float32\" Name=\"ContactRadius\" format=\"ascii\">\n";
399  // Add radius
400  for (const auto &p: *this)
401  {
402  file << '\t' << p->getContactRadius() << '\n';
403  }
404  file << " </DataArray>\n";
405  file << " <DataArray type=\"Float32\" Name=\"Force\" format=\"ascii\">\n";
406  // Add species type
407  for (const auto &p: *this)
408  {
409  file << '\t' << p->getForce() << '\n';
410  }
411  file << " </DataArray>\n";
412  file << " <DataArray type=\"Float32\" Name=\"TangentialOverlap\" format=\"ascii\">\n";
413  // Add species type
414  for (const auto &p: *this)
415  {
416  file << '\t' << p->getTangentialOverlap() << '\n';
417  }
418  file << " </DataArray>\n";
419  file << " <DataArray type=\"Float32\" Name=\"Torque\" format=\"ascii\">\n";
420  // Add species type
421  for (const auto &p: *this)
422  {
423  file << '\t' << p->getTorque() << '\n';
424  }
425  file << " </DataArray>\n";
426  //check if this type of Interaction has extra fields
427  if (getLastObject()!= nullptr)
428  {
429  for (unsigned i = 0; i<getLastObject()->getNumberOfFieldsVTK(); i++)
430  {
431  file << " <DataArray type=\"" << getLastObject()->getTypeVTK(i) << "\" Name=\"" << getLastObject()->getNameVTK(i) << "\" format=\"ascii\">\n";
432  // Add species type
433  for (const auto &p: *this)
434  {
435  for (auto f : p->getFieldVTK(i))
436  file << '\t' << f << '\n';
437  }
438  file << " </DataArray>\n";
439  }
440  }
441  file << "</PointData>\n";
442  file << "<Cells>\n";
443  file << " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n";
444  file << " </DataArray>\n";
445  file << " <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n";
446  file << " </DataArray>\n";
447  file << " <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n";
448  file << " </DataArray>\n";
449  file << "</Cells>\n";
450  file << "</Piece>\n";
451  file << "</UnstructuredGrid>\n";
452  file << "</VTKFile>\n";
453  file.close();
454 }
455 
457  writeVTK_ = fileType;
458 }
459 
461  return writeVTK_;
462 }
void writeVTK() const
Writes all particles into a vtk file format (unstructured grid), consisting of particle positions...
unsigned int getIndex() const
Returns the index of the object in the handler.
Definition: BaseObject.cc:108
virtual void actionsOnErase()
If an interaction needs to do something before it gets erased, add it here. E.g. Liquid bridges ruptu...
BaseSpecies is the class from which all other species are derived.
Definition: BaseSpecies.h:44
void write(std::ostream &os) const
Writes the InteractionHandler to an output stream, for example a restart file.
FileType getWriteVTK() const
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
T * getObjectById(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
Definition: BaseHandler.h:429
void setI(BaseInteractable *I)
Sets the second object involved in the interaction (often particle or wall).
BaseInteraction * getInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp)
Returns the Interaction between the BaseInteractable's P and I.
double Mdouble
InteractionHandler()
Default constructor, it creates an empty InteractionHandler.
~InteractionHandler()
Destructor, it destructs the InteractionHandler and all BaseInteraction it contains.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:167
Mdouble getTimeStamp() const
Returns an Mdouble which is the time stamp of the interaction.
Mdouble getMeanOverlap() const
The mean overlap of all interactions.
void setSpecies(BaseSpecies *species)
Set the Species of the interaction; note this can either be a Species or MixedSpecies.
Stores information about interactions between two interactable objects; often particles but could be ...
void eraseOldInteractions(Mdouble lastTimeStep)
erases interactions which have an old timestamp.
FileType
With FileType options, one is able to choose if data is to be read/written from/into no or single or ...
Definition: File.h:35
BaseParticle * getPeriodicFromParticle() const
Returns the 'original' particle this one's a periodic copy of.
void setTimeStamp(Mdouble timeStamp)
Updates the time step of the interacting. Note, timesteps used to find completed interactions.
void removeObjectKeepingPeriodics(unsigned const int id)
Removes interactions of periodic particles when the periodic particles get deleted (see DPMBase::remo...
file will not be created/read
InteractionHandler operator=(const InteractionHandler &rhs)
Assignment operator.
void getLineFromStringStream(std::istream &in, std::stringstream &out)
Reads a line from one stringstream into another, and prepares the latter for reading in...
Definition: Helpers.cc:396
virtual void removeObject(unsigned const int id)
Removes an Object from the BaseHandler.
ParticleHandler particleHandler
An object of the class ParticleHandler, contains the pointers to all the particles created...
Definition: DPMBase.h:1001
Container to store Interaction objects.
BaseInteraction * getObject(const unsigned int id)
Gets a pointer to the Object at the specified index in the BaseHandler.
void setHandler(InteractionHandler *handler)
Sets the pointer to the interaction hander which is storing this interaction.
virtual std::string getTypeVTK(unsigned i) const
std::string getName() const
Returns the name of the object.
#define UNUSED
Definition: GeneralDefine.h:39
std::vector< BaseInteraction * > objects_
The actual list of Object pointers.
Definition: BaseHandler.h:216
Container to store the pointers to all objects that one creates in a simulation.
Definition: BaseHandler.h:51
virtual std::string getNameVTK(unsigned i) const
unsigned int getNumberOfObjects() const
Gets the number of Object in this BaseHandler.
SpeciesHandler speciesHandler
A handler to that stores the species type i.e. elastic, linear visco-elastic... et cetera...
Definition: DPMBase.h:991
std::enable_if<!std::is_pointer< typename U::MixedSpeciesType >::value, typename U::MixedSpeciesType * >::type getMixedObject(const U *S, const U *T)
WallHandler wallHandler
An object of the class WallHandler. Contains pointers to all the walls created.
Definition: DPMBase.h:1006
void setWriteVTK(FileType f)
std::string to_string(const T &n)
Definition: Helpers.h:203
BaseInteractable * getI()
virtual void addObject(T *object)
Adds a new Object to the BaseHandler.
Definition: BaseHandler.h:313
Defines the basic properties that a interactable object can have.
BaseInteraction * getExistingInteraction(BaseInteractable *P, BaseInteractable *I) const
Returns the Interaction between the BaseInteractable's P and I if it exists, otherwise returns a null...
void readObject(std::istream &is)
Reads an Interaction into the InteractionHandler from restart data.
const std::list< BaseInteraction * > & getInteractions() const
Returns a reference to the list of interactions in this BaseInteractable.
unsigned int getIndSpecies() const
Returns the index of the Species of this BaseInteractable.
BaseInteraction * getLastObject()
Gets a pointer to the last Object in this BaseHandler.
BaseInteractable * getP()
Returns a pointer to first object involved in the interaction (normally a particle).
Implementation of a 3D vector (by Vitaliy).
Definition: Vector.h:45
DPMBase * getDPMBase()
Gets the problem that is solved using this handler.
void addObject(BaseInteraction *I)
Adds an Interaction to the InteractionHandler.
const std::string & getName() const
Returns the name of the file. Does not allow to change it though.
Definition: Files.cc:132
virtual BaseInteraction * getNewInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp) const =0
returns new Interaction object.
void clear()
Empties the whole BaseHandler by removing all Objects and setting all other variables to 0...
virtual unsigned getNumberOfFieldsVTK() const