MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ChargedBondedInteraction.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 
29 #include "Particles/BaseParticle.h"
30 #include "InteractionHandler.h"
31 #include <iomanip>
32 #include <assert.h>
33 
36 
43  : BaseInteraction(P, I, timeStamp)
44 {
45  //ensuring that, by default, particles are not 'bonded'
46  //i.e. they will not unintentionally 'stick' to any overlapping particles!
47  bonded_ = false;
48 #ifdef DEBUG_CONSTRUCTOR
49  std::cout<<"ChargedBondedInteraction::ChargedBondedInteraction() finished"<<std::endl;
50 #endif
51 }
52 
57  : BaseInteraction(p)
58 {
59  //carrying the history parameter over for copied particles to ensure that any bonded particles
60  //remain bonded!
61  bonded_ = p.bonded_;
62 #ifdef DEBUG_CONSTRUCTOR
63  std::cout<<"ChargedBondedInteraction::ChargedBondedInteraction(const ChargedBondedInteraction &p finished"<<std::endl;
64 #endif
65 }
66 
71 {
72 #ifdef DEBUG_DESTRUCTOR
73  std::cout<<"ChargedBondedInteraction::ChargedBondedInteractionaction() finished"<<std::endl;
74 #endif
75 }
76 
80 void ChargedBondedInteraction::write(std::ostream& os UNUSED) const
81 {
82  os << " bonded " << bonded_;
83 }
84 
88 void ChargedBondedInteraction::read(std::istream& is UNUSED)
89 {
90  std::string dummy;
91  //logger(INFO,"ChargedBondedSpecies %",dummy);
92  is >> dummy >> bonded_;
93 }
98 {
99 
100  const ChargedBondedSpecies* species = getSpecies();
101  //std::cout << getSpecies()->getCharge() << std::endl;
102 
103  //creating local parameters to store the charges of both particles
104  //involved in the interaction to allow for quick calculation
105  const auto pSpecies = dynamic_cast<const ChargedBondedSpecies*>(getP()->getSpecies());
106  const auto iSpecies = dynamic_cast<const ChargedBondedSpecies*>(getI()->getSpecies());
107  assert(pSpecies);
108  assert(iSpecies);
109  const int pCharge = pSpecies->getCharge();
110  const int iCharge = iSpecies->getCharge();
111 
112  //similarly, creating local parameters to store the relevant stiffness
113  //and max force values
114  const Mdouble k = species->getAdhesionStiffness();
115  const Mdouble fMax = species->getAdhesionForceMax();
116 
117  const Mdouble kWaals = species->getVanDerWaalsStiffness();
118  const Mdouble fMaxWaals = species->getVanDerWaalsForceMax();
119  const Mdouble rWaals = fMaxWaals / kWaals;
120 
121 
122  //First, adding bonded force if applicable
123  if (bonded_ && getOverlap()>=0)
124  {
125  addForce(getNormal() * (-species->getBondForceMax()
127  return;
128  }
129 
130 
131  //determining which of the three possible cases for force based on charge -
132  //repulsive (like charges), attractive (unlike charges) or none (1 or more uncharged) -
133  //is relevant for the current combination of particle charges...
134  //(Note that the charge set function contains a safety check that means charge can only be
135  // +/- 1, i.e. the expressions used below should not produce errors!
136 
137  //case 1 - 1 or more particles has no charge, i.e. no EM force between them
138  if ( (pCharge == 0) or (iCharge == 0) )
139  {
140  //No need to write anything here as nothing needs to be returned!
141  //std::cout << "no charge" << std::endl;
142  }
143  //case 2: unlike charges --> attractive force
144  else if (pCharge == -iCharge)
145  {
146  //std::cout << "dissimilar charge" << std::endl;
147  //in the case of particles with opposing charges, simply implements the
148  //standard attractive force used for adhesive particle interactions
149  if (getOverlap() >= 0)
150  {
151  addForce(getNormal() * -fMax);
152  addForce(getNormal() * -fMaxWaals);
153  }
154  else if (getOverlap() >= -rWaals)
155  {
156  addForce(getNormal() * (-kWaals * getOverlap() - fMaxWaals));
157  addForce( getNormal() * (-k * getOverlap() - fMax));
158  }
159  else
160  {
161  addForce( getNormal() * (-k * getOverlap() - fMax));
162  }
163  }
164  //case 3: like charges --> repulsive force
165  else if (pCharge == iCharge)
166  {
167  //std::cout << "similar charge" << std::endl;
168  //in the case of particles with like charges, reverse the direction of the force applied
169  //such that particles repel one another
170  if (getOverlap() >= 0)
171  {
172  addForce(getNormal() * +fMax);
173  addForce(getNormal() * -fMaxWaals);
175  }
176  else if (getOverlap() >= -rWaals)
177  {
178  addForce(getNormal() * (-kWaals * getOverlap() - fMaxWaals));
179  addForce(getNormal() * (+k * getOverlap() + fMax));
180  //std::cout << "Waals = " << getNormal() * (-kWaals * getOverlap() - fMaxWaals) << std::endl;
181  }
182  else
183  {
184  addForce(getNormal() * (+k * getOverlap() + fMax));
185  }
186  }
187  //if none of the above are satisfied, something must have gone very wrong!
188  else
189  {
190  std::cerr << "Error: Particle charge has erroneous value" << std::endl;
191  exit(-1);
192  }
193 }
194 
201 {
202  const ChargedBondedSpecies* species = getSpecies();
203  const auto pSpecies = dynamic_cast<const ChargedBondedSpecies*>(getP()->getSpecies());
204  const auto iSpecies = dynamic_cast<const ChargedBondedSpecies*>(getI()->getSpecies());
205  assert(pSpecies);
206  assert(iSpecies);
207  const int pCharge = pSpecies->getCharge();
208  const int iCharge = iSpecies->getCharge();
209 
210  const Mdouble k = species->getAdhesionStiffness();
211  const Mdouble fMax = species->getAdhesionForceMax();
212  const Mdouble r = species->getInteractionDistance();
213 
214  const Mdouble kWaals = species->getVanDerWaalsStiffness();
215  const Mdouble fMaxWaals = species->getVanDerWaalsForceMax();
216  const Mdouble rWaals = (fMaxWaals==0)?0:(fMaxWaals/kWaals);
217 
218 
219  //First, adding bonded force if applicable
220  if (bonded_ && getOverlap()>=0)
221  {
222  //comment to ignore BondForce
223  Mdouble elasticEnergyAtEquilibrium = getElasticEnergyAtEquilibrium(species->getBondForceMax());
224  return -species->getBondForceMax()*getOverlap()+elasticEnergyAtEquilibrium;
225  }
226 
227  Mdouble elasticEnergy = 0.0;
228  if ( (pCharge != 0) && (iCharge != 0) )
229  {
230  if (pCharge == -iCharge)
231  {
232  if (getOverlap() >= 0)
233  {
234  elasticEnergy -= (0.5 * rWaals + getOverlap()) * fMaxWaals
235  + (0.5 * r + getOverlap()) * fMax;
236  }
237  else if (getOverlap() >= -rWaals)
238  {
239  elasticEnergy -= (0.5 * kWaals * mathsFunc::square(getOverlap() + rWaals)) +
240  (0.5 * k * mathsFunc::square(getOverlap() + r));
241  }
242  else
243  {
244  elasticEnergy -= (0.5 * k * mathsFunc::square(getOverlap() + r));
245  }
246  }
247  //case 3: like charges --> repulsive force
248  else if (pCharge == iCharge)
249  {
250  if (getOverlap() >= 0)
251  {
252  elasticEnergy -= (0.5 * rWaals + getOverlap()) * fMaxWaals
253  - (0.5 * r + getOverlap()) * fMax;
254  }
255  else if (getOverlap() >= -rWaals)
256  {
257  elasticEnergy -= (0.5 * kWaals * mathsFunc::square(getOverlap() + rWaals)) -
258  (0.5 * k * mathsFunc::square(getOverlap() + r));
259  }
260  else
261  {
262  elasticEnergy += (0.5 * k * mathsFunc::square(getOverlap() + r));
263  }
264  }
265  else
266  {
267  logger(ERROR,"Particle charge has erroneous value");
268  }
269  }
270  return elasticEnergy;
271 }
276 {
277  return dynamic_cast<const ChargedBondedSpecies *> (getBaseSpecies()); //downcast
278 }
283 {
284  return "ChargedBonded";
285 }
286 
292 {
293  bonded_=true;
294 }
295 
302 {
303  bonded_=false;
304 }
void write(std::ostream &os) const
Interaction print function, which accepts an std::ostream as input.
ChargedBondedInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp)
Constructor.
Mdouble getVanDerWaalsForceMax() const
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
const ParticleSpecies * getSpecies() const
Returns a pointer to the species of this BaseInteractable.
std::string getBaseName() const
Returns the name of the interaction, see Interaction.h.
void read(std::istream &is)
Interaction read function, which accepts an std::istream as input.
Mdouble getAdhesionForceMax() const
Allows the spring constant to be accessed.
double Mdouble
T square(T val)
squares a number
Definition: ExtendedMath.h:91
Stores information about interactions between two interactable objects; often particles but could be ...
ChargedBondedSpecies contains the parameters used to describe a linear reversible short-range force...
Mdouble getBondDissipation() const
Allows the additional dissipation used to damp oscillations between bondd particles to be accessed...
Mdouble getVanDerWaalsStiffness() const
Mdouble getNormalRelativeVelocity() const
Returns a double which is the norm (length) of the relative velocity vector.
Mdouble getInteractionDistance() const
returns the largest separation distance at which adhesive short-range forces can occur.
Mdouble getElasticEnergy() const
Returns the amount of Elastic energy involved in an interaction. Basically used in case you want to w...
const BaseSpecies * getBaseSpecies() const
Return a constant point to BaseSpecies of the interaction.
const Vec3D & getNormal() const
Gets the normal vector between the two interacting objects.
#define UNUSED
Definition: GeneralDefine.h:39
Mdouble getAdhesionStiffness() const
Allows the spring constant to be accessed.
Mdouble getOverlap() const
Returns a Mdouble with the current overlap between the two interacting objects.
void addForce(Vec3D force)
add an force increment to the total force.
const ChargedBondedSpecies * getSpecies() const
A dynamic_cast of BaseSpecies pointer type to a pointer to an object of type ChargedBondedSpecies.
#define assert(e,...)
Definition: Logger.h:584
BaseInteractable * getI()
Mdouble getBondForceMax() const
Allows the maximal force for 'bonding' particles together to be accessed.
virtual Mdouble getElasticEnergyAtEquilibrium(Mdouble adhesiveForce) const
void bond()
A pair of functions which can be used to fix or unfix a pair of overlapping particles.
Defines the basic properties that a interactable object can have.
void computeAdhesionForce()
Computes the adhesive forces.
BaseInteractable * getP()
Returns a pointer to first object involved in the interaction (normally a particle).
bool bonded_
A history parameter to store if the particles were in contact or not. Useful to compute adhesive forc...
virtual ~ChargedBondedInteraction()
Destructor.