![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_DEM_PARTICLE_H 00021 #define MECHSYS_DEM_PARTICLE_H 00022 00023 // Std lib 00024 #include <iostream> 00025 #ifdef USE_THREAD 00026 #include <thread> 00027 #endif 00028 00029 // MechSys 00030 #include <mechsys/dem/face.h> 00031 #include <mechsys/dem/special_functions.h> 00032 #include <mechsys/util/array.h> 00033 #include <mechsys/numerical/montecarlo.h> 00034 #include <mechsys/mesh/mesh.h> 00035 00036 struct ParticleProps 00037 { 00038 double Kn; 00039 double Kt; 00040 double Bn; 00041 double Bt; 00042 double Bm; 00043 double Gn; 00044 double Gt; 00045 double Mu; 00046 double eps; 00047 double Beta; 00048 double Eta; 00049 double R; 00050 double rho; 00051 double V; 00052 double m; 00053 }; 00054 00055 class Particle 00056 { 00057 public: 00058 // Constructor 00059 Particle() {} 00060 Particle(int Tag, 00061 Array<Vec3_t> const & V, 00062 Array<Array <int> > const & E, 00063 Array<Array <int> > const & F, 00064 Vec3_t const & v0, 00065 Vec3_t const & w0, 00066 double R, 00067 double rho=1.0); 00068 00069 // Alternative constructor 00070 Particle (int Tag, Mesh::Generic const & M, double R, double rho=1.0); 00071 00072 // Destructor 00073 ~Particle (); 00074 00075 // Methods 00076 void Initialize (size_t i=0, size_t NCalls=5000); 00077 void InitializeVelocity (double dt = 1.0); 00078 void Rotate (double dt); 00079 void Rotate (Quaternion_t & Q, Vec3_t & V); 00080 void Translate (double dt); 00081 void Translate (Vec3_t & t); 00082 void ResetDisplacements (); 00083 double MaxDisplacement (); 00084 void Draw (std::ostream & os, char const * Color="Blue", bool BPY=false); 00085 void FixVeloc (double vx=0.0, double vy=0.0, double vz=0.0); 00086 bool IsFree () {return !vxf&&!vyf&&!vzf&&!wxf&&!wyf&&!wzf;}; 00087 00088 #ifdef USE_THREAD 00089 std::mutex mtex; 00090 #endif 00091 00092 int Tag; 00093 size_t Index; 00094 bool PropsReady; 00095 bool IsBroken; 00096 bool vxf, vyf, vzf; 00097 bool wxf, wyf, wzf; 00098 Vec3_t x; 00099 Vec3_t xb; 00100 Vec3_t v; 00101 Vec3_t w; 00102 Vec3_t wb; 00103 Vec3_t F; 00104 Vec3_t Ff; 00105 Vec3_t T; 00106 Vec3_t Tf; 00107 Vec3_t I; 00108 Quaternion_t Q; 00109 Mat3_t M; 00110 Mat3_t B; 00111 double Erot; 00112 double Ekin; 00113 double Dmax; 00114 double Diam; 00115 double Cn; 00116 00117 Array<Vec3_t*> Verts; 00118 ParticleProps Props; 00119 Array<Vec3_t*> Vertso; 00120 Array<Array <int> > EdgeCon; 00121 Array<Array <int> > FaceCon; 00122 Array<Edge*> Edges; 00123 Array<Face*> Faces; 00124 Array<Torus*> Tori; 00125 Array<Cylinder*> Cylinders; 00126 00127 // Auxiliar methods 00128 void CalcProps (size_t NCalls=5000); 00129 bool IsInside (Vec3_t & V); 00130 bool IsInsideAlt(Vec3_t & V); 00131 double IsInside (double * V); 00132 double MaxX (); 00133 double MaxY (); 00134 double MaxZ (); 00135 double MinX (); 00136 double MinY (); 00137 double MinZ (); 00138 00139 // Integrants for the calc of properties 00140 double Vol (double * X); 00141 double Xc (double * X); 00142 double Yc (double * X); 00143 double Zc (double * X); 00144 double Ixx (double * X); 00145 double Iyy (double * X); 00146 double Izz (double * X); 00147 double Ixy (double * X); 00148 double Ixz (double * X); 00149 double Iyz (double * X); 00150 00151 #ifdef USE_BOOST_PYTHON 00152 double PyGetFeatures (BPy::list & V, BPy::list & E, BPy::list & F) const 00153 { 00154 // vertex-ID map 00155 typedef std::map<Vec3_t const *,int> VertID_t; 00156 VertID_t vids; 00157 00158 // vertices 00159 for (size_t i=0; i<Verts.Size(); ++i) 00160 { 00161 V.append (BPy::make_tuple((*Verts[i])(0),(*Verts[i])(1),(*Verts[i])(2))); 00162 vids[Verts[i]] = i; 00163 } 00164 00165 // edges 00166 for (size_t i=0; i<Edges.Size(); ++i) 00167 E.append (BPy::make_tuple(vids[Edges[i]->X0], vids[Edges[i]->X1])); 00168 00169 // faces 00170 for (size_t i=0; i<Faces.Size(); ++i) 00171 { 00172 /* // list of edges 00173 BPy::list edges; 00174 for (size_t j=0; j<Faces[i]->Edges.Size(); ++j) 00175 edges.append (BPy::make_tuple(vids[Faces[i]->Edges[j]->X0], vids[Faces[i]->Edges[j]->X1])); 00176 F.append (edges); 00177 */ 00178 // list of vertices 00179 BPy::list verts; 00180 for (size_t j=0; j<Faces[i]->Edges.Size(); ++j) 00181 verts.append (vids[Faces[i]->Edges[j]->X0]); 00182 F.append (verts); 00183 } 00184 00185 return Props.R; 00186 } 00187 #endif 00188 }; 00189 00190 00191 std::ostream & operator<< (std::ostream & os, Particle const & P) 00192 { 00193 os << "Tag = " << P.Tag << std::endl; 00194 os << "Index = " << P.Index << std::endl; 00195 os << "PropsReady = " << P.PropsReady << std::endl; 00196 os << "IsBroken = " << P.IsBroken << std::endl; 00197 os << "vxf, vyf, vzf = " << P.vxf << ", " << P.vyf << ", " << P.vzf << std::endl; 00198 os << "wxf, wyf, wzf = " << P.wxf << ", " << P.wyf << ", " << P.wzf << std::endl; 00199 os << "x = " << PrintVector(P.x ); 00200 os << "xb = " << PrintVector(P.xb); 00201 os << "v = " << PrintVector(P.v ); 00202 os << "w = " << PrintVector(P.w ); 00203 os << "wb = " << PrintVector(P.wb); 00204 os << "F = " << PrintVector(P.F ); 00205 os << "Ff = " << PrintVector(P.Ff); 00206 os << "T = " << PrintVector(P.T ); 00207 os << "Tf = " << PrintVector(P.Tf); 00208 os << "I = " << PrintVector(P.I ); 00209 os << "Q = " << P.Q << std::endl; 00210 os << "M =\n" << PrintMatrix(P.M ); 00211 os << "B =\n" << PrintMatrix(P.B ); 00212 os << "Erot = " << P.Erot << std::endl; 00213 os << "Ekin = " << P.Ekin << std::endl; 00214 os << "Dmax = " << P.Dmax << std::endl; 00215 os << "Diam = " << P.Diam << std::endl; 00216 os << "Cn = " << P.Cn << std::endl; 00217 return os; 00218 } 00219 00220 00222 00223 00224 // Constructor and destructor 00225 00226 inline Particle::Particle (int TheTag, Array<Vec3_t> const & V, Array<Array <int> > const & E, Array<Array <int> > const & Fa, Vec3_t const & v0, Vec3_t const & w0, double TheR, double TheRho) 00227 : Tag(TheTag), PropsReady(false), IsBroken(false), v(v0), w(w0) 00228 { 00229 Props.Kn = 1.0e4; 00230 Props.Kt = 5.0e3; 00231 Props.Bn = 1.0e4; 00232 Props.Bt = 5.0e3; 00233 Props.Bm = 5.0e3; 00234 Props.Gn = 16.0; 00235 Props.Gt = 8.0; 00236 Props.Mu = 0.4; 00237 Props.eps = 0.01; 00238 Props.Beta = 0.12; 00239 Props.Eta = 1.0; 00240 Props.R = TheR; 00241 Props.rho = TheRho; 00242 00243 00244 vxf = false; 00245 vyf = false; 00246 vzf = false; 00247 00248 wxf = false; 00249 wyf = false; 00250 wzf = false; 00251 00252 F = 0.0,0.0,0.0; 00253 Ff = 0.0,0.0,0.0; 00254 Tf = 0.0,0.0,0.0; 00255 00256 EdgeCon = E; 00257 FaceCon = Fa; 00258 00259 for (size_t i=0; i<V.Size(); i++) 00260 { 00261 Verts.Push (new Vec3_t(V[i])); 00262 Vertso.Push (new Vec3_t(V[i])); 00263 } 00264 for (size_t i=0; i<Fa.Size(); i++) 00265 { 00266 Array<Vec3_t*> verts(Fa[i].Size()); 00267 for (size_t j=0; j<Fa[i].Size(); ++j) verts[j] = Verts[Fa[i][j]]; 00268 Faces.Push (new Face(verts)); 00269 } 00270 for (size_t i=0; i<E.Size(); i++) Edges.Push (new Edge((*Verts[E[i][0]]), (*Verts[E[i][1]]))); 00271 } 00272 00273 inline Particle::Particle (int TheTag, Mesh::Generic const & M, double TheR, double TheRho) 00274 : Tag(TheTag), PropsReady(false), IsBroken(false), v(Vec3_t(0.0,0.0,0.0)), w(Vec3_t(0.0,0.0,0.0)) 00275 { 00276 Props.Kn = 1.0e4; 00277 Props.Kt = 5.0e3; 00278 Props.Bn = 1.0e4; 00279 Props.Bt = 5.0e3; 00280 Props.Bm = 5.0e3; 00281 Props.Gn = 16.0; 00282 Props.Gt = 8.0; 00283 Props.Mu = 0.4; 00284 Props.eps = 0.01; 00285 Props.Beta = 0.12; 00286 Props.Eta = 1.0; 00287 Props.R = TheR; 00288 Props.rho = TheRho; 00289 00290 Ff = 0.0,0.0,0.0; 00291 Tf = 0.0,0.0,0.0; 00292 00293 // check if mesh is Shell 00294 if (!M.IsShell) throw new Fatal("Particle::Particle: Mesh must be of Shell type"); 00295 00296 // vertices 00297 size_t nv = M.Verts.Size(); 00298 for (size_t i=0; i<nv; ++i) 00299 { 00300 Verts .Push (new Vec3_t(M.Verts[i]->C(0), M.Verts[i]->C(1), M.Verts[i]->C(2))); 00301 Vertso.Push (new Vec3_t(M.Verts[i]->C(0), M.Verts[i]->C(1), M.Verts[i]->C(2))); 00302 } 00303 00304 // edges and faces 00305 typedef std::map<std::pair<int,int>,Edge*> Key2Edge_t; 00306 Key2Edge_t key2edge; // map edge pair (v0,v1) to Edge* in Edges 00307 size_t nf = M.Cells.Size(); // number of faces: each cell is one face 00308 for (size_t i=0; i<nf; ++i) 00309 { 00310 // number of vertices per face 00311 size_t nvf = M.Cells[i]->V.Size(); 00312 00313 // edges 00314 size_t v0, v1; 00315 std::pair<int,int> keya, keyb; 00316 for (size_t j=0; j<nvf; ++j) 00317 { 00318 v0 = M.Cells[i]->V[j]->ID; 00319 v1 = M.Cells[i]->V[(j+1)%nvf]->ID; 00320 keya = std::make_pair(v0,v1); 00321 keyb = std::make_pair(v1,v0); 00322 Key2Edge_t::const_iterator ita = key2edge.find(keya); 00323 Key2Edge_t::const_iterator itb = key2edge.find(keyb); 00324 if (ita==key2edge.end() && itb==key2edge.end()) // new edge 00325 { 00326 Edges.Push (new Edge((*Verts[v0]), (*Verts[v1]))); 00327 key2edge[keya] = Edges[Edges.Size()-1]; 00328 EdgeCon.Push (Array<int>((int)v0,(int)v1)); // TODO: we may remove this 00329 } 00330 } 00331 00332 // faces 00333 Array<Vec3_t*> verts(nvf); 00334 FaceCon.Push (Array<int>()); // TODO: we may remove this 00335 for (size_t j=0; j<nvf; ++j) 00336 { 00337 v0 = M.Cells[i]->V[j]->ID; 00338 verts[j] = Verts[v0]; 00339 FaceCon[FaceCon.Size()-1].Push (v0); // TODO: we may remove this 00340 } 00341 Faces.Push (new Face(verts)); 00342 } 00343 } 00344 00345 inline Particle::~Particle() 00346 { 00347 for (size_t i=0; i<Verts.Size(); ++i) delete Verts[i]; 00348 for (size_t i=0; i<Vertso.Size(); ++i) delete Vertso[i]; 00349 for (size_t i=0; i<Edges.Size(); ++i) delete Edges[i]; 00350 for (size_t i=0; i<Faces.Size(); ++i) delete Faces[i]; 00351 } 00352 00353 // Methods 00354 00355 inline void Particle::Initialize (size_t i, size_t NCalls) 00356 { 00357 // calc properties 00358 if (!PropsReady) 00359 { 00360 Index = i; 00361 CalcProps (NCalls); 00362 } 00363 } 00364 00365 inline void Particle::InitializeVelocity (double dt) 00366 { 00367 // initialize the particle for the Verlet algorithm 00368 xb = x-v*dt; 00369 wb = w; 00370 } 00371 00372 inline void Particle::Rotate (double dt) 00373 { 00374 double q0,q1,q2,q3,wx,wy,wz; 00375 q0 = 0.5*Q(0); 00376 q1 = 0.5*Q(1); 00377 q2 = 0.5*Q(2); 00378 q3 = 0.5*Q(3); 00379 00380 if (wxf) T(0) = 0.0; 00381 if (wyf) T(1) = 0.0; 00382 if (wzf) T(2) = 0.0; 00383 00384 Vec3_t Td; 00385 Td(0)=(T(0)+(I(1)-I(2))*wb(1)*wb(2))/I(0); 00386 Td(1)=(T(1)+(I(2)-I(0))*wb(0)*wb(2))/I(1); 00387 Td(2)=(T(2)+(I(0)-I(1))*wb(1)*wb(0))/I(2); 00388 w = wb+0.5*dt*Td; 00389 wx = w(0); 00390 wy = w(1); 00391 wz = w(2); 00392 Quaternion_t dq(-(q1*wx+q2*wy+q3*wz),q0*wx-q3*wy+q2*wz,q3*wx+q0*wy-q1*wz,-q2*wx+q1*wy+q0*wz),qm; 00393 00394 wb = wb+Td*dt; 00395 qm = Q+dq*(0.5*dt); 00396 q0 = 0.5*qm(0); 00397 q1 = 0.5*qm(1); 00398 q2 = 0.5*qm(2); 00399 q3 = 0.5*qm(3); 00400 wx = wb(0); 00401 wy = wb(1); 00402 wz = wb(2); 00403 dq = Quaternion_t(-(q1*wx+q2*wy+q3*wz),q0*wx-q3*wy+q2*wz,q3*wx+q0*wy-q1*wz,-q2*wx+q1*wy+q0*wz); 00404 Quaternion_t Qd = (qm+dq*0.5*dt),temp; 00405 Conjugate (Q,temp); 00406 Rotate (temp,x); 00407 Q = Qd/norm(Qd); 00408 Rotate (Q,x); 00409 Erot=0.5*(I(0)*wx*wx+I(1)*wy*wy+I(2)*wz*wz); 00410 00411 } 00412 00413 inline void Particle::Rotate (Quaternion_t & Q,Vec3_t & V) 00414 { 00415 size_t nv = Verts.Size(),ne = Edges.Size(),nf = Faces.Size(),nc = Cylinders.Size(); 00416 for (size_t i = 0; i < nv; i++) 00417 { 00418 Vec3_t xt = *Verts[i]-V; 00419 Rotation(xt,Q,*Verts[i]); 00420 *Verts[i] += V; 00421 } 00422 00423 for (size_t i = 0; i < ne; i++) 00424 { 00425 Edges[i]->UpdatedL(); 00426 } 00427 00428 for (size_t i = 0; i < nf; i++) 00429 { 00430 Faces[i]->UpdatedL(); 00431 } 00432 00433 for (size_t i = 0; i < nc; i++) 00434 { 00435 Cylinders[i]->UpdatedL(); 00436 } 00437 } 00438 00439 inline void Particle::Translate (double dt) 00440 { 00441 if (vxf) F(0) = 0.0; 00442 if (vyf) F(1) = 0.0; 00443 if (vzf) F(2) = 0.0; 00444 if(Util::IsNan(norm(F))) 00445 { 00446 throw new Fatal("Particle::Translate: The force is not a number %d(%d), try reducing the time step",Index,Tag); 00447 } 00448 Vec3_t temp,xa; 00449 xa = 2*x - xb + F*(dt*dt/Props.m); 00450 temp = xa - x; 00451 v = 0.5*(xa - xb)/dt; 00452 xb = x; 00453 x = xa; 00454 Ekin = 0.5*Props.m*dot(v,v); 00455 00456 size_t nv = Verts.Size(); 00457 for (size_t i = 0; i < nv; i++) 00458 { 00459 *Verts[i] += temp; 00460 } 00461 } 00462 00463 inline void Particle::Translate (Vec3_t & V) 00464 { 00465 size_t nv = Verts.Size(); 00466 for (size_t i = 0; i < nv; i++) 00467 { 00468 *Verts[i] += V; 00469 } 00470 x += V; 00471 xb += V; 00472 } 00473 00474 inline void Particle::ResetDisplacements () 00475 { 00476 for (size_t i=0; i<Verts.Size(); ++i) 00477 { 00478 (*Vertso[i]) = (*Verts[i]); 00479 } 00480 } 00481 00482 inline double Particle::MaxDisplacement () 00483 { 00484 double md = 0.0; 00485 for (size_t i=0; i<Verts.Size(); ++i) 00486 { 00487 double mpd = Distance((*Vertso[i]),(*Verts[i])); 00488 if (mpd>md) md = mpd; 00489 } 00490 return md; 00491 } 00492 00493 inline void Particle::Draw (std::ostream & os, char const * Color, bool BPY) 00494 { 00495 for (size_t i=0; i<Verts.Size(); ++i) 00496 { 00497 if (BPY) BPYDrawVert((*Verts[i]),os,Props.R); 00498 else POVDrawVert((*Verts[i]),os,Props.R,Color); 00499 } 00500 for (size_t i=0; i<Edges.Size(); ++i) 00501 { 00502 Edges[i]->Draw(os,Props.R,Color,BPY); 00503 } 00504 for (size_t i=0; i<Faces.Size(); ++i) 00505 { 00506 Faces[i]->Draw(os,Props.R,Color,BPY); 00507 } 00508 for (size_t i=0; i<Tori.Size(); ++i) 00509 { 00510 Tori[i]->Draw(os,Props.R,Color,BPY); 00511 } 00512 for (size_t i=0; i<Cylinders.Size(); ++i) 00513 { 00514 Cylinders[i]->Draw(os,Props.R,Color,BPY); 00515 } 00516 } 00517 00518 inline void Particle::FixVeloc (double vx, double vy, double vz) 00519 { 00520 v = vx, vy, vz; 00521 vxf = true; vyf = true; vzf = true; 00522 wxf = true; wyf = true; wzf = true; 00523 } 00524 00525 // Auxiliar methods 00526 00527 inline void Particle::CalcProps (size_t NCalls) 00528 { 00529 if (Verts.Size()==1 && Edges.Size()==0 && Faces.Size()==0) 00530 { 00531 Props.V = (4./3.)*M_PI*Props.R*Props.R*Props.R; 00532 I = Vec3_t((8./15.)*M_PI*pow(Props.R,5.),(8./15.)*M_PI*pow(Props.R,5.),(8./15.)*M_PI*pow(Props.R,5.)); 00533 x = *Verts[0]; 00534 Q = 1,0,0,0; 00535 Props.m = Props.rho*Props.V; 00536 I*= Props.rho; 00537 Ekin = 0.5*Props.m*dot(v,v); 00538 Erot = 0.5*(I(0)*w(0)*w(0)+I(1)*w(1)*w(1)+I(2)*w(2)*w(2)); 00539 Dmax = Props.R; 00540 } 00541 else 00542 { 00543 Mat3_t It; 00544 double Xi[3] = { MinX() , MinY() , MinZ() }; 00545 double Xs[3] = { MaxX() , MaxY() , MaxZ() }; 00546 Numerical::MonteCarlo<Particle> MC(this, Numerical::VEGAS, NCalls); 00547 Props.V = MC.Integrate(&Particle::Vol, Xi,Xs); 00548 x(0) = MC.Integrate(&Particle::Xc, Xi,Xs)/Props.V; 00549 x(1) = MC.Integrate(&Particle::Yc, Xi,Xs)/Props.V; 00550 x(2) = MC.Integrate(&Particle::Zc, Xi,Xs)/Props.V; 00551 It(0,0) = MC.Integrate(&Particle::Ixx, Xi,Xs); 00552 It(1,1) = MC.Integrate(&Particle::Iyy, Xi,Xs); 00553 It(2,2) = MC.Integrate(&Particle::Izz, Xi,Xs); 00554 It(1,0) = MC.Integrate(&Particle::Ixy, Xi,Xs); 00555 It(2,0) = MC.Integrate(&Particle::Ixz, Xi,Xs); 00556 It(2,1) = MC.Integrate(&Particle::Iyz, Xi,Xs); 00557 It(0,1) = It(1,0); 00558 It(0,2) = It(2,0); 00559 It(1,2) = It(2,1); 00560 00561 Vec3_t xp,yp,zp; 00562 Eig(It,I,xp,yp,zp); 00563 std::cout << x(0) << std::endl; 00564 I *= Props.rho; 00565 Q(0) = 0.5*sqrt(1+xp(0)+yp(1)+zp(2)); 00566 Q(1) = (yp(2)-zp(1))/(4*Q(0)); 00567 Q(2) = (zp(0)-xp(2))/(4*Q(0)); 00568 Q(3) = (xp(1)-yp(0))/(4*Q(0)); 00569 Q = Q/norm(Q); 00570 Rotation(w,Q,wb); 00571 w = wb; 00572 Props.m = Props.rho*Props.V; 00573 Ekin = 0.5*Props.m*dot(v,v); 00574 Erot = 0.5*(I(0)*w(0)*w(0)+I(1)*w(1)*w(1)+I(2)*w(2)*w(2)); 00575 Dmax = Distance(x,(*Verts[0]))+Props.R; 00576 for (size_t i=1; i<Verts.Size(); ++i) 00577 { 00578 if (Distance(x,(*Verts[i]))+Props.R > Dmax) Dmax = Distance(x,(*Verts[i]))+Props.R; 00579 } 00580 } 00581 PropsReady = true; 00582 } 00583 00584 inline bool Particle::IsInside (Vec3_t & V) 00585 { 00586 bool inside = false; 00587 size_t nv = Verts.Size(),ne = Edges.Size(),nf = Faces.Size(); 00588 if (Distance(x,V)>Dmax) return inside; 00589 for (size_t i = 0; i < nv; i++) 00590 { 00591 if (Distance(V,*Verts[i]) < Props.R) { 00592 inside = true; 00593 return inside; 00594 } 00595 } 00596 00597 for (size_t i = 0; i < ne; i++) 00598 { 00599 if (Distance(V,*Edges[i]) < Props.R) { 00600 inside = true; 00601 return inside; 00602 } 00603 } 00604 for (size_t i = 0; i < nf; i++) 00605 { 00606 if (Distance(V,*Faces[i]) < Props.R) { 00607 inside = true; 00608 return inside; 00609 } 00610 } 00611 if (nf>3) 00612 { 00613 size_t k = 0; 00614 double Mindistance = Distance(V,*Faces[k]); 00615 for (size_t i = 1; i < nf; i++) 00616 { 00617 if (Distance(V,*Faces[i])<Mindistance) 00618 { 00619 k = i; 00620 Mindistance = Distance(V,*Faces[k]); 00621 } 00622 } 00623 Vec3_t ct(0,0,0); 00624 Faces[k]->Centroid(ct); 00625 Vec3_t pro = V - ct; 00626 Vec3_t nor; 00627 Faces[k]->Normal(nor); 00628 if (dot(pro,nor)<0) inside =true; 00629 } 00630 00631 00632 return inside; 00633 } 00634 00635 inline bool Particle::IsInsideAlt(Vec3_t & V) 00636 { 00637 bool inside = false; 00638 size_t nv = Verts.Size(),ne = Edges.Size(),nf = Faces.Size(); 00639 if (Distance(x,V)>Dmax) return inside; 00640 for (size_t i = 0; i < nv; i++) 00641 { 00642 if (Distance(V,*Verts[i]) < Props.R) { 00643 inside = true; 00644 return inside; 00645 } 00646 } 00647 00648 for (size_t i = 0; i < ne; i++) 00649 { 00650 if (Distance(V,*Edges[i]) < Props.R) { 00651 inside = true; 00652 return inside; 00653 } 00654 } 00655 for (size_t i = 0; i < nf; i++) 00656 { 00657 if (Distance(V,*Faces[i]) < Props.R) { 00658 inside = true; 00659 return inside; 00660 } 00661 } 00662 if (nf>3) 00663 { 00664 inside = true; 00665 Vec3_t D = V - x; 00666 for (size_t i = 0; i < nf; i++) 00667 { 00668 Vec3_t B = x - *Faces[i]->Edges[0]->X0; 00669 Mat3_t M; 00670 M(0,0) = -D(0); 00671 M(0,1) = (Faces[i]->Edges[0]->dL)(0); 00672 M(0,2) = (Faces[i]->Edges[1]->dL)(0); 00673 M(1,0) = -D(1); 00674 M(1,1) = (Faces[i]->Edges[0]->dL)(1); 00675 M(1,2) = (Faces[i]->Edges[1]->dL)(1); 00676 M(2,0) = -D(2); 00677 M(2,1) = (Faces[i]->Edges[0]->dL)(2); 00678 M(2,2) = (Faces[i]->Edges[1]->dL)(2); 00679 Vec3_t X; 00680 try { Sol(M,B,X); } 00681 catch (Fatal * fatal) { continue; } 00682 if (X(0)>1.0||X(0)<0.0) continue; 00683 B = *Faces[i]->Edges[0]->X0 + Faces[i]->Edges[0]->dL*X(1)+Faces[i]->Edges[1]->dL*X(2); 00684 Vec3_t nor; 00685 Faces[i]->Normal(nor); 00686 bool test = true; 00687 for (size_t j=0; j<Faces[i]->Edges.Size(); j++) 00688 { 00689 Vec3_t tmp = B-*Faces[i]->Edges[j]->X0; 00690 if (dot(cross(Faces[i]->Edges[j]->dL,tmp),nor)<0) test = false; 00691 } 00692 if (test) inside = false; 00693 } 00694 } 00695 00696 00697 return inside; 00698 } 00699 00700 inline double Particle::IsInside (double * V) 00701 { 00702 Vec3_t p(V); 00703 return static_cast<double>(IsInside(p)); 00704 } 00705 00706 inline double Particle::MaxX () 00707 { 00708 double result = (*Verts[0])(0)+Props.R; 00709 for (size_t i = 1; i < Verts.Size(); i++) 00710 { 00711 if ((*Verts[i])(0)+Props.R > result) result = (*Verts[i])(0)+Props.R; 00712 } 00713 return result; 00714 } 00715 00716 inline double Particle::MaxY () 00717 { 00718 double result = (*Verts[0])(1)+Props.R; 00719 for (size_t i = 1; i < Verts.Size(); i++) 00720 { 00721 if ((*Verts[i])(1)+Props.R > result) result = (*Verts[i])(1)+Props.R; 00722 } 00723 return result; 00724 } 00725 00726 inline double Particle::MaxZ () 00727 { 00728 double result = (*Verts[0])(2)+Props.R; 00729 for (size_t i = 1; i < Verts.Size(); i++) 00730 { 00731 if ((*Verts[i])(2)+Props.R > result) result = (*Verts[i])(2)+Props.R; 00732 } 00733 return result; 00734 } 00735 00736 inline double Particle::MinX () 00737 { 00738 double result = (*Verts[0])(0)-Props.R; 00739 for (size_t i = 1; i < Verts.Size(); i++) 00740 { 00741 if ((*Verts[i])(0)-Props.R < result) result = (*Verts[i])(0)-Props.R; 00742 } 00743 return result; 00744 } 00745 00746 inline double Particle::MinY () 00747 { 00748 double result = (*Verts[0])(1)-Props.R; 00749 for (size_t i = 1; i < Verts.Size(); i++) 00750 { 00751 if ((*Verts[i])(1)-Props.R < result) result = (*Verts[i])(1)-Props.R; 00752 } 00753 return result; 00754 } 00755 00756 inline double Particle::MinZ () 00757 { 00758 double result = (*Verts[0])(2)-Props.R; 00759 for (size_t i = 1; i < Verts.Size(); i++) 00760 { 00761 if ((*Verts[i])(2)-Props.R < result) result = (*Verts[i])(2)-Props.R; 00762 } 00763 return result; 00764 } 00765 00766 // Integrants for the calc of properties 00767 00768 inline double Particle::Vol (double * X) 00769 { 00770 return IsInside(X); 00771 } 00772 00773 inline double Particle::Xc (double * X) 00774 { 00775 return X[0]*IsInside(X); 00776 } 00777 00778 inline double Particle::Yc (double * X) 00779 { 00780 return X[1]*IsInside(X); 00781 } 00782 00783 inline double Particle::Zc (double * X) 00784 { 00785 return X[2]*IsInside(X); 00786 } 00787 00788 inline double Particle::Ixx (double * X) 00789 { 00790 return ((X[1]-x(1))*(X[1]-x(1))+(X[2]-x(2))*(X[2]-x(2)))*IsInside(X); 00791 } 00792 00793 inline double Particle::Iyy (double * X) 00794 { 00795 return ((X[0]-x(0))*(X[0]-x(0))+(X[2]-x(2))*(X[2]-x(2)))*IsInside(X); 00796 } 00797 00798 inline double Particle::Izz (double * X) 00799 { 00800 return ((X[0]-x(0))*(X[0]-x(0))+(X[1]-x(1))*(X[1]-x(1)))*IsInside(X); 00801 } 00802 00803 inline double Particle::Ixy (double * X) 00804 { 00805 return -(X[0]-x(0))*(X[1]-x(1))*IsInside(X); 00806 } 00807 00808 inline double Particle::Ixz (double * X) 00809 { 00810 return -(X[0]-x(0))*(X[2]-x(2))*IsInside(X); 00811 } 00812 00813 inline double Particle::Iyz (double * X) 00814 { 00815 return -(X[1]-x(1))*(X[2]-x(2))*IsInside(X); 00816 } 00817 00818 #endif // MECHSYS_DEM_PARTICLE_H