![]() |
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 #ifndef MECHSYS_LBM_LATTICE_H 00021 #define MECHSYS_LBM_LATTICE_H 00022 00023 // Hdf5 00024 #ifdef USE_HDF5 00025 #include <hdf5.h> 00026 #include <hdf5_hl.h> 00027 #endif 00028 00029 // MechSys 00030 #include <mechsys/lbm/Cell.h> 00031 #include <mechsys/util/util.h> 00032 #include <mechsys/util/stopwatch.h> 00033 00034 class Lattice 00035 { 00036 public: 00037 //typedefs 00038 typedef void (*ptFun_t) (Lattice & Lat, void * UserData); 00039 00040 //Constructors 00041 Lattice () {}; //Default 00042 Lattice (LBMethod Method, double nu, iVec3_t Ndim, double dx, double dt); 00043 00044 //Methods 00045 void Solve(double Tf, double dtOut, ptFun_t ptSetup=NULL, ptFun_t ptReport=NULL, 00046 char const * FileKey=NULL, bool RenderVideo=true, size_t Nproc=1); 00047 void Stream(size_t n = 0, size_t Np = 1); 00048 void Stream1(size_t n = 0, size_t Np = 1); 00049 void Stream2(size_t n = 0, size_t Np = 1); 00050 void SolidDisk(Vec3_t const & X, double R); 00051 void SetZeroGamma(size_t n=0, size_t Np = 1); 00052 double Psi(double); 00053 double SolidFraction(); 00054 void ApplyForce(); 00055 void Collide(); 00056 void CollideAlt(); 00057 void BounceBack(size_t n = 0, size_t Np = 1); 00058 void WriteVTK(char const * FileKey); 00059 #ifdef USE_HDF5 00060 void WriteXDMF(char const * FileKey); 00061 #endif 00062 Cell * GetCell(iVec3_t const & v); 00063 00064 00065 00066 00067 //Data 00068 size_t idx_out; // The discrete time step 00069 double Time; // The current time 00070 double G; // Interaction strength 00071 double Gs; // Interaction strength 00072 double Nu; // Real viscosity 00073 iVec3_t Ndim; // Integer dimension of the domain 00074 double dx; // grid space 00075 double dt; // time step 00076 double Tau; // Relaxation time 00077 double Rhoref; // Values for th intermolecular force 00078 double Psiref; // 00079 Array<Cell *> Cells; // Array of pointer cells 00080 Array<std::pair<Cell *, Cell*> > CellPairs; // Array of pairs of cells for interaction 00081 void * UserData; // User Data 00082 }; 00083 00084 inline Lattice::Lattice(LBMethod TheMethod, double Thenu, iVec3_t TheNdim, double Thedx, double Thedt) 00085 { 00086 Nu = Thenu; 00087 Ndim = TheNdim; 00088 dx = Thedx; 00089 dt = Thedt; 00090 Tau = 3.0*Nu*dt/(dx*dx) + 0.5; 00091 Rhoref = 200.0; 00092 Psiref = 4.0; 00093 G = 0.0; 00094 00095 Cells.Resize(Ndim[0]*Ndim[1]*Ndim[2]); 00096 size_t n = 0; 00097 for (size_t k=0;k<Ndim[2];k++) 00098 for (size_t j=0;j<Ndim[1];j++) 00099 for (size_t i=0;i<Ndim[0];i++) 00100 { 00101 Cells[n] = new Cell(n,TheMethod,iVec3_t(i,j,k),Ndim,dx/dt,Tau); 00102 n++; 00103 } 00104 for (size_t i=0;i<Cells.Size();i++) 00105 { 00106 Cell * c = Cells[i]; 00107 for (size_t j=1;j<c->Nneigh;j++) 00108 { 00109 Cell * nb = Cells[c->Neighs[j]]; 00110 if (nb->ID>c->ID) 00111 { 00112 std::pair<Cell *, Cell*> p; 00113 p = std::make_pair(c,nb); 00114 CellPairs.Push(p); 00115 } 00116 } 00117 } 00118 } 00119 00120 inline void Lattice::Stream(size_t n, size_t Np) 00121 { 00122 size_t Ni = Cells.Size()/Np; 00123 size_t In = n*Ni; 00124 size_t Fn; 00125 n == Np-1 ? Fn = Cells.Size() : Fn = (n+1)*Ni; 00126 // Assign temporal distributions 00127 for (size_t i=In;i<Fn;i++) 00128 for (size_t j=1;j<Cells[i]->Nneigh;j++) 00129 { 00130 Cells[Cells[i]->Neighs[j]]->Ftemp[j] = Cells[i]->F[j]; 00131 } 00132 00133 //Swap the distribution values 00134 for (size_t i=In;i<Fn;i++) 00135 { 00136 for (size_t j=1;j<Cells[i]->Nneigh;j++) 00137 { 00138 Cells[i]->F[j] = Cells[i]->Ftemp[j]; 00139 } 00140 Cells[i]->Rho = Cells[i]->VelDen(Cells[i]->Vel); 00141 } 00142 } 00143 00144 inline void Lattice::Stream1(size_t n, size_t Np) 00145 { 00146 size_t Ni = Cells.Size()/Np; 00147 size_t In = n*Ni; 00148 size_t Fn; 00149 n == Np-1 ? Fn = Cells.Size() : Fn = (n+1)*Ni; 00150 // Assign temporal distributions 00151 for (size_t i=In;i<Fn;i++) 00152 for (size_t j=1;j<Cells[i]->Nneigh;j++) 00153 { 00154 Cells[Cells[i]->Neighs[j]]->Ftemp[j] = Cells[i]->F[j]; 00155 } 00156 } 00157 00158 inline void Lattice::Stream2(size_t n, size_t Np) 00159 { 00160 size_t Ni = Cells.Size()/Np; 00161 size_t In = n*Ni; 00162 size_t Fn; 00163 n == Np-1 ? Fn = Cells.Size() : Fn = (n+1)*Ni; 00164 //Swap the distribution values 00165 for (size_t i=In;i<Fn;i++) 00166 { 00167 for (size_t j=1;j<Cells[i]->Nneigh;j++) 00168 { 00169 Cells[i]->F[j] = Cells[i]->Ftemp[j]; 00170 } 00171 Cells[i]->Rho = Cells[i]->VelDen(Cells[i]->Vel); 00172 } 00173 } 00174 00175 inline void Lattice::SolidDisk(Vec3_t const & X, double R) 00176 { 00177 for (size_t n=std::max(0.0,double(X(0)-R-dx)/dx);n<=std::min(double(Ndim(0)-1),double(X(0)+R+dx)/dx);n++) 00178 for (size_t m=std::max(0.0,double(X(1)-R-dx)/dx);m<=std::min(double(Ndim(1)-1),double(X(1)+R+dx)/dx);m++) 00179 for (size_t l=std::max(0.0,double(X(2)-R-dx)/dx);l<=std::min(double(Ndim(2)-1),double(X(2)+R+dx)/dx);l++) 00180 { 00181 Cell * cell = GetCell(iVec3_t(n,m,l)); 00182 double x = dx*cell->Index(0); 00183 double y = dx*cell->Index(1); 00184 double z = dx*cell->Index(2); 00185 Vec3_t C(x,y,z); 00186 if (norm(C-X)<R) cell->IsSolid = true; 00187 } 00188 } 00189 00190 inline void Lattice::SetZeroGamma(size_t n, size_t Np) 00191 { 00192 size_t Ni = Cells.Size()/Np; 00193 size_t In = n*Ni; 00194 size_t Fn; 00195 n == Np-1 ? Fn = Cells.Size() : Fn = (n+1)*Ni; 00196 for (size_t i=In;i<Fn;i++) 00197 { 00198 Cells[i]->Gamma = 0.0; 00199 Cells[i]->BForce = Cells[i]->BForcef; 00200 } 00201 } 00202 00203 inline double Lattice::Psi(double rho) 00204 { 00205 return Psiref*exp(-Rhoref/rho); 00206 //double a = 0.0015; 00207 //double b = 1.0/3000; 00208 //double RT= 1.0/3.0; 00209 //double p=RT*(rho/(1-b*rho))-a*rho*rho/(1+rho*b); 00210 //if (RT*rho-p>0.0) return sqrt( 2.0*(p - RT*rho)/(RT*G)); 00211 //else return -sqrt(-2.0*(p - RT*rho)/(RT*G)); 00212 } 00213 00214 inline double Lattice::SolidFraction() 00215 { 00216 double Sf = 0.0; 00217 for (size_t i=0; i<Cells.Size(); i++) 00218 { 00219 if (Cells[i]->IsSolid||Cells[i]->Gamma>0.0) Sf+=1.0; 00220 } 00221 return Sf/Cells.Size(); 00222 } 00223 00224 inline void Lattice::ApplyForce() 00225 { 00226 //for (size_t i=0;i<CellPairs.Size();i++) 00227 //{ 00228 //Cell * c = CellPairs[i].first; 00229 //Cell * nb = CellPairs[i].second; 00230 //if (fabs(c->Gamma-1.0)+fabs(nb->Gamma-1.0)<1.0e-12) continue; 00231 //double psi = Psi(c->Rho/); 00232 //double nb_psi = Psi(nb->Rho/); 00233 //double C = G; 00234 //if (nb->IsSolid) 00235 //{ 00236 //C = Gs; 00237 //nb_psi = 1.0; 00238 //} 00239 //if (c->IsSolid) 00240 //{ 00241 // 00242 //} 00243 //} 00244 00245 for (size_t i=0;i<Cells.Size();i++) 00246 { 00247 Cell * c = Cells[i]; 00248 double psi = Psi(c->Rho); 00249 if (fabs(c->Gamma-1.0)<1.0e-12) continue; 00250 for (size_t j=1;j<c->Nneigh;j++) 00251 { 00252 Cell * nb = Cells[c->Neighs[j]]; 00253 double nb_psi = Psi(nb->Rho); 00254 double C = G; 00255 if (nb->Gamma>0.0||nb->IsSolid) 00256 { 00257 nb_psi = 1.0; 00258 C = Gs; 00259 } 00260 c->BForce += -C*psi*c->W[j]*nb_psi*c->C[j]; 00261 } 00262 } 00263 } 00264 00265 inline void Lattice::Collide() 00266 { 00267 double ome = 1.0/Tau; 00268 for (size_t i=0;i<Cells.Size() ;i++) 00269 { 00270 Cell * c = Cells[i]; 00271 if (c->IsSolid) continue; 00272 //if (fabs(c->Gamma-1.0)<1.0e-12) continue; 00273 Vec3_t V; 00274 double rho = c->VelDen(V); 00275 double Bn = (c->Gamma*(Tau-0.5))/((1.0-c->Gamma)+(Tau-0.5)); 00276 for (size_t j=0;j<c->Nneigh;j++) 00277 { 00278 double Feqn = c->Feq(j, V,rho); 00279 //double Fvp = c->Feq(j,c->VelP,rho); 00280 c->F[j] = c->F[j] - (1 - Bn)*ome*(c->F[j] - Feqn) + Bn*c->Omeis[j]; 00281 } 00282 } 00283 } 00284 00285 inline void Lattice::CollideAlt() 00286 { 00287 double ome = 1.0/Tau; 00288 for (size_t i=0;i<Cells.Size() ;i++) 00289 { 00290 Cell * c = Cells[i]; 00291 if (c->IsSolid) continue; 00292 if (fabs(c->Gamma-1.0)<1.0e-12&&fabs(G)>1.0e-12) continue; 00293 Vec3_t V; 00294 double rho = c->VelDen(V); 00295 Vec3_t DV = V + c->BForce*Tau/rho; 00296 //Vec3_t DV = V + c->BForce*dt/rho; 00297 double Bn = (c->Gamma*(Tau-0.5))/((1.0-c->Gamma)+(Tau-0.5)); 00298 bool valid = true; 00299 //double omel = ome; 00300 //double omet = ome; 00301 double alphal = 1.0; 00302 double alphat = 1.0; 00303 size_t num = 0; 00304 while (valid) 00305 { 00306 valid = false; 00307 alphal = alphat; 00308 for (size_t j=0;j<c->Nneigh;j++) 00309 { 00310 //double Feqn = c->Feq(j, V,rho); 00311 double FDeqn = c->Feq(j, DV,rho); 00312 //double Fvp = c->Feq(j, c->VelP,rho); 00313 00314 //First method owen 00315 //c->F[j] = c->F[j] - (1 - Bn)*ome*(c->F[j] - Feqn) + Bn*c->Omeis[j] + dt*dt*(1 - Bn)*c->W[j]*dot(c->BForce,c->C[j])/(K*dx); 00316 00317 //Second method LBM EOS 00318 //c->Ftemp[j] = c->F[j] - alphal*((1 - Bn)*(ome*(c->F[j] - Feqn) - FDeqn + Feqn) - Bn*c->Omeis[j]); 00319 00320 //Third method sukop 00321 //c->Ftemp[j] = c->F[j] - (1 - Bn)*omel*(c->F[j] - FDeqn) + Bn*c->Omeis[j]; 00322 c->Ftemp[j] = c->F[j] - alphal*((1 - Bn)*ome*(c->F[j] - FDeqn) - Bn*c->Omeis[j]); 00323 00324 if (c->Ftemp[j]<0.0&&num<1) 00325 { 00326 double temp = fabs(c->F[j]/((1 - Bn)*ome*(c->F[j] - FDeqn) - Bn*c->Omeis[j])); 00327 if (temp<alphat) alphat = temp; 00328 valid = true; 00329 //std::cout << i << " " << c->F[j] << " " << FDeqn << " " << c->Omeis[j] << " " << Bn << " " << alphat << " " << temp << std::endl; 00330 } 00331 } 00332 num++; 00333 if (num>2) 00334 { 00335 throw new Fatal("Lattice::Collide: Redefine your time step, the current value ensures unstability"); 00336 } 00337 } 00338 for (size_t j=0;j<c->Nneigh;j++) 00339 { 00340 c->F[j] = fabs(c->Ftemp[j]); 00341 } 00342 } 00343 } 00344 00345 inline void Lattice::BounceBack(size_t n, size_t Np) 00346 { 00347 size_t Ni = Cells.Size()/Np; 00348 size_t In = n*Ni; 00349 size_t Fn; 00350 n == Np-1 ? Fn = Cells.Size() : Fn = (n+1)*Ni; 00351 for (size_t i=In;i<Fn;i++) 00352 { 00353 if (!Cells[i]->IsSolid) continue; 00354 for (size_t j = 0;j<Cells[i]->Nneigh;j++) Cells[i]->Ftemp[j] = Cells[i]->F[j]; 00355 for (size_t j = 0;j<Cells[i]->Nneigh;j++) Cells[i]->F[j] = Cells[i]->Ftemp[Cells[i]->Op[j]]; 00356 } 00357 } 00358 00359 #ifdef USE_HDF5 00360 inline void Lattice::WriteXDMF(char const * FileKey) 00361 { 00362 String fn(FileKey); 00363 fn.append(".h5"); 00364 hid_t file_id; 00365 file_id = H5Fcreate(fn.CStr(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); 00366 00367 // Creating data sets 00368 float *Density = new float[Ndim[0]*Ndim[1]*Ndim[2]]; 00369 float *Gamma = new float[Ndim[0]*Ndim[1]*Ndim[2]]; 00370 float *Velocity = new float[Ndim[0]*Ndim[1]*Ndim[2]]; 00371 float *MassFlux = new float[Ndim[0]*Ndim[1]*Ndim[2]]; 00372 00373 00374 for (size_t i=0;i<Cells.Size();i++) 00375 { 00376 double rho; 00377 Vec3_t vel; 00378 rho = Cells[i]->VelDen(vel); 00379 Density [i] = (float) rho; 00380 Gamma [i] = (float) Cells[i]->IsSolid? 1.0:Cells[i]->Gamma; 00381 Velocity [i] = (float) norm(vel); 00382 MassFlux [i] = (float) rho*norm(vel); 00383 } 00384 00385 //Write the data 00386 hsize_t dims[1]; 00387 dims[0] = Ndim(0)*Ndim(1)*Ndim(2); 00388 H5LTmake_dataset_float(file_id,"Density" ,1,dims,Density ); 00389 H5LTmake_dataset_float(file_id,"Gamma" ,1,dims,Gamma ); 00390 H5LTmake_dataset_float(file_id,"Velocity",1,dims,Velocity); 00391 H5LTmake_dataset_float(file_id,"MassFlux",1,dims,MassFlux); 00392 00393 delete [] Density ; 00394 delete [] Gamma ; 00395 delete [] Velocity; 00396 delete [] MassFlux; 00397 00398 //Closing the file 00399 H5Fclose(file_id); 00400 00401 // Writing xmf file 00402 std::ostringstream oss; 00403 oss << "<?xml version=\"1.0\" ?>\n"; 00404 oss << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n"; 00405 oss << "<Xdmf Version=\"2.0\">\n"; 00406 oss << " <Domain>\n"; 00407 oss << " <Grid Name=\"mesh1\" GridType=\"Uniform\">\n"; 00408 oss << " <Topology TopologyType=\"2DCoRectMesh\" Dimensions=\"" << Ndim(1) << " " << Ndim(0) << "\"/>\n"; 00409 oss << " <Geometry GeometryType=\"ORIGIN_DXDY\">\n"; 00410 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"2\"> 0.0 0.0\n"; 00411 oss << " </DataItem>\n"; 00412 oss << " <DataItem Format=\"XML\" NumberType=\"Float\" Dimensions=\"2\"> 1.0 1.0\n"; 00413 oss << " </DataItem>\n"; 00414 oss << " </Geometry>\n"; 00415 oss << " <Attribute Name=\"Density\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00416 oss << " <DataItem Dimensions=\"" << Ndim(0) << " " << Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00417 oss << " " << fn.CStr() <<":/Density\n"; 00418 oss << " </DataItem>\n"; 00419 oss << " </Attribute>\n"; 00420 oss << " <Attribute Name=\"Gamma\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00421 oss << " <DataItem Dimensions=\"" << Ndim(0) << " " << Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00422 oss << " " << fn.CStr() <<":/Gamma\n"; 00423 oss << " </DataItem>\n"; 00424 oss << " </Attribute>\n"; 00425 oss << " <Attribute Name=\"Velocity\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00426 oss << " <DataItem Dimensions=\"" << Ndim(0) << " " << Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00427 oss << " " << fn.CStr() <<":/Velocity\n"; 00428 oss << " </DataItem>\n"; 00429 oss << " </Attribute>\n"; 00430 oss << " <Attribute Name=\"MassFlux\" AttributeType=\"Scalar\" Center=\"Node\">\n"; 00431 oss << " <DataItem Dimensions=\"" << Ndim(0) << " " << Ndim(1) << "\" NumberType=\"Float\" Precision=\"4\" Format=\"HDF\">\n"; 00432 oss << " " << fn.CStr() <<":/MassFlux\n"; 00433 oss << " </DataItem>\n"; 00434 oss << " </Attribute>\n"; 00435 oss << " </Grid>\n"; 00436 oss << " </Domain>\n"; 00437 oss << "</Xdmf>\n"; 00438 00439 fn = FileKey; 00440 fn.append(".xmf"); 00441 std::ofstream of(fn.CStr(), std::ios::out); 00442 of << oss.str(); 00443 of.close(); 00444 } 00445 #endif 00446 00447 inline void Lattice::WriteVTK(char const * FileKey) 00448 { 00449 // Header 00450 std::ostringstream oss; 00451 oss << "# vtk DataFile Version 2.0\n"; 00452 oss << "TimeStep = " << idx_out << "\n"; 00453 oss << "ASCII\n"; 00454 oss << "DATASET STRUCTURED_POINTS\n"; 00455 oss << "DIMENSIONS " << Ndim[0] << " " << Ndim[1] << " " << Ndim[2] << "\n"; 00456 oss << "ORIGIN " << 0 << " " << 0 << " " << 0 << "\n"; 00457 oss << "SPACING " << 1 << " " << 1 << " " << 1 << "\n"; 00458 oss << "POINT_DATA " << Cells.Size() << "\n"; 00459 00460 // Solid cells 00461 oss << "SCALARS Geom float 1\n"; 00462 oss << "LOOKUP_TABLE default\n"; 00463 for (size_t i=0; i<Cells.Size(); ++i) 00464 { 00465 if (Cells[i]->IsSolid) oss << "1.0\n"; 00466 else oss << "0.0\n"; 00467 } 00468 00469 // Density field 00470 oss << "SCALARS Density float 1\n"; 00471 oss << "LOOKUP_TABLE default\n"; 00472 for (size_t i=0; i<Cells.Size(); i++) 00473 oss << Cells[i]->Rho << "\n"; 00474 00475 // Density field 00476 oss << "SCALARS Gamma float 1\n"; 00477 oss << "LOOKUP_TABLE default\n"; 00478 for (size_t i=0; i<Cells.Size(); i++) 00479 oss << Cells[i]->Gamma << "\n"; 00480 00481 oss << "VECTORS Velocity float\n"; 00482 for (size_t i=0; i<Cells.Size(); ++i) 00483 { 00484 Vec3_t v; Cells[i]->Velocity(v); 00485 oss << v(0) << " " << v(1) << " " << v(2) << "\n"; 00486 } 00487 oss << "VECTORS Mass_flux float\n"; 00488 for (size_t i=0; i<Cells.Size(); ++i) 00489 { 00490 Vec3_t v; Cells[i]->Velocity(v); 00491 v *= Cells[i]->Rho; 00492 oss << v(0) << " " << v(1) << " " << v(2) << "\n"; 00493 } 00494 00495 String fn(FileKey); 00496 fn.append(".vtk"); 00497 std::ofstream of(fn.CStr(), std::ios::out); 00498 of << oss.str(); 00499 of.close(); 00500 } 00501 00502 inline Cell * Lattice::GetCell(iVec3_t const & v) 00503 { 00504 return Cells[v[0] + v[1]*Ndim[0] + v[2]*Ndim[0]*Ndim[1]]; 00505 } 00506 00507 inline void Lattice::Solve(double Tf, double dtOut, ptFun_t ptSetup, ptFun_t ptReport, 00508 char const * FileKey, bool RenderVideo, size_t Nproc) 00509 { 00510 // info 00511 Util::Stopwatch stopwatch; 00512 printf("\n%s--- Solving ---------------------------------------------------------------------%s\n",TERM_CLR1,TERM_RST); 00513 00514 idx_out = 0; 00515 if (ptReport!=NULL) (*ptReport) ((*this), UserData); 00516 00517 double tout = Time; 00518 while (Time < Tf) 00519 { 00520 if (ptSetup!=NULL) (*ptSetup) ((*this), UserData); 00521 Collide(); 00522 BounceBack(); 00523 Stream(); 00524 00525 if (Time >= tout) 00526 { 00527 if (FileKey!=NULL) 00528 { 00529 String fn; 00530 fn.Printf ("%s_%08d", FileKey, idx_out); 00531 WriteVTK (fn.CStr()); 00532 if (ptReport!=NULL) (*ptReport) ((*this), UserData); 00533 } 00534 tout += dtOut; 00535 idx_out++; 00536 } 00537 00538 Time += dt; 00539 } 00540 printf("%s Final CPU time = %s\n",TERM_CLR2, TERM_RST); 00541 } 00542 #endif