![]() |
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 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