MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/dem/particle.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines