MercuryDPM  Alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SinterInteraction.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 
27 #include "SinterInteraction.h"
28 #include "InteractionHandler.h"
29 #include "Particles/BaseParticle.h"
30 #include "DPMBase.h"
33 
40  : BaseInteraction(P, I, timeStamp)
41 {
43 #ifdef DEBUG_CONSTRUCTOR
44  std::cout<<"SinterInteraction::SinterInteraction() finished"<<std::endl;
45 #endif
46 }
51  : BaseInteraction(p)
52 {
54 #ifdef DEBUG_CONSTRUCTOR
55  std::cout<<"SinterInteraction::SinterInteraction(const SinterInteraction &p finished"<<std::endl;
56 #endif
57 }
62 {
63 #ifdef DEBUG_DESTRUCTOR
64  std::cout<<"SinterInteraction::~SinterInteraction() finished"<<std::endl;
65 #endif
66 }
67 
72 void SinterInteraction::write(std::ostream& os) const
73 {
75  os << " plasticOverlap " << plasticOverlap_;
76 }
81 void SinterInteraction::read(std::istream& is)
82 {
84  std::string dummy;
85  is >> dummy >> plasticOverlap_;
86 }
90 std::string SinterInteraction::getBaseName() const
91 {
92  return "Sinter";
93 }
94 
99 {
100  // Compute the relative velocity vector of particle P w.r.t. I
101  setRelativeVelocity(getP()->getVelocityAtContact(getContactPoint()) - getI()->getVelocityAtContact(getContactPoint()));
102  // Compute the projection of vrel onto the normal (can be negative)
104 
105  if (getOverlap() > 0) //if contact forces
106  {
107  const SinterNormalSpecies* species = getSpecies();
108  // calculate the effective diameter, equal to the radius for two equal-sized particles
109  const Mdouble effectiveDiameter = 2.0 * getEffectiveRadius();
110  //calculate the overlap above which the max. unloading stiffness
111  //becomes active (the 'fluid branch')
112  const Mdouble deltaStar = species->getPenetrationDepthMax() * effectiveDiameter;
113  //compute the rate d(k2/k1)/d(delta0)
114  const Mdouble dk = (species->getUnloadingStiffnessMax()/species->getLoadingStiffness() - 1.0)/deltaStar;
115 
116  //increase max overlap if necessary
117  //k2*(d-d0)=k1*d, k2=k1*(1+dk*d)
118  //(1+dk*d)*(d-d0)=d
119  //dk*d^2=(1+dk*d)*d0
120  //d0=d/(1+1/(dk*d))
121  const Mdouble minPlasticOverlap = std::min(getOverlap()/(1.0+1.0/(dk*getOverlap())),deltaStar);
128  //const Mdouble minPlasticOverlap = std::min(getOverlap()-1.0/dk,deltaStar);
129  //logger(INFO,"minPlasticOverlap % overlap % dk % M %",minPlasticOverlap,getOverlap(),dk, dk*getOverlap());
130  plasticOverlap_ = std::max(minPlasticOverlap,plasticOverlap_);
131 
132  //calculate the unloading stiffness (only linear in maxOverlap, not equilibriumOverlap))
133  const Mdouble unloadingStiffness = species->getLoadingStiffness() * (1.0+dk*plasticOverlap_);
134 
135  //compute elastic force
136  Mdouble normalForce = unloadingStiffness * (getOverlap() - plasticOverlap_);
137 
138  //add cohesive forces (distinct from sintering)
139  Mdouble nonSinterAdhesiveForce = -species->getCohesionStiffness() * getOverlap();
140  if (normalForce < nonSinterAdhesiveForce) {
141  plasticOverlap_ = (1.0 + species->getCohesionStiffness()/unloadingStiffness)*getOverlap();
142  normalForce = nonSinterAdhesiveForce;
143  }
144 
145  //add dissipative force (distinct from sintering)
146  normalForce -= species->getDissipation() * getNormalRelativeVelocity();
147 
148  //Here comes the sintering effect:
149  Mdouble adhesiveForce = species->getSinterAdhesion()*effectiveDiameter;
150 
151  //now set the interaction force equal to this normal force (friction and adhesive forces will be added later)
152  setForce(getNormal() * ((normalForce-adhesiveForce)));
153  setTorque(Vec3D(0.0, 0.0, 0.0));
154  //used for tangential force calculations; don't add adhesive force components
155  setAbsoluteNormalForce(std::abs(normalForce));
156 
157  //increase plastic overlap due to sintering
158  DPMBase* dpmBase = getHandler()->getDPMBase();
159  Mdouble rateOverlap;
160  // sinter adhesion force fa=sinterAdhesion_*radius in sinter rate:
162  rateOverlap = normalForce*species->getSinterRate()/
163  (0.375*species->getSinterAdhesion()*mathsFunc::square(getOverlap()/effectiveDiameter));
164  if (species->getSinterRate()==0) rateOverlap = 0;
165  } else if (species->getSinterType()==SINTERTYPE::CONSTANT_RATE) {
166  rateOverlap = 2.0*normalForce*species->getSinterRate()/species->getSinterAdhesion();
167  if (species->getSinterRate()==0) rateOverlap = 0;
169  ThermalParticle* tp = dynamic_cast<ThermalParticle*>(getP());
170  ThermalParticle* ti = dynamic_cast<ThermalParticle*>(getI());
171  logger.assert(tp && ti,"warning contact partners have to be ThermalParticle's if this sinter species is used");
172  double temperature = 2.0*tp->getTemperature()*ti->getTemperature()/(tp->getTemperature()+ti->getTemperature());
173  rateOverlap = 2.0*normalForce*species->getTemperatureDependentSinterRate(temperature)/species->getSinterAdhesion();
174  } else {
175  //missing: add the sintering model 'modified Frenkel' of the Pokula paper
176  }
177  plasticOverlap_ = std::max(0.0,std::min(deltaStar,plasticOverlap_+rateOverlap*dpmBase->getTimeStep()));
178 
179  /*//change particle radius by dr
180  Mdouble dr;
181  BaseParticle* PParticle = dynamic_cast<BaseParticle*>(getP());
182  BaseParticle* IParticle = dynamic_cast<BaseParticle*>(getI());
183  if (dpmBase->getSystemDimensions()==2) {
184  //2D: increase the radius of each particle such that the particle area
185  //increases by the same amount that the contact area decreases
186  //Particle circumference C = 2 pi r increased by dr => dA = 2 pi r dr
187  //Contact line L = 2*sqrt(2*r*o) indented by do/2 => dA = sqrt(2*r*o) do
188  //Thus, dr = sqrt(0.5*o/r)/pi do.
189  dr = sqrt(0.5*plasticOverlap_/effectiveDiameter)/3.14 *doverlap;
190  } else {
191  //3D: increase the radius of each sphere such that the particle volume
192  //increases by the same amount that the contact volume decreases
193  //Particle surface area S = 4 pi r^2 increased by dr => dA = 4 pi r^2 dr
194  //Contact area L = pi 2*r*o indented by do/2 => dA = pi r o do
195  //Thus, dr = 0.25*o/r do
196  dr = 0.25*plasticOverlap_/effectiveDiameter *doverlap;
197  }
198  if (PParticle==nullptr) { //if P is a wall
199  IParticle->setRadius(IParticle->getRadius()+dr);//should be twice that amount
200  } else if (IParticle==nullptr) { //if I is a wall
201  PParticle->setRadius(PParticle->getRadius()+dr);
202  } else { //if both P and I are particles
203  PParticle->setRadius(PParticle->getRadius()+dr);
204  IParticle->setRadius(IParticle->getRadius()+dr);
205  }*/
206  }
207  else
208  {
210  setForce(Vec3D(0.0, 0.0, 0.0));
211  setTorque(Vec3D(0.0, 0.0, 0.0));
212  }
213 }
214 
219 {
220  if (getOverlap() > 0)
222  else
223  return 0.0;
225 }
230 {
231  return dynamic_cast<const SinterNormalSpecies*>(getBaseSpecies());
232 }
237 {
238  return plasticOverlap_;
239 }
244 {
245  plasticOverlap_ = plasticOverlap;
246 }
251 {
252  const SinterNormalSpecies* species = getSpecies();
253  Mdouble effectiveDiameter = 2.0*getEffectiveRadius();
254  Mdouble deltaMaxFluid = species->getPenetrationDepthMax() * effectiveDiameter / (1.0-species->getLoadingStiffness()/species->getUnloadingStiffnessMax());
255  if (getOverlap() > deltaMaxFluid)
256  return species->getUnloadingStiffnessMax();
257  else
258  return species->getLoadingStiffness() + (species->getUnloadingStiffnessMax() - species->getLoadingStiffness()) *
259  getPlasticOverlap()/deltaMaxFluid;
260 }
261 
263  return 2;
264 }
265 
266 std::string SinterInteraction::getTypeVTK(unsigned i) const {
267  return "Float32";
268 }
269 
270 std::string SinterInteraction::getNameVTK(unsigned i) const {
271  if (i==0)
272  return "plasticOverlap";
273  else
274  return "neckRadius";
275 }
276 
277 std::vector<Mdouble> SinterInteraction::getFieldVTK(unsigned i) const {
278  if (i==0)
279  return std::vector<Mdouble>(1, plasticOverlap_);
280  else
281  return std::vector<Mdouble>(1, sqrt(2.0*getEffectiveRadius()*plasticOverlap_));
282 }
283 
284 
285 //set xlabel 't'; set ylabel 'f_n = f_ep-f_a'; p 'SingleParticleCT.fstat' u 1:9 title 'f_g=f_a', 'SingleParticleCT_noGravity.fstat' u 1:9 title 'f_g=0'/
286 
287 //set xlabel 't'; set ylabel 'delta/r'; p 'SingleParticleCT.fstat' u 1:($7/1e-6) title 'f_g=f_a', 'SingleParticleCT_noGravity.fstat' u 1:($7/1e-6) title 'f_g=0'
Mdouble getEffectiveRadius() const
Returns a Mdouble to the effective radius of the interaction. (Not corrected for the overlap) ...
The DPMBase header includes quite a few header files, defining all the handlers, which are essential...
Definition: DPMBase.h:65
Logger< MERCURY_LOGLEVEL > logger("MercuryKernel")
InteractionHandler * getHandler() const
Gets a point to the interaction handlers to which this interaction belongs.
const Vec3D & getRelativeVelocity() const
Returns a constant reference to a vector of relative velocity.
Mdouble getSinterAdhesion() const
Accesses sinterAdhesion_.
double Mdouble
void setRelativeVelocity(Vec3D relativeVelocity)
set the relative velocity of the current of the interactions.
virtual ~SinterInteraction()
Destructor.
std::vector< Mdouble > getFieldVTK(unsigned i) const override
Mdouble getTemperature() const
void setForce(Vec3D force)
set total force (this is used by the normal force, tangential forces are added use addForce) ...
Mdouble getElasticEnergy() const
Computes and returns the amount of elastic energy stored in the spring.
static Mdouble dot(const Vec3D &a, const Vec3D &b)
Calculates the dot product of two Vec3D: .
Definition: Vector.cc:167
void setNormalRelativeVelocity(Mdouble normalRelativeVelocit)
set the normal component of the relative velocity.
Mdouble getUnloadingStiffness() const
T square(T val)
squares a number
Definition: ExtendedMath.h:91
Stores information about interactions between two interactable objects; often particles but could be ...
SINTERTYPE getSinterType() const
virtual void read(std::istream &is)
Interaction read function, which accepts an std::istream as input.
const Vec3D & getContactPoint() const
Gets constant reference to contact point (vector).
Mdouble getNormalRelativeVelocity() const
Returns a double which is the norm (length) of the relative velocity vector.
const BaseSpecies * getBaseSpecies() const
Return a constant point to BaseSpecies of the interaction.
SinterInteraction(BaseInteractable *P, BaseInteractable *I, Mdouble timeStamp)
Constructor.
const Vec3D & getNormal() const
Gets the normal vector between the two interacting objects.
std::string getTypeVTK(unsigned i) const override
Mdouble getLoadingStiffness() const
Returns the loading stiffness of the linear plastic-viscoelastic normal force.
void computeNormalForce()
Creates a copy of an object of this class. (Deep copy)
Mdouble getCohesionStiffness() const
Returns the cohesive stiffness of the linear plastic-viscoelastic normal force.
void setTorque(Vec3D torque)
set the total force (this is used by the normal force, tangential torques are added use addTorque) ...
Mdouble getOverlap() const
Returns a Mdouble with the current overlap between the two interacting objects.
std::string getNameVTK(unsigned i) const override
void setAbsoluteNormalForce(Mdouble absoluteNormalForce)
the absolute values of the norm (length) of the normal force
Mdouble getPenetrationDepthMax() const
Returns the maximum penetration depth of the linear plastic-viscoelastic normal force.
void setPlasticOverlap(const Mdouble plasticOverlap)
SinterNormalSpecies contains the parameters used to describe a plastic-cohesive normal force (Stefan ...
std::function< double(double temperature)> getTemperatureDependentSinterRate() const
unsigned getNumberOfFieldsVTK() const override
Mdouble getPlasticOverlap() const
BaseInteractable * getI()
virtual std::string getBaseName() const
Returns the name of the interaction.
virtual void write(std::ostream &os) const
Interaction write function, which accepts an std::ostream as input.
virtual void read(std::istream &is)
Interaction read function, which accepts an std::istream as input.
Defines the basic properties that a interactable object can have.
Mdouble getUnloadingStiffnessMax() const
Returns the maximum unloading stiffness of the linear plastic-viscoelastic normal force...
Mdouble getDissipation() const
Allows the normal dissipation to be accessed.
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.
Definition: BaseHandler.h:543
Mdouble getTimeStep() const
Allows the time step dt to be accessed.
Definition: DPMBase.cc:465
Computes normal forces in case of a linear plastic visco-elastic interaction.
virtual void write(std::ostream &os) const
Interaction print function, which accepts an std::ostream as input.
const SinterNormalSpecies * getSpecies() const
Mdouble getSinterRate() const
Accesses sinterRate_.