MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/lbm/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 
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines