MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/sph/domain.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 
00022 #ifndef MECHSYS_SPH_DOMAIN_H
00023 #define MECHSYS_SPH_DOMAIN_H
00024 
00025 // Mechsys
00026 #include <mechsys/sph/interacton.h>
00027 #include <mechsys/dem/graph.h>
00028 #include <mechsys/util/stopwatch.h>
00029 
00030 namespace SPH {
00031 
00032 class Domain
00033 {
00034 public:
00035 
00036     // Constructor
00037     Domain(iVec3_t n, Vec3_t Xmin, Vec3_t Xmax);  
00038 
00039     // Destructor
00040     ~Domain ();
00041 
00042     // Methods
00043     void AddBox(Vec3_t const & x, size_t nx, size_t ny, size_t nz, double h, double s,  double rho0, bool Fixed);      
00044     void AddRandomBox(Vec3_t const &V, double Lx, double Ly, double Lz,
00045                                        size_t nx, size_t ny, size_t nz, double rho0, double R, size_t RandomSeed=100); 
00046     void StartAcceleration (Vec3_t const & a = Vec3_t(0.0,0.0,0.0));                                                   
00047     void ComputeAcceleration (double dt);                                                                              
00048     void Move                (double dt);                                                                              
00049     void WriteBPY (char const * FileKey);                                                                              
00050     void WritePOV (char const * FileKey);                                                                              
00051     void WriteVTK (char const * FileKey);                                                                              
00052     void ResetInteractons();                                                                                           
00053     void ResetDisplacements();                                                                                         
00054     void ResetContacts();                                                                                              
00055     double MaxDisplacement();                                                                                          
00056     void Solve    (double tf, double dt, double dtOut, char const * TheFileKey, bool RenderVideo=true);                
00057 
00058     // Data
00059     Vec3_t                  CamPos;         
00060     Vec3_t                  Gravity;        
00061     Array <SPHParticle*>    Particles;      
00062     Array <SPHInteracton*>  Interactons;    
00063     Array <SPHInteracton*>  PInteractons;   
00064     size_t                  idx_out;        
00065     double                  Time;           
00066     double                  Alpha;          
00067     iVec3_t                 N_side;         
00068     Vec3_t                  DXmin;          
00069     Vec3_t                  DXmax;          
00070 };
00071 
00073 
00074 // Constructor
00075 inline Domain::Domain (iVec3_t n, Vec3_t Xmin, Vec3_t Xmax)
00076 {
00077     CamPos  = 1.0,2.0,3.0;
00078     Time    = 0.0;
00079     Gravity = 0.0,0.0,0.0;
00080     Alpha   = 0.1;
00081     N_side  = n;
00082     DXmin   = Xmin;
00083     DXmax   = Xmax;
00084 }
00085 
00086 inline Domain::~Domain ()
00087 {
00088     for (size_t i=0; i<Particles.Size();   ++i) if (Particles  [i]!=NULL) delete Particles  [i];
00089     for (size_t i=0; i<Interactons.Size(); ++i) if (Interactons[i]!=NULL) delete Interactons[i];
00090 }
00091 
00092 
00093 // Methods
00094 inline void Domain::AddBox(Vec3_t const & V, size_t nx, size_t ny, size_t nz, double R, double s, double rho0, bool Fixed)
00095 {
00096     Vec3_t C(V);
00097     C -= Vec3_t((nx-1)*R,(ny-1)*R,(nz-1)*R);
00098     for (size_t i = 0;i<nx;i++)
00099     for (size_t j = 0;j<ny;j++)
00100     for (size_t k = 0;k<nz;k++)
00101     {
00102         Vec3_t x(2*i*R,2*j*R,2*k*R);
00103         x +=C;
00104         Particles.Push(new SPHParticle(x,OrthoSys::O,rho0,s,Fixed));
00105     }
00106 }
00107 
00108 inline void Domain::AddRandomBox(Vec3_t const & V, double Lx, double Ly, double Lz, size_t nx, size_t ny, size_t nz, double rho0, double R, size_t RandomSeed)
00109 {
00110     Util::Stopwatch stopwatch;
00111     printf("\n%s--- Generating random packing of spheres ----------------------------------------%s\n",TERM_CLR1,TERM_RST);
00112     const double x_min=-Lx/2.0+V(0), x_max=Lx/2.0+V(0);
00113     const double y_min=-Ly/2.0+V(1), y_max=Ly/2.0+V(1);
00114     const double z_min=-Lz/2.0+V(2), z_max=Lz/2.0+V(2);
00115     double qin = 0.95;
00116     srand(RandomSeed);
00117     for (size_t i=0; i<nx; i++)
00118     {
00119         for (size_t j=0; j<ny; j++)
00120         {
00121             for (size_t k=0; k<nz; k++)
00122             {
00123                 double x = x_min+(i+0.5*qin+(1-qin)*double(rand())/RAND_MAX)*(x_max-x_min)/nx;
00124                 double y = y_min+(j+0.5*qin+(1-qin)*double(rand())/RAND_MAX)*(y_max-y_min)/ny;
00125                 double z = z_min+(k+0.5*qin+(1-qin)*double(rand())/RAND_MAX)*(z_max-z_min)/nz;
00126                 Particles.Push(new SPHParticle(Vec3_t(x,y,z),OrthoSys::O,rho0,R,false));
00127             }
00128         }
00129     }
00130     printf("%s  Num of particles   = %d%s\n",TERM_CLR2,Particles.Size(),TERM_RST);
00131 }
00132 
00133 inline void Domain::StartAcceleration (Vec3_t const & a)
00134 {
00135     for (size_t i=0; i<Particles.Size(); i++)
00136     {
00137         Particles[i]->a = a;
00138         Particles[i]->dDensity = 0.0;
00139     }
00140 }
00141 
00142 inline void Domain::ComputeAcceleration (double dt)
00143 {
00144     for (size_t i=0; i<PInteractons.Size(); i++) PInteractons[i]->CalcForce(dt);
00145 }
00146 
00147 inline void Domain::Move (double dt)
00148 {
00149     for (size_t i=0; i<Particles.Size(); i++) Particles[i]->Move(dt);
00150 }
00151 
00152 inline void Domain::WritePOV (char const * FileKey)
00153 {
00154     String fn(FileKey);
00155     fn.append(".pov");
00156     std::ofstream of(fn.CStr(), std::ios::out);
00157     POVHeader (of);
00158     POVSetCam (of, CamPos, OrthoSys::O);
00159     for (size_t i=0; i<Particles.Size(); i++) 
00160     {
00161         if (Particles[i]->IsFree) POVDrawVert(Particles[i]->x,of,Particles[i]->h,"Blue");
00162         else                      POVDrawVert(Particles[i]->x,of,Particles[i]->h,"Col_Glass_Ruby");
00163     }
00164     of.close();
00165 }
00166 
00167 inline void Domain::WriteBPY (char const * FileKey)
00168 {
00169     String fn(FileKey);
00170     fn.append(".bpy");
00171     std::ofstream of(fn.CStr(), std::ios::out);
00172     BPYHeader(of);
00173     for (size_t i=0; i<Particles.Size(); i++) BPYDrawVert(Particles[i]->x,of,Particles[i]->h);
00174     of.close();
00175 }
00176 
00177 inline void Domain::WriteVTK (char const * FileKey)
00178 {
00179     // Header
00180     std::ostringstream oss;
00181     oss << "# vtk DataFile Version 2.0\n";
00182     oss << "TimeStep = " << idx_out << "\n";
00183     oss << "ASCII\n";
00184     oss << "DATASET STRUCTURED_POINTS\n";
00185     oss << "DIMENSIONS "   << N_side(0)                     << " " << N_side(1)                      << " " << N_side(2)                      << "\n";
00186     oss << "ORIGIN "       << DXmin(0)                      << " " << DXmin(1)                       << " " << DXmin(2)                       << "\n";
00187     oss << "SPACING "      << (DXmax(0)-DXmin(0))/N_side(0) << " " << (DXmax(1)-DXmin(1))/N_side(1)  << " " << (DXmax(2)-DXmin(2))/N_side(2)  << "\n";
00188     oss << "POINT_DATA "   << N_side(0)*N_side(1)*N_side(2) << "\n";
00189 
00190     Array<double> rho(N_side(0)*N_side(1)*N_side(2));    //Array of density
00191     Array<double> Press(N_side(0)*N_side(1)*N_side(2));  //Array of pressures
00192     Array<double> Water(N_side(0)*N_side(1)*N_side(2));  //Array of water content
00193 
00194     for (size_t i = 0;i < N_side(0)*N_side(1)*N_side(2); ++i)
00195     {
00196         Vec3_t x((DXmax(0)-DXmin(0))/N_side(0)*(i%N_side(0))          +DXmin(0),
00197                  (DXmax(1)-DXmin(1))/N_side(1)*(i/N_side(0)/N_side(2))+DXmin(1),
00198                  (DXmax(2)-DXmin(2))/N_side(2)*(i%N_side(2))          +DXmin(2));
00199         rho [i] = 0.0;
00200         Press [i] = 0.0;
00201         Water [i] = 0.0;
00202         for (size_t j = 0;j < Particles.Size();j++)
00203         {
00204             if (Particles[j]->IsFree) 
00205             {
00206                 double Ker = SPHKernel(x,Particles[j]->x,Particles[j]->h);
00207                 rho[i]      += Particles[j]->Density*Ker;
00208                 Press[i]    += Pressure(Particles[j]->Density)*Ker;
00209                 Water[i]    += Particles[j]->Density0/Particles[j]->Density*Ker;
00210             }
00211         }
00212     }
00213 
00214 
00215     //Density field
00216     oss << "SCALARS Density float 1\n";
00217     oss << "LOOKUP_TABLE default\n";
00218     for (size_t i = 0;i < N_side(0)*N_side(1)*N_side(2); ++i)
00219     {
00220         oss << rho[i] << "\n";
00221     }
00222 
00223     //Density field
00224     oss << "SCALARS Pressure float 1\n";
00225     oss << "LOOKUP_TABLE default\n";
00226     for (size_t i = 0;i < N_side(0)*N_side(1)*N_side(2); ++i)
00227     {
00228         oss << Press[i] << "\n";
00229     }
00230     
00231     //Free surface
00232     oss << "SCALARS Water float 1\n";
00233     oss << "LOOKUP_TABLE default\n";
00234     for (size_t i = 0;i < N_side(0)*N_side(1)*N_side(2); ++i)
00235     {
00236         oss << Water[i] << "\n";
00237     }
00238 
00239     // Open/create file, write to file, and close file
00240     String fn(FileKey);
00241     fn.append(".vtk");
00242     std::ofstream  of;
00243     of.open (fn.CStr(), std::ios::out);
00244     of << oss.str();
00245     of.close();
00246 }
00247 
00248 inline void Domain::ResetInteractons()
00249 {
00250     // delete old interactors
00251     for (size_t i=0; i<Interactons.Size(); ++i)
00252     {
00253         if (Interactons[i]!=NULL) delete Interactons[i];
00254     }
00255 
00256     // new interactors
00257     Interactons.Resize(0);
00258     for (size_t i=0; i<Particles.Size()-1; i++)
00259     {
00260         for (size_t j=i+1; j<Particles.Size(); j++)
00261         {
00262             // if both particles are fixed, don't create any intereactor
00263             if (!Particles[i]->IsFree && !Particles[j]->IsFree) continue;
00264             else 
00265             {
00266                 //SPHInteracton * I = new SPHInteracton(Particles[i],Particles[j]);
00267                 //if (I->UpdateContacts(Alpha)) Interactons.Push(I);
00268                 //else delete I;
00269                 Interactons.Push(new SPHInteracton(Particles[i],Particles[j]));
00270             }
00271         }
00272     }
00273 }
00274 
00275 inline void Domain::ResetDisplacements()
00276 {
00277     for (size_t i=0; i<Particles.Size(); i++)
00278     {
00279         Particles[i]->ResetDisplacements();
00280     }
00281 }
00282 
00283 inline void Domain::ResetContacts()
00284 {
00285     PInteractons.Resize(0);
00286     for (size_t i=0; i<Interactons.Size(); i++)
00287     {
00288         if(Interactons[i]->UpdateContacts(Alpha)) PInteractons.Push(Interactons[i]);
00289     }
00290 }
00291 
00292 inline double Domain::MaxDisplacement()
00293 {
00294     double md = 0.0;
00295     for (size_t i=0; i<Particles.Size(); i++)
00296     {
00297         double mpd = Particles[i]->MaxDisplacement();
00298         if (mpd > md) md = mpd;
00299     }
00300     return md;
00301 }
00302 
00303 inline void Domain::Solve (double tf, double dt, double dtOut, char const * TheFileKey, bool RenderVideo)
00304 {
00305     Util::Stopwatch stopwatch;
00306     printf("\n%s--- Solving ---------------------------------------------------------------------%s\n",TERM_CLR1,TERM_RST);
00307     idx_out = 0;
00308     double tout = Time;
00309 
00310     ResetInteractons();
00311     ResetDisplacements();
00312     ResetContacts();
00313 
00314 
00315     while (Time<tf)
00316     {
00317         // Calculate the acceleration for each particle
00318         StartAcceleration(Gravity);
00319         ComputeAcceleration(dt);
00320 
00321         // Move each particle
00322         Move(dt);
00323 
00324         // next time position
00325         Time += dt;
00326 
00327 
00328         // output
00329         if (Time>=tout)
00330         {
00331             idx_out++;
00332             if (TheFileKey!=NULL)
00333             {
00334                 if(RenderVideo)
00335                 {
00336                     String fn;
00337                     fn.Printf    ("%s_%08d", TheFileKey, idx_out);
00338                     WritePOV     (fn.CStr());
00339                     WriteVTK     (fn.CStr());
00340                 }
00341             }
00342             tout += dtOut;
00343         }
00344 
00345         if (MaxDisplacement()>Alpha)
00346         {
00347             ResetDisplacements();
00348             ResetContacts();
00349         }
00350         
00351     }
00352 }
00353 
00354 }; // namespace SPH
00355 
00356 #endif // MECHSYS_SPH_DOMAIN_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines