![]() |
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 00021 #ifndef MECHSYS_LBM_DOMAIN_H 00022 #define MECHSYS_LBM_DOMAIN_H 00023 00024 // STD 00025 #include <map> 00026 #include <vector> 00027 #include <utility> 00028 #include <set> 00029 00030 // MechSys 00031 #include <mechsys/lbm/Interacton.h> 00032 00033 using std::set; 00034 using std::map; 00035 using std::pair; 00036 using std::make_pair; 00037 00038 namespace LBM 00039 { 00040 00041 class Domain 00042 { 00043 public: 00044 //typedefs 00045 typedef void (*ptDFun_t) (Domain & Dom, void * UserData); 00046 00047 //Constructors 00048 Domain (LBMethod Method, 00049 Array<double> nu, 00050 iVec3_t Ndim, 00051 double dx, 00052 double dt); 00053 00054 //Special constructor with only one component, the parameters are the same as above 00055 Domain (LBMethod Method, 00056 double nu, 00057 iVec3_t Ndim, 00058 double dx, 00059 double dt); 00060 00061 00062 //Methods 00063 #ifdef USE_HDF5 00064 void WriteXDMF (char const * FileKey); 00065 #endif 00066 void ApplyForce (size_t n = 0, size_t Np = 1); 00067 void Collide (size_t n = 0, size_t Np = 1); 00068 void ImprintLattice (); 00069 void Solve(double Tf, double dtOut, ptDFun_t ptSetup=NULL, ptDFun_t ptReport=NULL, 00070 char const * FileKey=NULL, bool RenderVideo=true, size_t Nproc=1); 00071 void AddDisk (int TheTag, Vec3_t const & TheX, Vec3_t const & TheV, Vec3_t const & TheW, double Therho, double TheR, double dt); 00072 void AddSphere(int TheTag, Vec3_t const & TheX, Vec3_t const & TheV, Vec3_t const & TheW, double Therho, double TheR, double dt); 00073 void ResetContacts(); 00074 void ResetDisplacements(); 00075 double MaxDisplacement(); 00076 void BoundingBox(Vec3_t & Xmin, Vec3_t & Xmax); 00077 00078 00079 00080 //Data 00081 bool PrtVec; 00082 Array<Lattice> Lat; 00083 Array <Particle *> Particles; 00084 Array <Interacton *> Interactons; 00085 Array <Interacton *> CInteractons; 00086 Array <iVec3_t> CellPairs; 00087 set<pair<Particle *, Particle *> > Listofpairs; 00088 double Time; 00089 double dt; 00090 double Alpha; 00091 double Gmix; 00092 void * UserData; 00093 size_t idx_out; 00094 00095 }; 00096 00097 #ifdef USE_THREAD 00098 struct MtData 00099 { 00100 size_t ProcRank; 00101 size_t N_Proc; 00102 LBM::Domain * Dom; 00103 }; 00104 00105 void * GlobalSetZeroGamma(void * Data) 00106 { 00107 MtData & dat = (*static_cast<MtData *>(Data)); 00108 for (size_t i=0;i<dat.Dom->Lat.Size();i++) 00109 { 00110 dat.Dom->Lat[i].SetZeroGamma(dat.ProcRank, dat.N_Proc); 00111 } 00112 } 00113 00114 void * GlobalApplyForce (void * Data) 00115 { 00116 MtData & dat = (*static_cast<MtData *>(Data)); 00117 dat.Dom->ApplyForce(dat.ProcRank, dat.N_Proc); 00118 } 00119 00120 void * GlobalCollide (void * Data) 00121 { 00122 MtData & dat = (*static_cast<MtData *>(Data)); 00123 dat.Dom->Collide(dat.ProcRank, dat.N_Proc); 00124 } 00125 00126 void * GlobalBounceBack (void * Data) 00127 { 00128 MtData & dat = (*static_cast<MtData *>(Data)); 00129 for (size_t i=0;i<dat.Dom->Lat.Size();i++) 00130 { 00131 dat.Dom->Lat[i].BounceBack(dat.ProcRank, dat.N_Proc); 00132 } 00133 } 00134 00135 void * GlobalStream (void * Data) 00136 { 00137 MtData & dat = (*static_cast<MtData *>(Data)); 00138 for (size_t i=0;i<dat.Dom->Lat.Size();i++) 00139 { 00140 dat.Dom->Lat[i].Stream(dat.ProcRank, dat.N_Proc); 00141 } 00142 } 00143 00144 void * GlobalStream1 (void * Data) 00145 { 00146 MtData & dat = (*static_cast<MtData *>(Data)); 00147 for (size_t i=0;i<dat.Dom->Lat.Size();i++) 00148 { 00149 dat.Dom->Lat[i].Stream1(dat.ProcRank, dat.N_Proc); 00150 } 00151 } 00152 00153 void * GlobalStream2 (void * Data) 00154 { 00155 MtData & dat = (*static_cast<MtData *>(Data)); 00156 for (size_t i=0;i<dat.Dom->Lat.Size();i++) 00157 { 00158 dat.Dom->Lat[i].Stream2(dat.ProcRank, dat.N_Proc); 00159 } 00160 } 00161 00162 #endif 00163 00164 inline Domain::Domain(LBMethod Method, Array<double> nu, iVec3_t Ndim, double dx, double Thedt) 00165 { 00166 if (nu.Size()==0) throw new Fatal("LBM::Domain: Declare at leat one fluid please"); 00167 if (Ndim(2) >1&&Method==D2Q9) throw new Fatal("LBM::Domain: D2Q9 scheme does not allow for a third dimension, please set Ndim(2)=1 or change to D3Q15"); 00168 if (Ndim(2)==1&&Method==D3Q15) throw new Fatal("LBM::Domain: Ndim(2) is greater than 1. Either change the method to D2Q9 or increse the z-dimension"); 00169 for (size_t i=0;i<nu.Size();i++) 00170 { 00171 Lat.Push(Lattice(Method,nu[i],Ndim,dx,Thedt)); 00172 } 00173 Time = 0.0; 00174 dt = Thedt; 00175 Alpha = 10.0; 00176 PrtVec = false; 00177 } 00178 00179 inline Domain::Domain(LBMethod Method, double nu, iVec3_t Ndim, double dx, double Thedt) 00180 { 00181 Lat.Push(Lattice(Method,nu,Ndim,dx,Thedt)); 00182 if (Ndim(2) >1&&Method==D2Q9) throw new Fatal("LBM::Domain: D2Q9 scheme does not allow for a third dimension, please set Ndim(2)=1 or change to D3Q15"); 00183 if (Ndim(2)==1&&Method==D3Q15) throw new Fatal("LBM::Domain: Ndim(2) is greater than 1. Either change the method to D2Q9 or increse the z-dimension"); 00184 Time = 0.0; 00185 dt = Thedt; 00186 Alpha = 10.0; 00187 PrtVec = false; 00188 } 00189 00190 #ifdef USE_HDF5 00191 inline void Domain::WriteXDMF(char const * FileKey) 00192 { 00193 String fn(FileKey); 00194 fn.append(".h5"); 00195 hid_t file_id; 00196 file_id = H5Fcreate(fn.CStr(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); 00197 for (size_t j=0;j<Lat.Size();j++) 00198 { 00199 // Creating data sets 00200 float * Density = new float[Lat[0].Ndim[0]*Lat[0].Ndim[1]*Lat[0].Ndim[2]]; 00201 float * Gamma = new float[Lat[0].Ndim[0]*Lat[0].Ndim[1]*Lat[0].Ndim[2]]; 00202 //float * Velocity = new float[Lat[0].Ndim[0]*Lat[0].Ndim[1]*Lat[0].Ndim[2]]; 00203 //float * MassFlux = new float[Lat[0].Ndim[0]*Lat[0].Ndim[1]*Lat[0].Ndim[2]]; 00204 float * Vvec = new float[3*Lat[0].Ndim[0]*Lat[0].Ndim[1]*Lat[0].Ndim[2]]; 00205 for (size_t i=0;i<Lat[j].Cells.Size();i++) 00206 { 00207 double rho = Lat[j].Cells[i]->Rho; 00208 Vec3_t vel = Lat[j].Cells[i]->Vel; 00209 Density [i] = (float) rho; 00210 Gamma [i] = (float) Lat[j].Cells[i]->IsSolid? 1.0:Lat[j].Cells[i]->Gamma; 00211 //Velocity [i] = (float) norm(vel); 00212 //MassFlux [i] = (float) rho*norm(vel); 00213 Vvec[3*i ] = (float) vel(0); 00214 Vvec[3*i+1] = (float) vel(1); 00215 Vvec[3*i+2] = (float) vel(2); 00216 } 00217 00218 //Write the data 00219 hsize_t dims[1]; 00220 dims[0] = Lat[0].Ndim(0)*Lat[0].Ndim(1)*Lat[0].Ndim(2); 00221 String dsname; 00222 dsname.Printf("Density_%d",j); 00223 H5LTmake_dataset_float(file_id,dsname.CStr(),1,dims,Density ); 00224 dsname.Printf("Gamma_%d",j); 00225 H5LTmake_dataset_float(file_id,dsname.CStr(),1,dims,Gamma ); 00226 //dsname.Printf("Velocity_%d",j); 00227 //H5LTmake_dataset_float(file_id,dsname.CStr(),1,dims,Velocity); 00228 //dsname.Printf("MassFlux_%d",j); 00229 //H5LTmake_dataset_float(file_id,dsname.CStr(),1,dims,MassFlux); 00230 dims[0] = 3*Lat[0].Ndim(0)*Lat[0].Ndim(1)*Lat[0].Ndim(2); 00231 dsname.Printf("Velocity_%d",j); 00232 H5LTmake_dataset_float(file_id,dsname.CStr(),1,dims,Vvec ); 00233 00234 delete [] Density ; 00235 delete [] Gamma ; 00236 //delete [] Velocity; 00237 //delete [] MassFlux; 00238 delete [] Vvec ; 00239 } 00240 00241 //Closing the file 00242 H5Fclose(file_id); 00243 00244 // Writing xmf file 00245 std::ostringstream oss; 00246 00247 if (Lat[0].Ndim(2)==1) 00248 { 00249 oss << "<?xml version=\"1.0\" ?>\n"; 00250 oss << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n"; 00251 oss << "<Xdmf Version=\"2.0\">\n"; 00252 oss << " <Domain>\n"; 00253 oss << " <Grid Name=\"mesh1\" GridType=\"Uniform\">\n"; 00254 oss << " <Topology TopologyType=\"2DCoRectMesh\" Dimensions=\"" << Lat[0].Ndim(1) << " " << Lat[0].Ndim(0) << "\"/>\n"; 00255 oss << " <Geometry GeometryType=\"ORIGIN_DXDY\">\n"; 00256 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"2\"> 0.0 0.0\n"; 00257 oss << " </DataItem>\n"; 00258 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"2\"> 1.0 1.0\n"; 00259 oss << " </DataItem>\n"; 00260 oss << " </Geometry>\n"; 00261 for (size_t j=0;j<Lat.Size();j++) 00262 { 00263 oss << " <Attribute Name=\"Density_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00264 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00265 oss << " " << fn.CStr() <<":/Density_" << j << "\n"; 00266 oss << " </DataItem>\n"; 00267 oss << " </Attribute>\n"; 00268 oss << " <Attribute Name=\"Gamma_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00269 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00270 oss << " " << fn.CStr() <<":/Gamma_" << j << "\n"; 00271 oss << " </DataItem>\n"; 00272 oss << " </Attribute>\n"; 00273 //oss << " <Attribute Name=\"Velocity_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00274 //oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00275 //oss << " " << fn.CStr() <<":/Velocity_" << j << "\n"; 00276 //oss << " </DataItem>\n"; 00277 //oss << " </Attribute>\n"; 00278 //oss << " <Attribute Name=\"MassFlux_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00279 //oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00280 //oss << " " << fn.CStr() <<":/MassFlux_" << j << "\n"; 00281 //oss << " </DataItem>\n"; 00282 //oss << " </Attribute>\n"; 00283 oss << " <Attribute Name=\"Velocity_" << j << "\" AttributeType=\"Vector\" Center=\"Node\">\n"; 00284 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " 3\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00285 oss << " " << fn.CStr() <<":/Velocity_" << j << "\n"; 00286 oss << " </DataItem>\n"; 00287 oss << " </Attribute>\n"; 00288 } 00289 oss << " </Grid>\n"; 00290 oss << " </Domain>\n"; 00291 oss << "</Xdmf>\n"; 00292 } 00293 else 00294 { 00295 oss << "<?xml version=\"1.0\" ?>\n"; 00296 oss << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n"; 00297 oss << "<Xdmf Version=\"2.0\">\n"; 00298 oss << " <Domain>\n"; 00299 oss << " <Grid Name=\"mesh1\" GridType=\"Uniform\">\n"; 00300 oss << " <Topology TopologyType=\"3DCoRectMesh\" Dimensions=\"" << Lat[0].Ndim(2) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(0) << "\"/>\n"; 00301 oss << " <Geometry GeometryType=\"ORIGIN_DXDYDZ\">\n"; 00302 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"3\"> 0.0 0.0 0.0\n"; 00303 oss << " </DataItem>\n"; 00304 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"3\"> 1.0 1.0 1.0\n"; 00305 oss << " </DataItem>\n"; 00306 oss << " </Geometry>\n"; 00307 for (size_t j=0;j<Lat.Size();j++) 00308 { 00309 oss << " <Attribute Name=\"Density_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00310 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(2) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00311 oss << " " << fn.CStr() <<":/Density_" << j << "\n"; 00312 oss << " </DataItem>\n"; 00313 oss << " </Attribute>\n"; 00314 oss << " <Attribute Name=\"Gamma_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00315 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(2) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00316 oss << " " << fn.CStr() <<":/Gamma_" << j << "\n"; 00317 oss << " </DataItem>\n"; 00318 oss << " </Attribute>\n"; 00319 //oss << " <Attribute Name=\"Velocity_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00320 //oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(2) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00321 //oss << " " << fn.CStr() <<":/Velocity_" << j << "\n"; 00322 //oss << " </DataItem>\n"; 00323 //oss << " </Attribute>\n"; 00324 //oss << " <Attribute Name=\"MassFlux_" << j << "\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00325 //oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(2) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00326 //oss << " " << fn.CStr() <<":/MassFlux_" << j << "\n"; 00327 //oss << " </DataItem>\n"; 00328 //oss << " </Attribute>\n"; 00329 oss << " <Attribute Name=\"Velocity_" << j << "\" AttributeType=\"Vector\" Center=\"Node\">\n"; 00330 oss << " <DataItem Dimensions=\"" << Lat[0].Ndim(0) << " " << Lat[0].Ndim(1) << " " << Lat[0].Ndim(2) << " 3\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00331 oss << " " << fn.CStr() <<":/Velocity_" << j << "\n"; 00332 oss << " </DataItem>\n"; 00333 oss << " </Attribute>\n"; 00334 } 00335 oss << " </Grid>\n"; 00336 oss << " </Domain>\n"; 00337 oss << "</Xdmf>\n"; 00338 } 00339 fn = FileKey; 00340 fn.append(".xmf"); 00341 std::ofstream of(fn.CStr(), std::ios::out); 00342 of << oss.str(); 00343 of.close(); 00344 } 00345 #endif 00346 00347 inline void Domain::ApplyForce(size_t n, size_t Np) 00348 { 00349 size_t Ni = CellPairs.Size()/Np; 00350 size_t In = n*Ni; 00351 size_t Fn; 00352 n == Np-1 ? Fn = CellPairs.Size() : Fn = (n+1)*Ni; 00353 00354 for (size_t i=In;i<Fn;i++) 00355 { 00356 size_t ind1 = CellPairs[i](0); 00357 size_t ind2 = CellPairs[i](1); 00358 size_t vec = CellPairs[i](2); 00359 for (size_t j=0;j<Lat.Size();j++) 00360 { 00361 bool solid = false; 00362 Cell * c = Lat[j].Cells[ind1]; 00363 double psi; 00364 if (c->IsSolid||c->Gamma>0.0) 00365 { 00366 psi = 1.0; 00367 solid = true; 00368 } 00369 else fabs(Lat[j].G)>1.0e-12 ? psi = Lat[j].Psi(c->Rho) : psi = c->Rho; 00370 for (size_t k=0;k<Lat.Size();k++) 00371 { 00372 Cell * nb = Lat[k].Cells[ind2]; 00373 double nb_psi; 00374 if (nb->IsSolid||nb->Gamma>0.0) 00375 { 00376 nb_psi = 1.0; 00377 solid = true; 00378 } 00379 else fabs(Lat[j].G)>1.0e-12 ? nb_psi = Lat[k].Psi(nb->Rho) : nb_psi = nb->Rho; 00380 double G; 00381 solid ? G = Lat[j].Gs*2.0*ReducedValue(nb->Gs,c->Gs) : G = Lat[j].G; 00382 Vec3_t BF(OrthoSys::O); 00383 if (j==k) 00384 { 00385 BF += -G*psi*nb_psi*c->W[vec]*c->C[vec]; 00386 } 00387 else if(!solid) 00388 { 00389 BF += -Gmix*c->Rho*nb->Rho*c->W[vec]*c->C[vec]; 00390 } 00391 #ifdef USE_THREAD 00392 pthread_mutex_lock(&c ->lck); 00393 pthread_mutex_lock(&nb->lck); 00394 #endif 00395 c ->BForce += BF; 00396 nb->BForce -= BF; 00397 #ifdef USE_THREAD 00398 pthread_mutex_unlock(&c ->lck); 00399 pthread_mutex_unlock(&nb->lck); 00400 #endif 00401 } 00402 } 00403 } 00404 } 00405 00406 void Domain::Collide (size_t n, size_t Np) 00407 { 00408 size_t Ni = Lat[0].Cells.Size()/Np; 00409 size_t In = n*Ni; 00410 size_t Fn; 00411 n == Np-1 ? Fn = Lat[0].Cells.Size() : Fn = (n+1)*Ni; 00412 for (size_t i=In;i<Fn;i++) 00413 { 00414 Vec3_t num(0.0,0.0,0.0); 00415 double den = 0.0; 00416 for (size_t j=0;j<Lat.Size();j++) 00417 { 00418 Cell * c = Lat[j].Cells[i]; 00419 double tau = Lat[j].Tau; 00420 num += c->Vel*c->Rho/tau; 00421 den += c->Rho/tau; 00422 } 00423 Vec3_t Vmix = num/den; 00424 00425 00426 for (size_t j=0;j<Lat.Size();j++) 00427 { 00428 Cell * c = Lat[j].Cells[i]; 00429 double rho = c->Rho; 00430 if (c->IsSolid||rho<1.0e-12) continue; 00431 if (fabs(c->Gamma-1.0)<1.0e-12&&fabs(Lat[j].G)>1.0e-12) continue; 00432 double Tau = Lat[j].Tau; 00433 Vec3_t DV = Vmix + c->BForce*dt/rho; 00434 double Bn = (c->Gamma*(Tau-0.5))/((1.0-c->Gamma)+(Tau-0.5)); 00435 bool valid = true; 00436 double alphal = 1.0; 00437 double alphat = 1.0; 00438 size_t num = 0; 00439 while (valid) 00440 { 00441 valid = false; 00442 alphal = alphat; 00443 for (size_t k=0;k<c->Nneigh;k++) 00444 { 00445 double FDeqn = c->Feq(k,DV,rho); 00446 c->Ftemp[k] = c->F[k] - alphal*((1 - Bn)*(c->F[k] - FDeqn)/Tau - Bn*c->Omeis[k]); 00447 if (c->Ftemp[k]<0.0&&num<1) 00448 { 00449 double temp = fabs(c->F[k]/((1 - Bn)*(c->F[k] - FDeqn)/Tau - Bn*c->Omeis[k])); 00450 if (temp<alphat) alphat = temp; 00451 valid = true; 00452 } 00453 } 00454 num++; 00455 if (num>2) 00456 { 00457 throw new Fatal("Domain::Collide: Redefine your time step, the current value ensures unstability"); 00458 } 00459 } 00460 for (size_t k=0;k<c->Nneigh;k++) 00461 { 00462 if (isnan(c->Ftemp[k])) 00463 { 00464 c->Gamma = 2.0; 00465 #ifdef USE_HDF5 00466 WriteXDMF("error"); 00467 #endif 00468 std::cout << c->Density() << " " << c->BForce << " " << num << " " << alphat << " " << c->Index << " " << c->IsSolid << " " << j << " " << k << std::endl; 00469 throw new Fatal("Domain::Collide: Body force gives nan value, check parameters"); 00470 } 00471 c->F[k] = fabs(c->Ftemp[k]); 00472 } 00473 } 00474 } 00475 } 00476 00477 void Domain::ImprintLattice () 00478 { 00479 00480 // 2D imprint 00481 if (Lat[0].Ndim(2)==1) 00482 { 00483 for (size_t i = 0;i<Particles.Size();i++) 00484 { 00485 LBM::Particle * Pa = Particles[i]; 00486 for (size_t n=std::max(0.0,double(Pa->X(0)-Pa->R-Lat[0].dx)/Lat[0].dx);n<=std::min(double(Lat[0].Ndim(0)-1),double(Pa->X(0)+Pa->R+Lat[0].dx)/Lat[0].dx);n++) 00487 for (size_t m=std::max(0.0,double(Pa->X(1)-Pa->R-Lat[0].dx)/Lat[0].dx);m<=std::min(double(Lat[0].Ndim(1)-1),double(Pa->X(1)+Pa->R+Lat[0].dx)/Lat[0].dx);m++) 00488 { 00489 Cell * cell = Lat[0].GetCell(iVec3_t(n,m,0)); 00490 double x = Lat[0].dx*cell->Index(0); 00491 double y = Lat[0].dx*cell->Index(1); 00492 double z = Lat[0].dx*cell->Index(2); 00493 Vec3_t C(x,y,z); 00494 Array<Vec3_t> P(4); 00495 00496 P[0] = C - 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1; 00497 P[1] = C + 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1; 00498 P[2] = C + 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1; 00499 P[3] = C - 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1; 00500 00501 double len = 0.0; 00502 00503 for (size_t j=0;j<4;j++) 00504 { 00505 Vec3_t D = P[(j+1)%4] - P[j]; 00506 double a = dot(D,D); 00507 double b = 2*dot(P[j]-Pa->X,D); 00508 double c = dot(P[j]-Pa->X,P[j]-Pa->X) - Pa->R*Pa->R; 00509 if (b*b-4*a*c>0.0) 00510 { 00511 double ta = (-b - sqrt(b*b-4*a*c))/(2*a); 00512 double tb = (-b + sqrt(b*b-4*a*c))/(2*a); 00513 if (ta>1.0&&tb>1.0) continue; 00514 if (ta<0.0&&tb<0.0) continue; 00515 if (ta<0.0) ta = 0.0; 00516 if (tb>1.0) tb = 1.0; 00517 len += norm((tb-ta)*D); 00518 } 00519 } 00520 00521 if (len>0.0) 00522 { 00523 for (size_t j=0;j<Lat.Size();j++) 00524 { 00525 cell = Lat[j].GetCell(iVec3_t(n,m,0)); 00526 cell->Gamma = std::max(len/(4.0*Lat[0].dx),cell->Gamma); 00527 if (fabs(cell->Gamma-1.0)<1.0e-12&&fabs(Lat[0].G)>1.0e-12) continue; 00528 Vec3_t B = C - Pa->X; 00529 Vec3_t VelP = Pa->V + cross(Pa->W,B); 00530 double rho = cell->Rho; 00531 double Bn = (cell->Gamma*(cell->Tau-0.5))/((1.0-cell->Gamma)+(cell->Tau-0.5)); 00532 for (size_t k=0;k<cell->Nneigh;k++) 00533 { 00534 double Fvpp = cell->Feq(cell->Op[k],VelP,rho); 00535 double Fvp = cell->Feq(k ,VelP,rho); 00536 cell->Omeis[k] = cell->F[cell->Op[k]] - Fvpp - (cell->F[k] - Fvp); 00537 Vec3_t Flbm = -Bn*cell->Omeis[k]*cell->C[k]; 00538 Pa->F += Flbm; 00539 Pa->T += cross(B,Flbm); 00540 //std::cout << i << " " << Pa->F << " " << Flbm << " " << Bn << std::endl; 00541 } 00542 } 00543 } 00544 } 00545 } 00546 } 00547 00548 //3D imprint 00549 else 00550 { 00551 for (size_t i = 0;i<Particles.Size();i++) 00552 { 00553 LBM::Particle * Pa = Particles[i]; 00554 for (size_t n=std::max(0.0,double(Pa->X(0)-Pa->R-Lat[0].dx)/Lat[0].dx);n<=std::min(double(Lat[0].Ndim(0)-1),double(Pa->X(0)+Pa->R+Lat[0].dx)/Lat[0].dx);n++) 00555 for (size_t m=std::max(0.0,double(Pa->X(1)-Pa->R-Lat[0].dx)/Lat[0].dx);m<=std::min(double(Lat[0].Ndim(1)-1),double(Pa->X(1)+Pa->R+Lat[0].dx)/Lat[0].dx);m++) 00556 for (size_t l=std::max(0.0,double(Pa->X(2)-Pa->R-Lat[0].dx)/Lat[0].dx);l<=std::min(double(Lat[0].Ndim(2)-1),double(Pa->X(2)+Pa->R+Lat[0].dx)/Lat[0].dx);l++) 00557 { 00558 Cell * cell = Lat[0].GetCell(iVec3_t(n,m,l)); 00559 double x = Lat[0].dx*cell->Index(0); 00560 double y = Lat[0].dx*cell->Index(1); 00561 double z = Lat[0].dx*cell->Index(2); 00562 Vec3_t C(x,y,z); 00563 Array<Vec3_t> P(8); 00564 00565 P[0] = C - 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1 + 0.5*Lat[0].dx*OrthoSys::e2; 00566 P[1] = C + 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1 + 0.5*Lat[0].dx*OrthoSys::e2; 00567 P[2] = C + 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1 + 0.5*Lat[0].dx*OrthoSys::e2; 00568 P[3] = C - 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1 + 0.5*Lat[0].dx*OrthoSys::e2; 00569 P[4] = C - 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1 - 0.5*Lat[0].dx*OrthoSys::e2; 00570 P[5] = C + 0.5*Lat[0].dx*OrthoSys::e0 - 0.5*Lat[0].dx*OrthoSys::e1 - 0.5*Lat[0].dx*OrthoSys::e2; 00571 P[6] = C + 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1 - 0.5*Lat[0].dx*OrthoSys::e2; 00572 P[7] = C - 0.5*Lat[0].dx*OrthoSys::e0 + 0.5*Lat[0].dx*OrthoSys::e1 - 0.5*Lat[0].dx*OrthoSys::e2; 00573 00574 double len = 0.0; 00575 00576 for (size_t j=0;j<4;j++) 00577 { 00578 Vec3_t D; 00579 double a; 00580 double b; 00581 double c; 00582 D = P[(j+1)%4] - P[j]; 00583 a = dot(D,D); 00584 b = 2*dot(P[j]-Pa->X,D); 00585 c = dot(P[j]-Pa->X,P[j]-Pa->X) - Pa->R*Pa->R; 00586 if (b*b-4*a*c>0.0) 00587 { 00588 double ta = (-b - sqrt(b*b-4*a*c))/(2*a); 00589 double tb = (-b + sqrt(b*b-4*a*c))/(2*a); 00590 if (ta>1.0&&tb>1.0) continue; 00591 if (ta<0.0&&tb<0.0) continue; 00592 if (ta<0.0) ta = 0.0; 00593 if (tb>1.0) tb = 1.0; 00594 len += norm((tb-ta)*D); 00595 } 00596 D = P[(j+1)%4 + 4] - P[j + 4]; 00597 a = dot(D,D); 00598 b = 2*dot(P[j + 4]-Pa->X,D); 00599 c = dot(P[j + 4]-Pa->X,P[j + 4]-Pa->X) - Pa->R*Pa->R; 00600 if (b*b-4*a*c>0.0) 00601 { 00602 double ta = (-b - sqrt(b*b-4*a*c))/(2*a); 00603 double tb = (-b + sqrt(b*b-4*a*c))/(2*a); 00604 if (ta>1.0&&tb>1.0) continue; 00605 if (ta<0.0&&tb<0.0) continue; 00606 if (ta<0.0) ta = 0.0; 00607 if (tb>1.0) tb = 1.0; 00608 len += norm((tb-ta)*D); 00609 } 00610 D = P[j+4] - P[j]; 00611 a = dot(D,D); 00612 b = 2*dot(P[j]-Pa->X,D); 00613 c = dot(P[j]-Pa->X,P[j]-Pa->X) - Pa->R*Pa->R; 00614 if (b*b-4*a*c>0.0) 00615 { 00616 double ta = (-b - sqrt(b*b-4*a*c))/(2*a); 00617 double tb = (-b + sqrt(b*b-4*a*c))/(2*a); 00618 if (ta>1.0&&tb>1.0) continue; 00619 if (ta<0.0&&tb<0.0) continue; 00620 if (ta<0.0) ta = 0.0; 00621 if (tb>1.0) tb = 1.0; 00622 len += norm((tb-ta)*D); 00623 } 00624 } 00625 00626 if (len>0.0) 00627 { 00628 for (size_t j=0;j<Lat.Size();j++) 00629 { 00630 cell = Lat[j].GetCell(iVec3_t(n,m,l)); 00631 cell->Gamma = std::max(len/(12.0*Lat[0].dx),cell->Gamma); 00632 if (fabs(cell->Gamma-1.0)<1.0e-12&&fabs(Lat[0].G)>1.0e-12) continue; 00633 Vec3_t B = C - Pa->X; 00634 Vec3_t VelP = Pa->V + cross(Pa->W,B); 00635 double rho = cell->Rho; 00636 double Bn = (cell->Gamma*(cell->Tau-0.5))/((1.0-cell->Gamma)+(cell->Tau-0.5)); 00637 for (size_t k=0;k<cell->Nneigh;k++) 00638 { 00639 double Fvpp = cell->Feq(cell->Op[k],VelP,rho); 00640 double Fvp = cell->Feq(k ,VelP,rho); 00641 cell->Omeis[k] = cell->F[cell->Op[k]] - Fvpp - (cell->F[k] - Fvp); 00642 Vec3_t Flbm = -Bn*cell->Omeis[k]*cell->C[k]; 00643 Pa->F += Flbm; 00644 Pa->T += cross(B,Flbm); 00645 } 00646 } 00647 } 00648 } 00649 } 00650 } 00651 } 00652 00653 inline void Domain::ResetDisplacements() 00654 { 00655 for (size_t i=0; i<Particles.Size(); i++) 00656 { 00657 Particles[i]->X0 = Particles[i]->X; 00658 } 00659 } 00660 00661 inline double Domain::MaxDisplacement() 00662 { 00663 double md = 0.0; 00664 for (size_t i=0; i<Particles.Size(); i++) 00665 { 00666 double mdp = norm(Particles[i]->X - Particles[i]->X0); 00667 if (mdp>md) md = mdp; 00668 } 00669 return md; 00670 } 00671 00672 inline void Domain::ResetContacts() 00673 { 00674 if (Particles.Size()==0) return; 00675 for (size_t i=0; i<Particles.Size()-1; i++) 00676 { 00677 bool pi_has_vf = !Particles[i]->IsFree(); 00678 for (size_t j=i+1; j<Particles.Size(); j++) 00679 { 00680 bool pj_has_vf = !Particles[j]->IsFree(); 00681 00682 bool close = (norm(Particles[i]->X-Particles[j]->X)<=Particles[i]->R+Particles[j]->R+2*Alpha); 00683 if ((pi_has_vf && pj_has_vf) || !close) continue; 00684 00685 // checking if the interacton exist for that pair of particles 00686 set<pair<Particle *, Particle *> >::iterator it = Listofpairs.find(make_pair(Particles[i],Particles[j])); 00687 if (it != Listofpairs.end()) 00688 { 00689 continue; 00690 } 00691 Listofpairs.insert(make_pair(Particles[i],Particles[j])); 00692 CInteractons.Push (new Interacton(Particles[i],Particles[j])); 00693 } 00694 } 00695 00696 Interactons.Resize(0); 00697 for (size_t i=0; i<CInteractons.Size(); i++) 00698 { 00699 if(CInteractons[i]->UpdateContacts(Alpha)) Interactons.Push(CInteractons[i]); 00700 } 00701 } 00702 00703 inline void Domain::BoundingBox(Vec3_t & minX, Vec3_t & maxX) 00704 { 00705 minX = Vec3_t(Particles[0]->X(0) - Particles[0]->R, Particles[0]->X(1) - Particles[0]->R, Particles[0]->X(2) - Particles[0]->R); 00706 maxX = Vec3_t(Particles[0]->X(0) + Particles[0]->R, Particles[0]->X(1) + Particles[0]->R, Particles[0]->X(2) + Particles[0]->R); 00707 for (size_t i=1; i<Particles.Size(); i++) 00708 { 00709 if (minX(0)>(Particles[i]->X(0) - Particles[i]->R)&&Particles[i]->IsFree()) minX(0) = Particles[i]->X(0) - Particles[i]->R; 00710 if (minX(1)>(Particles[i]->X(1) - Particles[i]->R)&&Particles[i]->IsFree()) minX(1) = Particles[i]->X(1) - Particles[i]->R; 00711 if (minX(2)>(Particles[i]->X(2) - Particles[i]->R)&&Particles[i]->IsFree()) minX(2) = Particles[i]->X(2) - Particles[i]->R; 00712 if (maxX(0)<(Particles[i]->X(0) + Particles[i]->R)&&Particles[i]->IsFree()) maxX(0) = Particles[i]->X(0) + Particles[i]->R; 00713 if (maxX(1)<(Particles[i]->X(1) + Particles[i]->R)&&Particles[i]->IsFree()) maxX(1) = Particles[i]->X(1) + Particles[i]->R; 00714 if (maxX(2)<(Particles[i]->X(2) + Particles[i]->R)&&Particles[i]->IsFree()) maxX(2) = Particles[i]->X(2) + Particles[i]->R; 00715 } 00716 } 00717 00718 inline void Domain::AddDisk(int TheTag, Vec3_t const & TheX, Vec3_t const & TheV, Vec3_t const & TheW, double Therho, double TheR, double dt) 00719 { 00720 Particles.Push(new Disk(TheTag,TheX,TheV,TheW,Therho,TheR,dt)); 00721 } 00722 00723 inline void Domain::AddSphere(int TheTag, Vec3_t const & TheX, Vec3_t const & TheV, Vec3_t const & TheW, double Therho, double TheR, double dt) 00724 { 00725 Particles.Push(new Sphere(TheTag,TheX,TheV,TheW,Therho,TheR,dt)); 00726 } 00727 00728 inline void Domain::Solve(double Tf, double dtOut, ptDFun_t ptSetup, ptDFun_t ptReport, 00729 char const * FileKey, bool RenderVideo, size_t Nproc) 00730 { 00731 // info 00732 Util::Stopwatch stopwatch; 00733 printf("\n%s--- Solving ---------------------------------------------------------------------%s\n",TERM_CLR1,TERM_RST); 00734 00735 idx_out = 0; 00736 //Connect particles and lattice 00737 // 00738 00739 //for(size_t i=0;i<Particles.Size();i++) Particles[i]->ImprintDisk(Lat[0]); 00740 ImprintLattice(); 00741 ResetContacts(); 00742 ResetDisplacements(); 00743 00744 // Creates pair of cells to speed up body force calculation 00745 for (size_t i=0;i<Lat[0].Cells.Size();i++) 00746 { 00747 Cell * c = Lat[0].Cells[i]; 00748 for (size_t j=1;j<c->Nneigh;j++) 00749 { 00750 Cell * nb = Lat[0].Cells[c->Neighs[j]]; 00751 if (nb->ID>c->ID) 00752 { 00753 if (!c->IsSolid||!nb->IsSolid) CellPairs.Push(iVec3_t(i,nb->ID,j)); 00754 } 00755 } 00756 } 00757 #ifdef USE_THREAD 00758 MtData MTD[Nproc]; 00759 for (size_t i=0;i<Nproc;i++) 00760 { 00761 MTD[i].N_Proc = Nproc; 00762 MTD[i].ProcRank = i; 00763 MTD[i].Dom = this; 00764 } 00765 pthread_t thrs[Nproc]; 00766 #endif 00767 double tout = Time; 00768 while (Time < Tf) 00769 { 00770 if (ptSetup!=NULL) (*ptSetup) ((*this), UserData); 00771 if (Time >= tout) 00772 { 00773 if (FileKey!=NULL) 00774 { 00775 String fn; 00776 fn.Printf ("%s_%04d", FileKey, idx_out); 00777 if ( RenderVideo) 00778 { 00779 #ifdef USE_HDF5 00780 WriteXDMF(fn.CStr()); 00781 #else 00782 //WriteVTK (fn.CStr()); 00783 #endif 00784 } 00785 if (ptReport!=NULL) (*ptReport) ((*this), UserData); 00786 } 00787 tout += dtOut; 00788 idx_out++; 00789 } 00790 00791 //Assigning a vlaue of zero to the particles forces and torques 00792 for(size_t i=0;i<Particles.Size();i++) 00793 { 00794 Particles[i]->F = Particles[i]->Ff; 00795 Particles[i]->T = Particles[i]->Tf; 00796 } 00797 00798 #ifdef USE_THREAD 00799 for (size_t i=0;i<Nproc;i++) 00800 { 00801 pthread_create(&thrs[i], NULL, GlobalSetZeroGamma, &MTD[i]); 00802 } 00803 for (size_t i=0;i<Nproc;i++) 00804 { 00805 pthread_join(thrs[i], NULL); 00806 } 00807 #else 00808 //Set Gamma values of the lattice cell to zero 00809 for(size_t j=0;j<Lat.Size();j++) 00810 { 00811 Lat[j].SetZeroGamma(); 00812 } 00813 #endif 00814 //Connect particles and lattice 00815 ImprintLattice(); 00816 00817 //Move Particles 00818 for(size_t i=0;i<Interactons.Size();i++) Interactons[i]->CalcForce(dt); 00819 for(size_t i=0;i<Particles.Size() ;i++) Particles[i]->Translate(dt); 00820 00821 //Move fluid 00822 #ifdef USE_THREAD 00823 if (Lat.Size()>1||fabs(Lat[0].G)>1.0e-12) 00824 { 00825 for (size_t i=0;i<Nproc;i++) 00826 { 00827 pthread_create(&thrs[i], NULL, GlobalApplyForce, &MTD[i]); 00828 } 00829 for (size_t i=0;i<Nproc;i++) 00830 { 00831 pthread_join(thrs[i], NULL); 00832 } 00833 } 00834 for (size_t i=0;i<Nproc;i++) 00835 { 00836 pthread_create(&thrs[i], NULL, GlobalCollide, &MTD[i]); 00837 } 00838 for (size_t i=0;i<Nproc;i++) 00839 { 00840 pthread_join(thrs[i], NULL); 00841 } 00842 for (size_t i=0;i<Nproc;i++) 00843 { 00844 pthread_create(&thrs[i], NULL, GlobalBounceBack, &MTD[i]); 00845 } 00846 for (size_t i=0;i<Nproc;i++) 00847 { 00848 pthread_join(thrs[i], NULL); 00849 } 00850 for (size_t i=0;i<Nproc;i++) 00851 { 00852 pthread_create(&thrs[i], NULL, GlobalStream1, &MTD[i]); 00853 } 00854 for (size_t i=0;i<Nproc;i++) 00855 { 00856 pthread_join(thrs[i], NULL); 00857 } 00858 for (size_t i=0;i<Nproc;i++) 00859 { 00860 pthread_create(&thrs[i], NULL, GlobalStream2, &MTD[i]); 00861 } 00862 for (size_t i=0;i<Nproc;i++) 00863 { 00864 pthread_join(thrs[i], NULL); 00865 } 00866 00867 #else 00868 if (Lat.Size()>1||fabs(Lat[0].G)>1.0e-12) ApplyForce(); 00869 Collide(); 00870 for(size_t j=0;j<Lat.Size();j++) 00871 { 00872 Lat[j].BounceBack(); 00873 Lat[j].Stream(); 00874 } 00875 #endif 00876 00877 if (MaxDisplacement()>Alpha) 00878 { 00879 ResetContacts(); 00880 ResetDisplacements(); 00881 } 00882 00883 Time += dt; 00884 } 00885 printf("%s Final CPU time = %s\n",TERM_CLR2, TERM_RST); 00886 } 00887 } 00888 00889 00890 #endif 00891