1
/////////////////////////////////////////////////////////////
3
// Copyright (c) 2003-2017 by The University of Queensland //
4
// Centre for Geoscience Computing //
5
// http://earth.uq.edu.au/centre-geoscience-computing //
7
// Primary Business: Brisbane, Queensland, Australia //
8
// Licensed under the Open Software License version 3.0 //
9
// http://www.apache.org/licenses/LICENSE-2.0 //
11
/////////////////////////////////////////////////////////////
13
#include "Model/ARotBondedInteraction.h"
14
#include "Model/BondedInteractionCpData.h"
15
#include "Foundation/console.h"
17
// --- TML includes ---
18
#include "tml/message/packed_message_interface.h"
22
double calc_angle( double s_in, double c_os)
27
if ( c_os>=1.0 ||c_os<=-1.0)
41
if ( c_os>=1.0 ||c_os<=-1.0)
55
Default constructor for basic rotational bonded interaction parameters.
56
Sets all stiffnesses to 0.0
58
ARotBondedIGP::ARotBondedIGP()
69
Constructor for basic rotational bonded interaction parameters from
70
individual stiffness parameters (Wang et al 2006)
72
ARotBondedIGP::ARotBondedIGP(
73
const std::string &name,
91
Constructor for basic rotational bonded interaction parameters from
92
brittle beam parameters (stiffness only, not strength).
94
ARotBondedIGP::ARotBondedIGP(
95
const std::string &name,
104
double shearModulus = youngsModulus / (2.0*(1.+poissonsRatio));
106
kr = M_PI*youngsModulus;
107
ks = M_PI*shearModulus;
108
kb = M_PI*youngsModulus;
109
kt = M_PI*shearModulus;
112
// --------- END PARAMETER CLASS ----------
116
Default constructor for base of rotational bonded interactions.
117
Just sets all parameters to 0.0
119
ARotBondedInteraction::ARotBondedInteraction():ARotPairInteraction()
130
m_moment = Vec3(0.0,0.0,0.0);
131
m_force = Vec3(0.0,0.0,0.0);
138
Constructor for base of rotational bonded interactions using two particle pointers
139
and a parameter set contained in a ARotBondedIGP.
141
ARotBondedInteraction::ARotBondedInteraction(CRotParticle* p1,CRotParticle* p2,const ARotBondedIGP& param):ARotPairInteraction(p1,p2)
148
m_D = p2->getPos()-p1->getPos();
149
m_dist=sqrt(m_D*m_D);
157
m_scaling = param.scaling;
159
// scale elastic param
160
// assume Rmean-scaling -> add option to do otherwise to derived class
161
if (m_scaling == true) {
162
if(!CParticle::getDo2dCalculations()){
166
momentJ = 0.5 * effR * effR * effR * effR;
167
momentI = 0.5 * momentJ;
171
m_kr = param.kr * effA / effL;
172
m_ks = param.ks * effA / effL;
173
m_kb = param.kb * momentI / effL;
174
m_kt = param.kt * momentJ / effL;
176
m_force = Vec3(0.0,0.0,0.0);
177
m_moment = Vec3(0.0,0.0,0.0) ;
183
Default destructor - does nothing
185
ARotBondedInteraction::~ARotBondedInteraction()
191
int ARotBondedInteraction::getTag() const
199
void ARotBondedInteraction::setTag(int tag)
205
Get _initial_ vector between particle centers (i.e. at contruction time)
207
Vec3 ARotBondedInteraction::getInitialCentrePtDiff() const
209
return m_p2->getInitPos() - m_p1->getInitPos();
213
Get _current_ vector between particle centers
215
Vec3 ARotBondedInteraction::getCentrePtDiff() const
217
return m_p2->getPos() - m_p1->getPos();
221
Get location of the midpoint between the particles at construction time
223
Vec3 ARotBondedInteraction::getInitialMidPoint() const
225
const Vec3 initialDiff = getInitialCentrePtDiff();
226
const Vec3 normalisedDiff = initialDiff*(1.0/initialDiff.norm());
227
return 0.5*((m_p1->getInitPos() + normalisedDiff*m_p1->getRad()) + (m_p2->getInitPos() - normalisedDiff*m_p2->getRad()));
231
Get shear force on particle 2
233
Vec3 ARotBondedInteraction::getP2ShearForcePt() const
235
return m_p2->getPos() + (m_p2->getQuat().to_matrix()*(getInitialMidPoint()-m_p2->getInitPos()));
239
Get shear force on particle 1
241
Vec3 ARotBondedInteraction::getP1ShearForcePt() const
243
return m_p1->getPos() + (m_p1->getQuat().to_matrix()*(getInitialMidPoint()-m_p1->getInitPos()));
249
Vec3 ARotBondedInteraction::getShearDiff() const
251
const Vec3 p1Pt = getP1ShearForcePt();
252
const Vec3 p2Pt = getP2ShearForcePt();
253
const Vec3 ptDiff = p2Pt-p1Pt;
254
const Vec3 rotatedInitialDiffDirection = p1Pt - m_p1->getPos(); //getCentrePtDiff();
255
return (ptDiff - (((ptDiff*rotatedInitialDiffDirection)/rotatedInitialDiffDirection.norm2())*rotatedInitialDiffDirection));
259
get _current_ midpoint between particles
261
Vec3 ARotBondedInteraction::getContactPoint() const
263
const Vec3 centrePtDiff = getCentrePtDiff();
264
const Vec3 normalisedDiff = centrePtDiff*(1.0/centrePtDiff.norm());
265
return 0.5*((m_p1->getPos() + normalisedDiff*m_p1->getRad()) + (m_p2->getPos() - normalisedDiff*m_p2->getRad()));
270
Vec3 getTangent(const Vec3 &r, const Vec3 &f)
272
return (f.norm2() > 0) ? (f - ((r*f)/f.norm2())*r) : Vec3::ZERO;
275
void CRotBondedInteraction::calcForces()
277
// Calculate linear elastic force, no moment
278
const Vec3 currentDiff = m_p2->getPos() - m_p1->getPos();
279
const double currentDiffNorm = currentDiff.norm();
280
const Vec3 initialDiff = getInitialCentrePtDiff();
281
const Vec3 p2LinearForce = ((m_kr * (initialDiff.norm() - currentDiffNorm))/currentDiffNorm) * currentDiff;
283
m_p2->applyForce( p2LinearForce, m_p2->getPos());
284
m_p1->applyForce(-p2LinearForce, m_p1->getPos());
285
m_nForce = p2LinearForce.norm();
287
// Calculate the shearing forces, linear and moment contributions.
288
// Need to take into account relative orientations of particles.
289
const Vec3 shearDiff = getShearDiff();
290
const Vec3 p2ShearForcePt = getP2ShearForcePt();
291
const Vec3 p1ShearForcePt = getP1ShearForcePt();
292
const Vec3 p2ShearForce = -m_ks * (p2ShearForcePt - p1ShearForcePt); //(m_ks * shearDiff);
293
m_p2->applyMoment(cross(p2ShearForcePt - m_p2->getPos(), getTangent(p2ShearForcePt - m_p2->getPos(), p2ShearForce)));
294
m_p1->applyMoment(cross(p1ShearForcePt - m_p1->getPos(), getTangent(p1ShearForcePt - m_p1->getPos(), -p2ShearForce)));
295
m_p2->applyForce( p2ShearForce, m_p2->getPos());
296
m_p1->applyForce(-p2ShearForce, m_p1->getPos());
297
m_shForce = p2ShearForce.norm();
302
const double HALF_SQRT_2 = 0.5*sqrt(2.0); // use constexpr?
307
void ARotBondedInteraction::calcForces()
309
double s_fai=0.0, c_fai=0.0, c_pasi2=0.0, s_pasi2=0.0;
310
double sita=0.0, pasi=0.0;
312
const Matrix3 mat0 = (m_p1->getQuat()).to_matrix();
313
const Vec3 rbp = m_p2->getPos() - m_p1->getPos(); // rbp <-> r_f
314
const double rbpNorm = rbp.norm();
315
const Vec3 rb = mat0*(m_p2->getPos() - m_p1->getPos()); // eq. 11, rb <-> r_c
316
const double rbNorm = rb.norm();
318
const double r_0Norm = m_p1->getRad()+m_p2->getRad();
319
//const double r_0Norm = m_r0;
320
const Vec3 delta_r = (rbNorm - r_0Norm)*rb/rbNorm; // eq. 9, part of eq. 12
321
const Vec3 Fr = m_kr*delta_r ; // rest of eq. 12
323
const double gama_cos = dot(rb, m_D)/(rbNorm*m_D.norm()) ;
325
if (gama_cos < 1.0 && gama_cos > -1.0 )
327
gama = acos(gama_cos);
330
const Vec3 rb_0 = cross(rb, m_D);
331
const Vec3 rb_b0 = cross(rb, rb_0);
332
const double rb_b0Norm = rb_b0.norm();
333
Vec3 Fst(0.0,0.0,0.0);
336
Fst = m_ks*r_0Norm*gama*rb_b0/rb_b0Norm; // eq. 14
339
Vec3 Mst(0.0,0.0,0.0);
340
const double rb_0Norm = rb_0.norm();
343
Mst = -Fst.norm()*rb_0/rb_0Norm; // eq. 15
346
const double m0 = HALF_SQRT_2*sqrt((rbNorm + rb.Z())/rbNorm);
347
double m1 = -HALF_SQRT_2*sqrt((rbNorm - rb.Z())/rbNorm) ;
349
const double m3 = 0.0;
350
const double rbX2PlusRbY2 = rb.X()*rb.X() + rb.Y()*rb.Y();
351
if (rbX2PlusRbY2 != 0.0)
353
const double denomSqrt = sqrt(rbX2PlusRbY2);
354
m1 = m1*rb.Y()/denomSqrt;
355
m2 = m2*rb.X()/denomSqrt;
358
const Quaternion qm(m0, Vec3(m1,m2,m3));
359
const Matrix3 mat = qm.to_matrix();
360
const Matrix3 matTrans(mat.trans());
361
const Quaternion rp = (m_p1->getQuat()).inverse() * (m_p2->getQuat());
362
const Quaternion r = qm.inverse() * rp * qm;
363
const double temp0 = r.return_sca()*r.return_sca() +
364
r.return_vec().Z()*r.return_vec().Z();
371
const double sqrtTemp0 = sqrt(temp0);
372
c_pasi2 = r.return_sca()/sqrtTemp0;
373
s_pasi2 = r.return_vec().Z()/sqrtTemp0;
374
pasi = 2.0 * calc_angle(s_pasi2,c_pasi2);
376
const Vec3 Mtp = Vec3(0.0,0.0, m_kt*pasi);
377
const Vec3 Mtr = matTrans * Mtp;
378
const double temp2 = r.return_vec().X()*r.return_vec().X() +
379
r.return_vec().Y()*r.return_vec().Y();
380
const double temp3 = r.return_vec().X()*r.return_vec().Z() +
381
r.return_sca() * r.return_vec().Y();
382
const double temp4 = r.return_vec().Y()*r.return_vec().Z() -
383
r.return_sca() * r.return_vec().X();
390
const double temp1 = temp0 - temp2;
391
if (temp1 >= 1.0 || temp1 <= -1.0)
400
const double sqrtDenom = sqrt(temp2);
401
c_fai = r.return_vec().Y()/sqrtDenom;
402
s_fai = -r.return_vec().X()/sqrtDenom;
404
const double sqrtDenom = sqrt(temp0*temp2);
405
c_fai = temp3/sqrtDenom;
406
s_fai = temp4/sqrtDenom;
408
const Vec3 Mbp = Vec3( - 0.5*m_kb*sita*s_fai, 0.5*m_kb*sita*c_fai, 0.0); // eq 16.1
409
Mbr = matTrans * Mbp; // eq. 17.1
410
const Vec3 Fsp = Vec3 ( - 0.5*m_ks*c_fai*sita*r_0Norm,
411
- 0.5*m_ks*s_fai*sita*r_0Norm,
413
Fsr = matTrans * Fsp; // eq. 17.3
415
const Vec3 Msp = Vec3( 0.5*m_ks*s_fai*sita*r_0Norm,
416
- 0.5*m_ks*c_fai*sita*r_0Norm,
418
// above is diff to paper: r instead r^2 here, other r moved to eq 19 below
419
Msr = matTrans * Msp;
422
const double eq_rad1 = m_p1->getRad()/(m_p1->getRad()+m_p2->getRad());
423
const double eq_rad2 = m_p2->getRad()/(m_p1->getRad()+m_p2->getRad());
425
const Matrix3 mat0Trans(mat0.trans());
426
m_force = mat0Trans * (Fr + Fst + Fsr );
427
m_moment = mat0Trans * (Mbr + Mtr + Msr*eq_rad1*rbpNorm + Mst*eq_rad1*rbpNorm); // eq. 19 for particle 1
429
const Vec3 moment2 = mat0Trans *( Msr*eq_rad2*rbpNorm + Mst*eq_rad2*rbpNorm - Mbr - Mtr); // eq. 19 for particle 2
431
m_shForce = (Fst + Fsr).norm();
432
m_tMoment = Mtr.norm();
433
m_bMoment = Mbr.norm();
434
const double r0 = m_p1->getRad()+m_p2->getRad();
435
const Vec3 D = m_p1->getPos() - m_p2->getPos();
438
m_nForce = ((m_dist < r0) ? -1.0 : 1.0) * Fr.norm();
440
Vec3 pos=m_p2->getPos()+(m_p2->getRad()/(m_p1->getRad()+m_p2->getRad()))*D;
442
m_p2->applyForce(-1.0*m_force,pos);
443
m_p1->applyForce(m_force,pos);
446
m_p1->applyMoment(m_moment) ;
447
m_p2->applyMoment(moment2) ;
452
// --- FIELD FUNCTIONS ---
454
get stored elastic energy
456
double ARotBondedInteraction::getPotentialEnergy() const
458
double pe_r,pe_s,pe_t,pe_b;
460
pe_r=(m_kr!=0.0) ? 0.5*(m_nForce*m_nForce)/m_kr : 0.0;
461
pe_s=(m_ks!=0.0) ? 0.5*(m_shForce*m_shForce)/m_ks : 0.0;
462
pe_t=(m_kt!=0.0) ? 0.5*(m_tMoment*m_tMoment)/m_kt : 0.0;
463
pe_b=(m_kb!=0.0) ? 0.5*(m_bMoment*m_bMoment)/m_kb : 0.0;
464
return pe_r+pe_s+pe_t+pe_b;
467
double ARotBondedInteraction::getNormalPotentialEnergy() const
469
return (m_kr!=0.0) ? 0.5*(m_nForce*m_nForce)/m_kr : 0.0;
472
double ARotBondedInteraction::getShearPotentialEnergy() const
474
return (m_ks!=0.0) ? 0.5*(m_shForce*m_shForce)/m_ks : 0.0;
477
double ARotBondedInteraction::getTwistPotentialEnergy() const
479
return (m_kt!=0.0) ? 0.5*(m_tMoment*m_tMoment)/m_kt : 0.0;
482
double ARotBondedInteraction::getBendPotentialEnergy() const
484
return (m_kb!=0.0) ? 0.5*(m_bMoment*m_bMoment)/m_kb : 0.0;
487
Vec3 ARotBondedInteraction::getForce() const
492
Vec3 ARotBondedInteraction::getNormalForce() const
494
Vec3 dr = (m_p1->getPos() - m_p2->getPos()).unit();
495
Vec3 normalForce = (m_force*dr)*dr;
499
Vec3 ARotBondedInteraction::getTangentialForce() const
501
return (m_force - getNormalForce());
505
Get the particle member function which returns a scalar field of a given name.
507
\param name the name of the field
509
ARotBondedInteraction::ScalarFieldFunction ARotBondedInteraction::getScalarFieldFunction(const string& name)
511
ARotBondedInteraction::ScalarFieldFunction sf;
513
if (name=="potential_energy"){
514
sf=&ARotBondedInteraction::getPotentialEnergy;
515
} else if (name=="e_pot_normal"){
516
sf=&ARotBondedInteraction::getNormalPotentialEnergy;
517
} else if (name=="e_pot_shear"){
518
sf=&ARotBondedInteraction::getShearPotentialEnergy;
519
} else if (name=="e_pot_twist"){
520
sf=&ARotBondedInteraction::getTwistPotentialEnergy;
521
} else if (name=="e_pot_bend"){
522
sf=&ARotBondedInteraction::getBendPotentialEnergy;
523
} else if (name=="count"){
524
sf=&ARotBondedInteraction::Count;
527
cerr << "ERROR - invalid name for interaction scalar access function" << endl;
534
Get the particle member function which returns a vector field of a given name.
536
\param name the name of the field
538
ARotBondedInteraction::VectorFieldFunction ARotBondedInteraction::getVectorFieldFunction(const string& name)
540
ARotBondedInteraction::VectorFieldFunction vf;
543
vf=&ARotBondedInteraction::getForce;
544
} else if (name=="normal_force"){
545
vf=&ARotBondedInteraction::getNormalForce;
546
} else if (name=="tangential_force"){
547
vf=&ARotBondedInteraction::getTangentialForce;
550
cerr << "ERROR - invalid name for interaction vector access function" << endl;
557
Get the particle member function which returns a checked scalar field of a given name.
559
\param name the name of the field
561
ARotBondedInteraction::CheckedScalarFieldFunction ARotBondedInteraction::getCheckedScalarFieldFunction(const string& name)
563
ARotBondedInteraction::CheckedScalarFieldFunction sf;
566
cerr << "ERROR - invalid name for interaction scalar access function" << endl;