MercuryDPM  0.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ExtendedMath.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 #include "ExtendedMath.h"
27 #include <cmath>
28 #include <assert.h>
29 //This has the defintion of quiet nan
30 #include <limits>
31 
38 {
39 const Mdouble ep=1e-5;
40 
41 if (gamma_in > 1.0+ep)
42  {
43  return ((gamma_in-1)*gamma(gamma_in-1));
44  }
45 else
46  {
47 
48  if ((gamma_in-ep<1.0) && (gamma_in+ep>1.0))
49  return 1.0;
50  else if ((gamma_in-ep<0.5) && (gamma_in+ep>0.5))
51  return constants::sqrt_pi;
52  else
53  return std::numeric_limits<Mdouble>::quiet_NaN();
54  }
55 }//end func gamma
56 
61 {
62 
63 Mdouble prefactor = pow(2,k/2.0)*gamma(k/2.0);
64 Mdouble mainfactor = pow(x,k/2.0-1)*exp(x/-2.0);
65 
66 return mainfactor/prefactor;
67 
68 
69 
70 }
71 
79 {
80 
81 //The current value was picked by tried were it stopped effect the 4 d.p.
82 const int num_steps_per_unit=100;
83 Mdouble sum=0;
84 Mdouble x=0;
85 long int num_steps=static_cast<int>(num_steps_per_unit*x_max);
86 //Use trapezional rule, but ignoring the ends
87 for (int i=0;i<num_steps;i++)
88  {
89  x=x_max/num_steps*(i+0.5);
90  sum=sum+chi_squared(x,k);
91  }
92 return 1.0-sum*x_max/num_steps;
93 
94 }
95 
96 
97 
99 {
100  const Mdouble *p = coef;
101  Mdouble b0 = *p++;
102  Mdouble b1=0, b2;
103  int i = N - 1;
104 
105  assert(i>0);
106  do
107  {
108  b2 = b1;
109  b1 = b0;
110  b0 = x * b1 - b2 + *p++;
111  }
112  while( --i );
113 
114  return( 0.5*(b0-b2) );
115 }
116 
118 {
119  // Cooefficients for [0..8]
120  const Mdouble A[] =
121  {
122  -4.415341646479339379501E-18,
123  3.330794518822238097831E-17,
124  -2.431279846547954693591E-16,
125  1.715391285555133030611E-15,
126  -1.168533287799345168081E-14,
127  7.676185498604935616881E-14,
128  -4.856446783111929460901E-13,
129  2.955052663129639834611E-12,
130  -1.726826291441555707231E-11,
131  9.675809035373236912241E-11,
132  -5.189795601635262906661E-10,
133  2.659823724682386650351E-9,
134  -1.300025009986248042121E-8,
135  6.046995022541918949321E-8,
136  -2.670793853940611733911E-7,
137  1.117387539120103718151E-6,
138  -4.416738358458750563591E-6,
139  1.644844807072889708931E-5,
140  -5.754195010082103703981E-5,
141  1.885028850958416557291E-4,
142  -5.763755745385823658851E-4,
143  1.639475616941335798421E-3,
144  -4.324309995050575944301E-3,
145  1.054646039459499831831E-2,
146  -2.373741480589946881561E-2,
147  4.930528423967070848781E-2,
148  -9.490109704804764442101E-2,
149  1.716209015222087753491E-1,
150  -3.046826723431983986831E-1,
151  6.767952744094760849951E-1
152  };
153 
154  // Cooefficients for [8..infinity]
155  const Mdouble B[] =
156  {
157  -7.233180487874753954561E-18,
158  -4.830504485944182071261E-18,
159  4.465621420296759999011E-17,
160  3.461222867697461093101E-17,
161  -2.827623980516583484941E-16,
162  -3.425485619677219134621E-16,
163  1.772560133056526383601E-15,
164  3.811680669352622420751E-15,
165  -9.554846698828307648701E-15,
166  -4.150569347287222086631E-14,
167  1.540086217521409826911E-14,
168  3.852778382742142701141E-13,
169  7.180124451383666233671E-13,
170  -1.794178531506806117781E-12,
171  -1.321581184044771311881E-11,
172  -3.149916527963241364541E-11,
173  1.188914710784643834241E-11,
174  4.940602388224969589101E-10,
175  3.396232025708386345151E-9,
176  2.266668990498178064591E-8,
177  2.048918589469063741831E-7,
178  2.891370520834756482971E-6,
179  6.889758346916823984261E-5,
180  3.369116478255694089901E-3,
181  8.044904110141088316081E-1
182  };
183 
184 
185  if (x < 0)
186  x = -x;
187 
188  if (x <= 8.0)
189  {
190  Mdouble y = (x/2.0) - 2.0;
191  return( chebyshev( y, A, 30 ) );
192  }
193 
194  return( chebyshev( 32.0/x - 2.0, B, 25 ) / sqrt(x) );
195 }
196 
198 {
199  if (x< 0)
200  x = -x;
201  return exp(x) * I0_exp(x);
202 }
203 
204 void getLineFromStringStream(std::istream& in, std::stringstream& out)
205 {
206  std::string line_string;
207  getline(in,line_string);
208  out.str(line_string);
209  out.clear();
210 }
211 
213 {
215  ans.disp = - 2.0 * mass * std::log(r) / tc;
216  ans.k = mass * (sqr(constants::pi/tc) + sqr(ans.disp/(2.0*mass)));
217  return ans;
218 }
219 
222 {
224  ans.disp = - 2.0 * mass * log(r) / tc;
225  ans.k = mass * (sqr(constants::pi/tc) + sqr(ans.disp/(2.0*mass)));
226  ans.kt = 2.0/7.0*ans.k*(sqr(constants::pi)+sqr(log(beta)))/(sqr(constants::pi)+sqr(log(r)));
227  if (beta!=0.0) ans.dispt = -2*log(beta)*sqrt(1.0/7.0*mass*ans.kt/(sqr(constants::pi)+sqr(log(beta))));
228  else ans.dispt = 2.*sqrt(1.0/7.0*mass*ans.kt);
229  return ans;
230 }
231 
233 {
234 
235  //check for errors in input
236  if(mass<=0)
237  {
238  std::cerr << "Error in get_collision_time(Mdouble mass) mass is not set or has an unexpected value, (get_collision_time("<<mass<<"))"<< std::endl;
239  exit(-1);
240  }
241  if(k<=0)
242  {
243  std::cerr << "Error in get_collision_time(Mdouble mass) stiffness is not set or has an unexpected value, (get_collision_time("<<mass<<"), with stiffness="<<k<<")"<< std::endl;
244  exit(-1);
245  }
246  if(disp<0)
247  {
248  std::cerr << "Error in get_collision_time(Mdouble mass) dissipation is not set or has an unexpected value, (get_collision_time("<<mass<<"), with dissipation="<<disp<<")"<< std::endl;
249  exit(-1);
250  }
251 
252  //calculate square of oscillation frequency
253  Mdouble w2=k/mass - sqr(disp/(2.0*mass));
254 
255  if (w2<=0)
256  {
257  std::cerr << "Error in get_collision_time(Mdouble mass) values for mass, stiffness and dissipation lead to an over-damped system, (get_collision_time("<<mass<<"), with stiffness="<<k<<" and dissipation="<<disp<<")"<< std::endl;
258  exit(-1);
259  }
260 
261  return constants::pi / sqrt( w2 );
262 }
263 
265 {
266  return exp(-disp/(2.0*mass)*helperFunc::getCollisionTime(k, disp, mass));
267 }
268 
270 {
271  // note: underestimate based on energy argument,
272  // Ekin = 2*1/2*m*(v/2)^2 = 1/2*k*(2*r)^2, gives
273  // return radius * sqrt(8.0*k/mass);
274 
275  // with dissipation, see S. Luding, Collisions & Contacts between two particles, eq 34
276  Mdouble w = sqrt(k/mass - sqr(disp/(2.0*mass)));
277  Mdouble w0 = sqrt(k/mass);
278  Mdouble DispCorrection = exp(-disp/mass/w)*asin(w/w0);
279  //std::cout << "DispCorrection" << DispCorrection << std::endl;
280  return radius * sqrt(8.0*k/mass) / DispCorrection;
281 }
Mdouble chebyshev(Mdouble x, const Mdouble coef[], int N)
Definition: ExtendedMath.cc:98
KAndDisp computeKAndDispFromCollisionTimeAndRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble mass)
Set disp and k such that is matches a given collision time tc and restitution coefficient r for a col...
Mdouble getMaximumVelocity(Mdouble k, Mdouble disp, Mdouble radius, Mdouble mass)
Calculates the maximum relative velocity allowed for a normal collision of two particles of radius r ...
return type specifically for fuctions returning k and disp at once
Definition: ExtendedMath.h:98
void getLineFromStringStream(std::istream &in, std::stringstream &out)
Mdouble I0_exp(Mdouble x)
const Mdouble sqrt_pi
Definition: ExtendedMath.h:55
#define sqr(a)
Definition: ExtendedMath.h:36
const Mdouble pi
Definition: ExtendedMath.h:54
double Mdouble
Definition: ExtendedMath.h:33
return type specifically for fuctions returning k, disp, kt, dispt at once
Definition: ExtendedMath.h:110
Mdouble getRestitutionCoefficient(Mdouble k, Mdouble disp, Mdouble mass)
Calculates restitution coefficient for two copies of given disp, k, effective mass.
Mdouble gamma(Mdouble gamma_in)
This is the gamma function returns the true value for the half integer value.
Definition: ExtendedMath.cc:37
KAndDispAndKtAndDispt computeDisptFromCollisionTimeAndRestitutionCoefficientAndTangentialRestitutionCoefficientAndEffectiveMass(Mdouble tc, Mdouble r, Mdouble beta, Mdouble mass)
Set disp, k, dispt and kt such that is matches a given collision time tc and a normal andtangential r...
Mdouble I0(Mdouble x)
Mdouble chi_squared_prob(Mdouble x, int k)
This is the function which actually gives the probability back using a chi squared test...
Definition: ExtendedMath.cc:78
Mdouble getCollisionTime(Mdouble k, Mdouble disp, Mdouble mass)
Calculates collision time for two copies of a particle of given disp, k, effective mass...
Mdouble chi_squared(Mdouble x, int k)
This is a chi_squared function return the value x and degrees of freedom k.
Definition: ExtendedMath.cc:60