![]() |
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_MESH_STRUCTURED_H 00021 #define MECHSYS_MESH_STRUCTURED_H 00022 00023 /* LOCAL indexes of VERTICES, EDGES, and FACES 00024 00025 2D: 00026 Vertices Edges 00027 y 00028 | 3 6 2 2 00029 +--x @-----@-----@ +-----------+ 00030 | | | | 00031 | | | | 00032 7 @ @ 5 3| |1 00033 | | | | 00034 | | | | 00035 @-----@-----@ +-----------+ 00036 0 4 1 0 00037 00038 3D: 00039 Vertices Faces 00040 z 00041 | 4 15 7 00042 ,+--y @-------@--------@ +----------------+ 00043 x' ,'| ,'| ,'| ,'| 00044 12 @' | 14 ,' | ,' | ___ ,' | 00045 ,' |16 ,@ |19 ,' |,'5,' [0],' | 00046 5 ,' @ 6 ,' @ ,' |~~~ ,' | 00047 @'=======@=======@' | +'===============+' ,'| | 00048 | 13 | | | | ,'| | | |3| | 00049 | | | 11 | | |2| | | |,' | 00050 17 | 0 @- - - | @- - - -@ | |,' +- - - | +- - - -+ 00051 @ ,' @ ,' 3 | ,' | ,' 00052 | 8 @' 18 | ,' | ,' [1] ___| ,' 00053 | ,' | ,@ 10 | ,' ,'4,'| ,' 00054 | ,' | ,' | ,' ~~~ | ,' 00055 @-------@--------@' +----------------+' 00056 1 9 2 00057 */ 00058 00059 // Std Lib 00060 #include <iostream> 00061 #include <fstream> 00062 #include <sstream> 00063 #include <cfloat> // for DBL_EPSILON 00064 #include <cstdarg> // for va_list, va_start, va_end 00065 #include <map> // for std::map 00066 00067 // MechSys 00068 #include <mechsys/mesh/mesh.h> 00069 #include <mechsys/linalg/matvec.h> 00070 #include <mechsys/util/array.h> 00071 #include <mechsys/util/fatal.h> 00072 #include <mechsys/util/util.h> 00073 #include <mechsys/util/stopwatch.h> 00074 #include <mechsys/util/maps.h> 00075 00076 namespace Mesh 00077 { 00078 00079 /* TODO: 00080 * 1) Add additional checks, especially for 3D meshes 00081 * 2) Check second-order (o2) elements 00082 * 3) Add quality check and improvement 00083 * 4) Create list of neighbours blocks/edges 00084 */ 00085 00086 00088 00089 00090 typedef std::map<int,SDPair> Side2Ctr_t; 00091 00092 class Block 00093 { 00094 public: 00095 // Constructor 00096 Block () : Nx(1), Ny(1), Nz(1) {} 00097 00107 void Set (int NDim, int Tag, size_t NVerts, ...); 00108 00109 // Methods 00110 void SetNx (size_t Nx, double Ax=0.0, bool NonLin=false); 00111 void SetNy (size_t Ny, double Ay=0.0, bool NonLin=false); 00112 void SetNz (size_t Nz, double Az=0.0, bool NonLin=false); 00113 void SetNx (Array<double> const & TheWx); 00114 double Diagonal () const; 00115 void GenMidNodes (); 00116 bool BryIDs (size_t i, size_t j, size_t k, Array<int> & BryIDs) const; 00117 int GetVTag (size_t i, size_t j, size_t k) const; 00118 void AddArcCtr (int Side, double x, double y, double R, double Tol=1.0e-8); 00119 void AddCylXCtr (int Side, double y, double z, double R, double Tol=1.0e-8); 00120 void ApplyCtr (Array<int> const & Sides, Vertex & V) const; 00121 00122 // Data 00123 int NDim; 00124 int Tag; 00125 Mat_t C; 00126 Array<int> VTags; 00127 Array<int> BryTags; 00128 size_t Nx,Ny,Nz; 00129 Array<double> Wx,Wy,Wz; 00130 double SumWx,SumWy,SumWz; 00131 Array<bool> SideHasCtr; 00132 Side2Ctr_t Side2Ctr; 00133 00134 /* 2D: _ _ 00135 * C = | x0 x1 x2 x3 | 00136 * |_ y0 y1 y2 y3 _| 00137 * or 00138 * _ _ 00139 * C = | x0 x1 x2 x3 x4 x5 x6 x7 | 00140 * |_ y0 y1 y2 y3 y4 y5 y6 y7 _| 00141 * 00142 * 3D: _ _ 00143 * | x0 x1 x2 x3 x4 x5 x6 x7 | 00144 * C = | y0 y1 y2 y3 y4 y5 y6 y7 | 00145 * |_ z0 z1 z2 z3 z4 z5 z6 z7 _| 00146 * 00147 * or _ _ 00148 * | x0 x1 x2 x3 x4 x5 x6 x7 ... x17 x18 x19 | 00149 * C = | y0 y1 y2 y3 y4 y5 y6 y7 ... y17 y18 y19 | 00150 * |_ z0 z1 z2 z3 z4 z5 z6 z7 ... z17 z18 z19 _| 00151 */ 00152 00153 #ifdef USE_BOOST_PYTHON 00154 void PySet (BPy::dict const & Dat); 00155 #endif 00156 00157 private: 00158 void _initialize (size_t NVerts); 00159 }; 00160 00161 00163 00164 00165 class Structured : public virtual Mesh::Generic 00166 { 00167 public: 00168 // Structures 00169 struct VertexInfo 00170 { 00171 bool OnBry; 00172 int BlkNum; 00173 bool Dupl; 00174 Array<int> BlkBryIDs; 00175 }; 00176 00177 // Constructor 00178 Structured (int NDim) : Mesh::Generic(NDim) {} 00179 00180 // Destructor 00181 ~Structured () { Erase(); } 00182 00183 // Methods 00184 void Generate (Array<Block> const & Blks, bool O2=false); 00185 void GenBox (bool O2=true, int Nx=2, int Ny=2, int Nz=2, double Lx=1.0, double Ly=1.0, double Lz=1.0); 00186 void GenQRing (bool O2=true, int Nx=2, int Ny=2, double r=1.0, double R=2.0, 00187 size_t Nb=2, double Ax=1.0, bool NonLin=false, char const * WeightsX=NULL); 00188 void GenQRing (bool O2, int Nx, int Ny, int Nz, double r, double R, double t); 00189 void GenQDisk (bool O2, int Nx1, int Nx2, int Ny, double r, double R); 00190 void GenQPlateHole (double r, double R, double L, int Nx1, int Nx2, int Ny1, int Ny2, bool O2); 00191 void ShapeFunc (double r, double s, double t); 00192 00193 // Data 00194 Vec_t N; 00195 00196 #ifdef USE_BOOST_PYTHON 00197 void PyGenerate (BPy::list const & Blks, bool O2=false); 00198 #endif 00199 }; 00200 00201 00203 00204 00205 inline void Block::Set (int TheNDim, int TheTag, size_t NVerts, ...) 00206 { 00207 // allocate data 00208 NDim = TheNDim; 00209 Tag = TheTag; 00210 _initialize (NVerts); 00211 00212 // read data 00213 va_list arg_list; 00214 va_start (arg_list, NVerts); 00215 for (size_t i=0; i<NVerts; ++i) 00216 { 00217 VTags[i] = static_cast<int>(va_arg(arg_list,double)); 00218 C(0,i) = va_arg(arg_list,double); 00219 C(1,i) = va_arg(arg_list,double); if (NDim==3) 00220 C(2,i) = va_arg(arg_list,double); 00221 } 00222 for (size_t i=0; i<BryTags.Size(); ++i) BryTags[i] = static_cast<int>(va_arg(arg_list,double)); 00223 va_end (arg_list); 00224 00225 // check connectivity (2D) 00226 if (NDim==2) 00227 { 00228 Vec3_t p0, p1, p2; 00229 for (size_t i=1; i<NVerts-1; ++i) 00230 { 00231 p0 = C(0,i-1)-C(0,i), C(1,i-1)-C(1,i), 0.0; 00232 p1 = C(0,i+1)-C(0,i), C(1,i+1)-C(1,i), 0.0; 00233 p2 = blitz::cross (p1,p0); 00234 if (p2(2)<0.0) throw new Fatal("Mesh::Block::Set: Order of vertices is incorrect (it must be counter-clockwise)"); 00235 } 00236 } 00237 00238 // generate mid nodes 00239 if (NDim==2 && NVerts==4) GenMidNodes(); 00240 if (NDim==3 && NVerts==8) GenMidNodes(); 00241 00242 // constraints 00243 if (NDim==2) 00244 { 00245 SideHasCtr.Resize (4); 00246 SideHasCtr.SetValues (false); 00247 } 00248 else 00249 { 00250 SideHasCtr.Resize (6); 00251 SideHasCtr.SetValues (false); 00252 } 00253 } 00254 00255 inline void Block::SetNx (size_t TheNx, double Ax, bool NonLin) 00256 { 00257 if (TheNx<1) throw new Fatal("Block::SetNx: Number of divisions of block for structured mesh must be greater than or equal to 1. Nx=%zd is invalid",TheNx); 00258 Nx = TheNx; 00259 Wx.Resize(Nx); 00260 if (NonLin) for (size_t i=0; i<Nx; ++i) Wx[i] = pow(i+1.0,Ax); 00261 else for (size_t i=0; i<Nx; ++i) Wx[i] = 1.0+Ax*i; 00262 00263 SumWx = 0.0; 00264 for (size_t i=0; i<Nx; ++i) SumWx += Wx[i]; 00265 Wx.Push(0.0); // extra value just to help loop over weights 00266 } 00267 00268 inline void Block::SetNx (Array<double> const & TheWx) 00269 { 00270 Nx = TheWx.Size(); 00271 Wx = TheWx; 00272 00273 SumWx = 0.0; 00274 for (size_t i=0; i<Nx; ++i) SumWx += Wx[i]; 00275 Wx.Push(0.0); // extra value just to help loop over weights 00276 } 00277 00278 inline void Block::SetNy (size_t TheNy, double Ay, bool NonLin) 00279 { 00280 if (TheNy<1) throw new Fatal("Block::SetNy: Number of divisions of block for structured mesh must be greater than or equal to 1. Ny=%zd is invalid",TheNy); 00281 Ny = TheNy; 00282 Wy.Resize(Ny); 00283 if (NonLin) for (size_t i=0; i<Ny; ++i) Wy[i] = pow(i+1.0,Ay); 00284 else for (size_t i=0; i<Ny; ++i) Wy[i] = 1.0+Ay*i; 00285 00286 SumWy = 0.0; 00287 for (size_t i=0; i<Ny; ++i) SumWy += Wy[i]; 00288 Wy.Push(0.0); // extra value just to help loop over weights 00289 } 00290 00291 inline void Block::SetNz (size_t TheNz, double Az, bool NonLin) 00292 { 00293 if (TheNz<1) throw new Fatal("Block::SetNz: Number of divisions of block for structured mesh must be greater than or equal to 1. Nz=%zd is invalid",TheNz); 00294 Nz = TheNz; 00295 Wz.Resize(Nz); 00296 if (NonLin) for (size_t i=0; i<Nz; ++i) Wz[i] = pow(i+1.0,Az); 00297 else for (size_t i=0; i<Nz; ++i) Wz[i] = 1.0+Az*i; 00298 00299 SumWz = 0.0; 00300 for (size_t i=0; i<Nz; ++i) SumWz += Wz[i]; 00301 Wz.Push(0.0); // extra value just to help loop over weights 00302 } 00303 00304 inline double Block::Diagonal () const 00305 { 00306 if (NDim==3) return sqrt(pow(C(0,6)-C(0,0),2.0)+pow(C(1,6)-C(1,0),2.0)+pow(C(2,6)-C(2,0),2.0)); 00307 else return sqrt(pow(C(0,2)-C(0,0),2.0)+pow(C(1,2)-C(1,0),2.0)); 00308 } 00309 00310 inline void Block::GenMidNodes () 00311 { 00312 if (NDim==3) 00313 { 00314 for (size_t i=0; i<3; ++i) 00315 { 00316 C(i, 8) = (C(i,0) + C(i,1))/2.0; 00317 C(i, 9) = (C(i,1) + C(i,2))/2.0; 00318 C(i,10) = (C(i,2) + C(i,3))/2.0; 00319 C(i,11) = (C(i,3) + C(i,0))/2.0; 00320 00321 C(i,12) = (C(i,4) + C(i,5))/2.0; 00322 C(i,13) = (C(i,5) + C(i,6))/2.0; 00323 C(i,14) = (C(i,6) + C(i,7))/2.0; 00324 C(i,15) = (C(i,7) + C(i,4))/2.0; 00325 00326 C(i,16) = (C(i,0) + C(i,4))/2.0; 00327 C(i,17) = (C(i,1) + C(i,5))/2.0; 00328 C(i,18) = (C(i,2) + C(i,6))/2.0; 00329 C(i,19) = (C(i,3) + C(i,7))/2.0; 00330 } 00331 } 00332 else 00333 { 00334 for (size_t i=0; i<2; ++i) 00335 { 00336 C(i,4) = (C(i,0) + C(i,1))/2.0; 00337 C(i,5) = (C(i,1) + C(i,2))/2.0; 00338 C(i,6) = (C(i,2) + C(i,3))/2.0; 00339 C(i,7) = (C(i,3) + C(i,0))/2.0; 00340 } 00341 } 00342 } 00343 00344 inline bool Block::BryIDs (size_t i, size_t j, size_t k, Array<int> & BryIDs) const 00345 { 00346 bool onbry = false; 00347 if (NDim==2) 00348 { 00349 if (j==0 ) { if (BryIDs.Find(0)<0) BryIDs.Push(0); onbry = true; } // bottom 00350 if (i==Nx) { if (BryIDs.Find(1)<0) BryIDs.Push(1); onbry = true; } // right 00351 if (j==Ny) { if (BryIDs.Find(2)<0) BryIDs.Push(2); onbry = true; } // top 00352 if (i==0 ) { if (BryIDs.Find(3)<0) BryIDs.Push(3); onbry = true; } // left 00353 } 00354 else 00355 { 00356 if (i==0 ) { if (BryIDs.Find(0)<0) BryIDs.Push(0); onbry = true; } // behind 00357 if (i==Nx) { if (BryIDs.Find(1)<0) BryIDs.Push(1); onbry = true; } // front 00358 if (j==0 ) { if (BryIDs.Find(2)<0) BryIDs.Push(2); onbry = true; } // left 00359 if (j==Ny) { if (BryIDs.Find(3)<0) BryIDs.Push(3); onbry = true; } // right 00360 if (k==0 ) { if (BryIDs.Find(4)<0) BryIDs.Push(4); onbry = true; } // bottom 00361 if (k==Nz) { if (BryIDs.Find(5)<0) BryIDs.Push(5); onbry = true; } // top 00362 } 00363 return onbry; 00364 } 00365 00366 inline int Block::GetVTag (size_t i, size_t j, size_t k) const 00367 { 00368 if (NDim==2) 00369 { 00370 if (i==0 && j==0 ) return VTags[0]; 00371 if (i==Nx && j==0 ) return VTags[1]; 00372 if (i==Nx && j==Ny) return VTags[2]; 00373 if (i==0 && j==Ny) return VTags[3]; 00374 } 00375 else 00376 { 00377 if (i==0 && j==0 && k==0 ) return VTags[0]; 00378 if (i==Nx && j==0 && k==0 ) return VTags[1]; 00379 if (i==Nx && j==Ny && k==0 ) return VTags[2]; 00380 if (i==0 && j==Ny && k==0 ) return VTags[3]; 00381 if (i==0 && j==0 && k==Nz) return VTags[4]; 00382 if (i==Nx && j==0 && k==Nz) return VTags[5]; 00383 if (i==Nx && j==Ny && k==Nz) return VTags[6]; 00384 if (i==0 && j==Ny && k==Nz) return VTags[7]; 00385 } 00386 return 0; 00387 } 00388 00389 inline void Block::AddArcCtr (int Side, double xc, double yc, double R, double Tol) 00390 { 00391 SDPair data; 00392 data.Set ("type",1.0); // 1.0 = Arc 00393 data.Set ("xc", xc); 00394 data.Set ("yc", yc); 00395 data.Set ("R", R); 00396 data.Set ("Tol",Tol); 00397 Side2Ctr[Side] = data; 00398 SideHasCtr[Side] = true; 00399 } 00400 00401 inline void Block::AddCylXCtr (int Side, double yc, double zc, double R, double Tol) 00402 { 00403 SDPair data; 00404 data.Set ("type",2.0); // 2.0 = Cylinder parallel to x 00405 data.Set ("xc", yc); 00406 data.Set ("yc", zc); 00407 data.Set ("R", R); 00408 data.Set ("Tol",Tol); 00409 Side2Ctr[Side] = data; 00410 SideHasCtr[Side] = true; 00411 } 00412 00413 inline void Block::ApplyCtr (Array<int> const & Sides, Vertex & V) const 00414 { 00415 for (size_t m=0; m<Sides.Size(); ++m) 00416 { 00417 int side = Sides[m]; 00418 if (SideHasCtr[side]) 00419 { 00420 Side2Ctr_t::const_iterator it = Side2Ctr.find(side); 00421 double *X, *Y; 00422 if (static_cast<int>(it->second("type"))==1) // arc 00423 { 00424 X = &V.C(0); 00425 Y = &V.C(1); 00426 } 00427 else if (static_cast<int>(it->second("type"))==2) // cylinder parallel to x 00428 { 00429 X = &V.C(1); 00430 Y = &V.C(2); 00431 } 00432 else throw new Fatal("Mesh::Block: __internal_error__: Unknown constraint type (%d)",it->second("type")); 00433 double x = (*X); 00434 double y = (*Y); 00435 double xc = it->second("xc"); 00436 double yc = it->second("yc"); 00437 double R = it->second("R"); 00438 double tol = it->second("Tol"); 00439 double F = pow(x-xc,2.0) + pow(y-yc,2.0) - R*R; 00440 if (fabs(F)>tol) 00441 { 00442 //std::cout << "F_{before} = " << F; 00443 double nx = 2.0*(x-xc); 00444 double ny = 2.0*(y-yc); 00445 double A = nx*nx + ny*ny; 00446 double B = 2.0*nx*(x-xc) + 2.0*ny*(y-yc); 00447 double D = B*B - 4.0*A*F; 00448 if (D<0.0) throw new Fatal("Mesh::Block::ApplyCtr: Constraint failed with D=%g",D); 00449 double a = (F<0.0 ? (-B+sqrt(D))/(2.0*A) : (-B-sqrt(D))/(2.0*A)); 00450 (*X) = x + a*nx; 00451 (*Y) = y + a*ny; 00452 F = pow((*X)-xc,2.0) + pow((*Y)-yc,2.0) - R*R; 00453 //std::cout << " F_{after} = " << F << std::endl; 00454 } 00455 } 00456 } 00457 } 00458 00459 inline void Block::_initialize (size_t NVerts) 00460 { 00461 if (NDim==2) 00462 { 00463 if (NVerts==4 || NVerts==8) 00464 { 00465 C.change_dim (NDim,8); 00466 VTags.Resize (8); // 8 vertices 00467 BryTags.Resize (4); // 4 edges 00468 VTags.SetValues (0); 00469 BryTags.SetValues (0); 00470 } 00471 else throw new Fatal("Block::_initialize: With NDim=2 Number of vertices must be either 4 or 8 (%d is invalid)",NVerts); 00472 } 00473 else if (NDim==3) 00474 { 00475 if (NVerts==8 || NVerts==20) 00476 { 00477 C.change_dim (NDim,20); 00478 VTags.Resize (20); // 20 vertices 00479 BryTags.Resize (6); // 6 faces 00480 VTags.SetValues (0); 00481 BryTags.SetValues (0); 00482 } 00483 else throw new Fatal("Block::_initialize: With NDim=3 Number of vertices must be either 8 or 20 (%d is invalid)",NVerts); 00484 } 00485 else throw new Fatal("Block::_initialize: NDim=%d is invalid",NDim); 00486 SetNx (Nx); 00487 SetNy (Ny); 00488 SetNz (Nz); 00489 } 00490 00491 std::ostream & operator<< (std::ostream & os, Block const & B) 00492 { 00493 os << "B={'ndim':" << B.NDim << ", 'tag':" << B.Tag; 00494 os << ", 'nx':" << B.Nx; 00495 os << ", 'ny':" << B.Ny; if (B.NDim==3) 00496 os << ", 'nz':" << B.Nz; 00497 os << ", 'brytags':["; 00498 for (size_t i=0; i<B.BryTags.Size(); ++i) 00499 { 00500 os << B.BryTags[i]; 00501 if (i!=B.BryTags.Size()-1) os << ","; 00502 } 00503 os << "],\n 'V':["; 00504 for (size_t i=0; i<B.C.num_cols(); ++i) 00505 { 00506 os << "[" << Util::_4 << B.VTags[i]; 00507 os << "," << Util::_8s << B.C(0,i); 00508 os << "," << Util::_8s << B.C(1,i); if (B.NDim==3) 00509 os << "," << Util::_8s << B.C(2,i); 00510 if (i==B.C.num_cols()-1) os << "]]}"; 00511 else os << "],\n "; 00512 } 00513 return os; 00514 } 00515 00516 #ifdef USE_BOOST_PYTHON 00517 00518 inline void Block::PySet (BPy::dict const & Dat) 00519 { 00520 // allocate data 00521 NDim = BPy::extract<int>(Dat["ndim"])(); 00522 Tag = BPy::extract<int>(Dat["tag"])(); 00523 Nx = BPy::extract<int>(Dat["nx"])(); 00524 Ny = BPy::extract<int>(Dat["ny"])(); 00525 Nz = (Dat.has_key("nz") ? BPy::extract<int>(Dat["nz"])() : 0); 00526 BPy::list const & verts = BPy::extract<BPy::list>(Dat["V"])(); 00527 size_t nverts = BPy::len(verts); 00528 _initialize (nverts); 00529 00530 // read data 00531 for (size_t i=0; i<nverts; ++i) 00532 { 00533 BPy::list const & line = BPy::extract<BPy::list>(verts[i])(); 00534 VTags[i] = BPy::extract<int >(line[0])(); 00535 C(0,i) = BPy::extract<double>(line[1])(); 00536 C(1,i) = BPy::extract<double>(line[2])(); if (NDim==3) 00537 C(2,i) = BPy::extract<double>(line[3])(); 00538 } 00539 if (Dat.has_key("brytags")) 00540 { 00541 BPy::list const & brytags = BPy::extract<BPy::list>(Dat["brytags"])(); 00542 for (size_t i=0; i<BryTags.Size(); ++i) BryTags[i] = BPy::extract<int>(brytags[i])(); 00543 } 00544 00545 // check connectivity (2D) 00546 if (NDim==2) 00547 { 00548 Vec3_t p0, p1, p2; 00549 for (size_t i=1; i<nverts-1; ++i) 00550 { 00551 p0 = C(0,i-1)-C(0,i), C(1,i-1)-C(1,i), 0.0; 00552 p1 = C(0,i+1)-C(0,i), C(1,i+1)-C(1,i), 0.0; 00553 p2 = blitz::cross (p1,p0); 00554 if (p2(2)<0.0) throw new Fatal("Mesh::Block::PySet: Order of vertices is incorrect (it must be counter-clockwise)"); 00555 } 00556 } 00557 00558 // generate mid nodes 00559 if (NDim==2 && nverts==4) GenMidNodes(); 00560 if (NDim==3 && nverts==8) GenMidNodes(); 00561 } 00562 00563 #endif 00564 00565 00567 00568 00569 inline void Structured::Generate (Array<Block> const & Blks, bool O2) 00570 { 00571 // data 00572 Array<Vertex*> verts; // Vertices (with duplicates) 00573 Array<Vertex*> verts_bry; // Vertices on boundary (with duplicates) 00574 Array<Vertex*> verts_m1; // X O2 Vertices (with duplicates) 00575 Array<Vertex*> verts_m2; // Y O2 Vertices (with duplicates) 00576 Array<Vertex*> verts_m3; // Z O2 Vertices (with duplicates) 00577 00578 // info 00579 Util::Stopwatch stopwatch(/*activated*/WithInfo); 00580 00581 // check 00582 if (Blks.Size()<1) throw new Fatal("Structured::Generate: Number of blocks must be greater than 0 (%d is invalid)",Blks.Size()); 00583 00584 // erase previous mesh 00585 Erase(); 00586 00587 // check if the first block is 3D 00588 if (Blks[0].NDim!=NDim) throw new Fatal("Structured::Generate: NDim=%d of blocks must be equal to NDim=%d of Mesh::Structured",Blks[0].NDim,NDim); 00589 N.change_dim((NDim==3 ? 20 : 8)); // resize the shape values vector 00590 00591 // vertices information 00592 std::map<Vertex*,VertexInfo> vinfo; // map: pointer2vertex => info 00593 00594 // generate vertices and elements (with duplicates) 00595 double min_diagonal = Blks[0].Diagonal(); // minimum diagonal among all elements 00596 for (size_t b=0; b<Blks.Size(); ++b) 00597 { 00598 // check if all blocks have the same space dimension 00599 if (Blks[b].NDim!=NDim) throw new Fatal("Structured::Generate: All blocks must have the same space dimension"); 00600 00601 // check Nx Ny Nz 00602 if (Blks[b].Nx<1) throw new Fatal("Structured::Generate: All blocks must have Nx>0"); 00603 if (Blks[b].Ny<1) throw new Fatal("Structured::Generate: All blocks must have Ny>0"); if (NDim==3) 00604 if (Blks[b].Nz<1) throw new Fatal("Structured::Generate: All blocks must have Nz>0"); 00605 00606 // generate 00607 double t_prev = -2.0; 00608 double t = -1.0; // initial Z natural coordinate 00609 for (size_t k=0; k<(NDim==3 ? Blks[b].Nz+1 : 1); ++k) 00610 { 00611 double s_prev = -2.0; 00612 double s = -1.0; // initial Y natural coordinate 00613 for (size_t j=0; j<Blks[b].Ny+1; ++j) 00614 { 00615 double r_prev = -2.0; 00616 double r = -1.0; // initial X natural coordinate 00617 for (size_t i=0; i<Blks[b].Nx+1; ++i) 00618 { 00619 // new vertex 00620 ShapeFunc (r,s,t); 00621 Vec_t c(Blks[b].C * N); 00622 Vertex * v = new Vertex; 00623 v->Tag = 0; 00624 v->C = c(0), c(1), (NDim==3?c(2):0.0); 00625 vinfo[v].BlkNum = b; 00626 vinfo[v].Dupl = false; 00627 vinfo[v].OnBry = Blks[b].BryIDs (i,j,k,vinfo[v].BlkBryIDs); 00628 if (vinfo[v].OnBry) 00629 { 00630 v->Tag = Blks[b].GetVTag (i,j,k); 00631 verts_bry.Push (v); 00632 Blks[b].ApplyCtr (vinfo[v].BlkBryIDs, (*v)); // constraints 00633 } 00634 verts.Push (v); 00635 00636 // new O2 vertices 00637 Vertex * v1 = NULL; 00638 Vertex * v2 = NULL; 00639 Vertex * v3 = NULL; 00640 if (O2) 00641 { 00642 if (i!=0) 00643 { 00644 ShapeFunc ((r_prev+r)/2.0,s,t); 00645 c = Blks[b].C * N; 00646 v1 = new Vertex; 00647 v1->Tag = 0; 00648 v1->C = c(0), c(1), (NDim==3?c(2):0.0); 00649 vinfo[v1].BlkNum = b; 00650 vinfo[v1].Dupl = false; 00651 size_t m = (Blks[b].Nx==1 ? 2 : i-1); 00652 if (i==Blks[b].Nx) vinfo[v1].OnBry = Blks[b].BryIDs(m,j,k, vinfo[v1].BlkBryIDs); 00653 else vinfo[v1].OnBry = Blks[b].BryIDs(i,j,k, vinfo[v1].BlkBryIDs); 00654 if (vinfo[v1].OnBry) 00655 { 00656 verts_bry.Push (v1); 00657 Blks[b].ApplyCtr (vinfo[v1].BlkBryIDs, (*v1)); // constraints 00658 } 00659 verts_m1.Push (v1); 00660 } 00661 if (j!=0) 00662 { 00663 ShapeFunc (r,(s_prev+s)/2.0,t); 00664 c = Blks[b].C * N; 00665 v2 = new Vertex; 00666 v2->Tag = 0; 00667 v2->C = c(0), c(1), (NDim==3?c(2):0.0); 00668 vinfo[v2].BlkNum = b; 00669 vinfo[v2].Dupl = false; 00670 size_t m = (Blks[b].Ny==1 ? 2 : j-1); 00671 if (j==Blks[b].Ny) vinfo[v2].OnBry = Blks[b].BryIDs(i,m,k, vinfo[v2].BlkBryIDs); 00672 else vinfo[v2].OnBry = Blks[b].BryIDs(i,j,k, vinfo[v2].BlkBryIDs); 00673 if (vinfo[v2].OnBry) 00674 { 00675 verts_bry.Push (v2); 00676 Blks[b].ApplyCtr (vinfo[v2].BlkBryIDs, (*v2)); // constraints 00677 } 00678 verts_m2.Push (v2); 00679 } 00680 if (k!=0) 00681 { 00682 ShapeFunc (r,s,(t_prev+t)/2.0); 00683 c = Blks[b].C * N; 00684 v3 = new Vertex; 00685 v3->Tag = 0; 00686 v3->C = c(0), c(1), (NDim==3?c(2):0.0); 00687 vinfo[v3].BlkNum = b; 00688 vinfo[v3].Dupl = false; 00689 size_t m = (Blks[b].Nz==1 ? 2 : k-1); 00690 if (k==Blks[b].Nz) vinfo[v3].OnBry = Blks[b].BryIDs(i,j,m, vinfo[v3].BlkBryIDs); 00691 else vinfo[v3].OnBry = Blks[b].BryIDs(i,j,k, vinfo[v3].BlkBryIDs); 00692 if (vinfo[v3].OnBry) 00693 { 00694 verts_bry.Push (v3); 00695 Blks[b].ApplyCtr (vinfo[v3].BlkBryIDs, (*v3)); // constraints 00696 } 00697 verts_m3.Push (v3); 00698 } 00699 } 00700 00701 // new element 00702 if (i!=0 && j!=0 && (NDim==3 ? k!=0 : true)) 00703 { 00704 Cell * e = new Cell; 00705 e->ID = Cells.Size(); 00706 e->Tag = Blks[b].Tag; 00707 e->PartID = 0; // partition id (domain decomposition) 00708 int nvonbry = 0; // number of vertices of this element on boundary 00709 size_t pnv = verts.Size()-1; // previous number of vertices 00710 Cells.Push (e); 00711 if (NDim==2) 00712 { 00713 // connectivity 00714 e->V.Resize((O2?8:4)); 00715 e->V[0] = verts[pnv - 1 - (Blks[b].Nx+1)]; 00716 e->V[1] = verts[pnv - (Blks[b].Nx+1)]; 00717 e->V[2] = verts[pnv]; 00718 e->V[3] = verts[pnv - 1]; 00719 if (O2) 00720 { 00721 size_t pnv1 = verts_m1.Size()-1; 00722 size_t pnv2 = verts_m2.Size()-1; 00723 e->V[4] = verts_m1[pnv1 - Blks[b].Nx]; 00724 e->V[5] = verts_m2[pnv2]; 00725 e->V[6] = verts_m1[pnv1]; 00726 e->V[7] = verts_m2[pnv2 - 1]; 00727 } 00728 // shares and onbry information 00729 for (size_t m=0; m<e->V.Size(); ++m) 00730 { 00731 Share s = {e,m}; 00732 if (vinfo[e->V[m]].OnBry) nvonbry++; 00733 e->V[m]->Shares.Push (s); 00734 } 00735 // diagonal 00736 double d = sqrt(pow(e->V[2]->C(0) - e->V[0]->C(0),2.0)+ 00737 pow(e->V[2]->C(1) - e->V[0]->C(1),2.0)); 00738 if (d<min_diagonal) min_diagonal = d; 00739 } 00740 else 00741 { 00742 // connectivity 00743 e->V.Resize((O2?20:8)); 00744 e->V[0] = verts[pnv - 1 - (Blks[b].Nx+1) - (Blks[b].Nx+1)*(Blks[b].Ny+1)]; 00745 e->V[1] = verts[pnv - (Blks[b].Nx+1) - (Blks[b].Nx+1)*(Blks[b].Ny+1)]; 00746 e->V[2] = verts[pnv - (Blks[b].Nx+1)*(Blks[b].Ny+1)]; 00747 e->V[3] = verts[pnv - 1 - (Blks[b].Nx+1)*(Blks[b].Ny+1)]; 00748 e->V[4] = verts[pnv - 1 - (Blks[b].Nx+1)]; 00749 e->V[5] = verts[pnv - (Blks[b].Nx+1)]; 00750 e->V[6] = verts[pnv]; 00751 e->V[7] = verts[pnv - 1]; 00752 if (O2) 00753 { 00754 size_t pnv1 = verts_m1.Size()-1; 00755 size_t pnv2 = verts_m2.Size()-1; 00756 size_t pnv3 = verts_m3.Size()-1; 00757 e->V[ 8] = verts_m1[pnv1 - Blks[b].Nx - Blks[b].Nx*(Blks[b].Ny+1)]; 00758 e->V[ 9] = verts_m2[pnv2 - Blks[b].Ny*(Blks[b].Nx+1)]; 00759 e->V[10] = verts_m1[pnv1 - Blks[b].Nx*(Blks[b].Ny+1)]; 00760 e->V[11] = verts_m2[pnv2 -1 - Blks[b].Ny*(Blks[b].Nx+1)]; 00761 00762 e->V[12] = verts_m1[pnv1 - Blks[b].Nx]; 00763 e->V[13] = verts_m2[pnv2]; 00764 e->V[14] = verts_m1[pnv1]; 00765 e->V[15] = verts_m2[pnv2 - 1]; 00766 00767 e->V[16] = verts_m3[pnv3 - 1 - (Blks[b].Nx+1)]; 00768 e->V[17] = verts_m3[pnv3 - (Blks[b].Nx+1)]; 00769 e->V[18] = verts_m3[pnv3]; 00770 e->V[19] = verts_m3[pnv3 - 1]; 00771 } 00772 // shares and onbry information 00773 for (size_t m=0; m<e->V.Size(); ++m) 00774 { 00775 Share s = {e,m}; 00776 if (vinfo[e->V[m]].OnBry) nvonbry++; 00777 e->V[m]->Shares.Push (s); 00778 } 00779 // diagonal 00780 double d = sqrt(pow(e->V[6]->C(0) - e->V[0]->C(0),2.0)+ 00781 pow(e->V[6]->C(1) - e->V[0]->C(1),2.0)+ 00782 pow(e->V[6]->C(2) - e->V[0]->C(2),2.0)); 00783 if (d<min_diagonal) min_diagonal = d; 00784 } 00785 // apply boundary tags 00786 if (nvonbry>0) 00787 { 00788 bool has_bry_tag = false; 00789 for (size_t m=0; m<(NDim==2?4:8); ++m) 00790 { 00791 for (size_t n=0; n<vinfo[e->V[m]].BlkBryIDs.Size(); ++n) 00792 { 00793 int side = vinfo[e->V[m]].BlkBryIDs[n]; 00794 int tag = Blks[b].BryTags[side]; 00795 if (tag<0) 00796 { 00797 e->BryTags[side] = tag; 00798 has_bry_tag = true; 00799 } 00800 } 00801 } 00802 if (has_bry_tag) TgdCells.Push (e); 00803 } 00804 } 00805 // next r 00806 r_prev = r; 00807 r += (2.0/Blks[b].SumWx) * Blks[b].Wx[i]; 00808 } 00809 // next s 00810 s_prev = s; 00811 s += (2.0/Blks[b].SumWy) * Blks[b].Wy[j]; 00812 } 00813 // next t 00814 t_prev = t; 00815 t += (NDim==3 ? (2.0/Blks[b].SumWz) * Blks[b].Wz[k] : 0.0); 00816 } 00817 } 00818 00819 // remove duplicates 00820 long ncomp = 0; // number of comparisons 00821 long ndupl = 0; // number of duplicates 00822 double tol = min_diagonal*0.001; // tolerance to decide whether two vertices are coincident or not 00823 if (Blks.Size()>1) 00824 { 00825 for (size_t i=0; i<verts_bry.Size(); ++i) 00826 { 00827 for (size_t j=i+1; j<verts_bry.Size(); ++j) 00828 { 00829 if (vinfo[verts_bry[i]].BlkNum!=vinfo[verts_bry[j]].BlkNum) // vertices are located on different blocks 00830 { 00831 // check distance 00832 double dist = sqrt( pow(verts_bry[i]->C(0)-verts_bry[j]->C(0),2.0)+ 00833 pow(verts_bry[i]->C(1)-verts_bry[j]->C(1),2.0)+ 00834 (NDim==3 ? pow(verts_bry[i]->C(2)-verts_bry[j]->C(2),2.0) : 0.0)); 00835 if (dist<tol) 00836 { 00837 // mark duplicated 00838 if (vinfo[verts_bry[j]].Dupl==false) // vertex not tagged as duplicated yet 00839 { 00840 vinfo[verts_bry[j]].Dupl = true; 00841 // change elements' connectivities 00842 for (size_t k=0; k<verts_bry[j]->Shares.Size(); ++k) 00843 { 00844 Cell * e = verts_bry[j]->Shares[k].C; 00845 int n = verts_bry[j]->Shares[k].N; 00846 e->V[n] = verts_bry[i]; 00847 Share sha = {e,n}; 00848 verts_bry[i]->Shares.Push (sha); 00849 } 00850 ndupl++; 00851 } 00852 } 00853 ncomp++; 00854 } 00855 } 00856 } 00857 } 00858 00859 // set new array with non-duplicated vertices 00860 size_t k = 0; 00861 Verts.Resize (verts.Size() + verts_m1.Size() + verts_m2.Size() + verts_m3.Size() - ndupl); 00862 for (size_t i=0; i<verts.Size(); ++i) 00863 { 00864 if (vinfo[verts[i]].Dupl==false) 00865 { 00866 Verts[k] = verts[i]; 00867 Verts[k]->ID = k; 00868 if (vinfo[verts[i]].OnBry) 00869 { 00870 if (Verts[k]->Tag<0) TgdVerts.Push (Verts[k]); 00871 } 00872 k++; 00873 } 00874 else delete verts[i]; 00875 } 00876 for (size_t i=0; i<verts_m1.Size(); ++i) 00877 { 00878 if (vinfo[verts_m1[i]].Dupl==false) 00879 { 00880 Verts[k] = verts_m1[i]; 00881 Verts[k]->ID = k; 00882 if (vinfo[verts_m1[i]].OnBry) 00883 { 00884 if (Verts[k]->Tag<0) TgdVerts.Push (Verts[k]); 00885 } 00886 k++; 00887 } 00888 else delete verts_m1[i]; 00889 } 00890 for (size_t i=0; i<verts_m2.Size(); ++i) 00891 { 00892 if (vinfo[verts_m2[i]].Dupl==false) 00893 { 00894 Verts[k] = verts_m2[i]; 00895 Verts[k]->ID = k; 00896 if (vinfo[verts_m2[i]].OnBry) 00897 { 00898 if (Verts[k]->Tag<0) TgdVerts.Push (Verts[k]); 00899 } 00900 k++; 00901 } 00902 else delete verts_m2[i]; 00903 } 00904 for (size_t i=0; i<verts_m3.Size(); ++i) 00905 { 00906 if (vinfo[verts_m3[i]].Dupl==false) 00907 { 00908 Verts[k] = verts_m3[i]; 00909 Verts[k]->ID = k; 00910 if (vinfo[verts_m3[i]].OnBry) 00911 { 00912 if (Verts[k]->Tag<0) TgdVerts.Push (Verts[k]); 00913 } 00914 k++; 00915 } 00916 else delete verts_m3[i]; 00917 } 00918 00919 // info 00920 if (WithInfo) 00921 { 00922 printf("\n%s--- Structured Mesh Generation --- %dD --- O%d ---------------------------------------%s\n",TERM_CLR1,NDim,(O2?2:1),TERM_RST); 00923 printf("%s Num of comparisons = %ld%s\n", TERM_CLR5, ncomp, TERM_RST); 00924 printf("%s Num of duplicates = %ld%s\n", TERM_CLR5, ndupl, TERM_RST); 00925 printf("%s Min diagonal = %g%s\n", TERM_CLR4, min_diagonal, TERM_RST); 00926 printf("%s Num of cells = %zd%s\n", TERM_CLR2, Cells.Size(), TERM_RST); 00927 printf("%s Num of vertices = %zd%s\n", TERM_CLR2, Verts.Size(), TERM_RST); 00928 } 00929 } 00930 00931 inline void Structured::GenBox (bool O2, int Nx, int Ny, int Nz, double Lx, double Ly, double Lz) 00932 { 00933 /* 00934 4----------------7 00935 ,'| ,'| 00936 ,' | ,' | 00937 ,' | -31 -10,' | 00938 ,' | ,' | 00939 5'===============6' | 00940 | | | -21 | 00941 | -20 | | | 00942 | 0- - - | - - - -3 00943 | ,' | ,' 00944 | ,' -11 | ,' 00945 | ,' -30| ,' 00946 | ,' | ,' 00947 1----------------2' 00948 */ 00949 Array<Block> blks(1); 00950 blks[0].Set (/*NDim*/3, /*Tag*/-1, /*NVert*/8, 00951 -1., 0.0, 0.0, 0.0, // tag, x, y, z 00952 -2., Lx, 0.0, 0.0, 00953 -3., Lx, Ly, 0.0, 00954 -4., 0.0, Ly, 0.0, 00955 -5., 0.0, 0.0, Lz, // tag, x, y, z 00956 -6., Lx, 0.0, Lz, 00957 -7., Lx, Ly, Lz, 00958 -8., 0.0, Ly, Lz, 00959 -10.,-11.,-20.,-21.,-30.,-31.); // face tags 00960 blks[0].SetNx (Nx); 00961 blks[0].SetNy (Ny); 00962 blks[0].SetNz (Nz); 00963 NDim = 3; 00964 Generate (blks,O2); 00965 } 00966 00967 inline void Structured::GenQRing (bool O2, int Nx, int Ny, double r, double R, size_t Nb, double Ax, bool NonLin, char const * WeightsX) 00968 { 00969 Array<double> Wx; 00970 if (WeightsX!=NULL) 00971 { 00972 double wx; 00973 std::istringstream iss(WeightsX); 00974 while (iss>>wx) { Wx.Push(wx); } 00975 } 00976 00977 Array<Block> blks(Nb); 00978 double alp = (Util::PI/2.0)/Nb; 00979 double bet = alp/2.0; 00980 double m = (r+R)/2.0; 00981 for (size_t i=0; i<Nb; ++i) 00982 { 00983 double tag0 = (i==0 ? -10. : 0.); 00984 double tag1 = -20.; 00985 double tag2 = (i==Nb-1 ? -30. : 0.); 00986 double tag3 = -40.; 00987 blks[i].Set (/*NDim*/2, /*Tag*/-1, /*NVert*/8, 00988 0., r*cos(i*alp) , r*sin(i*alp) , 00989 0., R*cos(i*alp) , R*sin(i*alp) , 00990 0., R*cos((i+1)*alp) , R*sin((i+1)*alp) , 00991 0., r*cos((i+1)*alp) , r*sin((i+1)*alp) , 00992 0., m*cos(i*alp) , m*sin(i*alp) , 00993 0., R*cos(i*alp+bet) , R*sin(i*alp+bet) , 00994 0., m*cos((i+1)*alp) , m*sin((i+1)*alp) , 00995 0., r*cos(i*alp+bet) , r*sin(i*alp+bet) , 00996 tag0,tag1,tag2,tag3); 00997 if (WeightsX!=NULL) blks[i].SetNx (Wx); 00998 else blks[i].SetNx (Nx, Ax, NonLin); 00999 blks[i].SetNy (Ny); 01000 blks[i].AddArcCtr (/*side*/1, /*x*/0.0, /*y*/0.0, R); 01001 blks[i].AddArcCtr (/*side*/3, /*x*/0.0, /*y*/0.0, r); 01002 } 01003 NDim = 2; 01004 Generate (blks,O2); 01005 } 01006 01007 inline void Structured::GenQRing (bool O2, int Nx, int Ny, int Nz, double r, double R, double t) 01008 { 01009 double m = r + (R-r)/2.0; 01010 double a = r*cos(Util::PI/4.0); 01011 double b = R*cos(Util::PI/4.0); 01012 Array<Mesh::Block> blks(1); 01013 blks[0].Set (3, -1, 20, 01014 -1. , 0.0 , r , 0.0 , // 0 01015 -2. , t , r , 0.0 , // 1 01016 -3. , t , R , 0.0 , // 2 01017 -4. , 0.0 , R , 0.0 , // 3 01018 01019 -5. , 0.0 , 0.0 , r , // 4 01020 -6. , t , 0.0 , r , // 5 01021 -7. , t , 0.0 , R , // 6 01022 -8. , 0.0 , 0.0 , R , // 7 01023 01024 0. , t/2. , r , 0.0 , // 8 01025 0. , t , m , 0.0 , // 9 01026 0. , t/2. , R , 0.0 , // 10 01027 0. , 0.0 , m , 0.0 , // 11 01028 01029 0. , t/2. , 0.0 , r , // 12 01030 0. , t , 0.0 , m , // 13 01031 0. , t/2. , 0.0 , R , // 14 01032 0. , 0.0 , 0.0 , m , // 15 01033 01034 0. , 0.0 , a , a , // 16 01035 0. , t , a , a , // 17 01036 0. , t , b , b , // 18 01037 0. , 0.0 , b , b , // 19 01038 01039 -10.,-20.,-30.,-40.,-50.,-60.); // face tags 01040 01041 blks[0].SetNx (Nx); 01042 blks[0].SetNy (Ny); 01043 blks[0].SetNz (Nz); 01044 01045 blks[0].AddCylXCtr (2, 0.0, 0.0, r); 01046 blks[0].AddCylXCtr (3, 0.0, 0.0, R); 01047 01048 NDim = 3; 01049 Generate (blks, O2); 01050 } 01051 01052 inline void Structured::GenQDisk (bool O2, int Nx1, int Nx2, int Ny, double r, double R) 01053 { 01054 Array<Block> blks(3); 01055 double m = r + (R-r)/2.0; 01056 double n = r/2.0; 01057 double a = r*cos(Util::PI/4.0); 01058 double b = r*cos(Util::PI/8.0); 01059 double c = r*sin(Util::PI/8.0); 01060 double A = R*cos(Util::PI/4.0); 01061 double B = R*cos(Util::PI/8.0); 01062 double C = R*sin(Util::PI/8.0); 01063 double d = m*cos(Util::PI/4.0); 01064 01065 blks[0].Set (2, -1, 8, 01066 0. , 0.0 , 0.0 , 01067 0. , r , 0.0 , 01068 0. , a , a , 01069 0. , 0.0 , r , 01070 0. , n , 0.0 , 01071 0. , b , c , 01072 0. , c , b , 01073 0. , 0.0 , n , 01074 -1., -11., -22., -3.); 01075 01076 blks[1].Set (2, -1, 8, 01077 0. , r , 0.0 , 01078 0. , R , 0.0 , 01079 0. , A , A , 01080 0. , a , a , 01081 0. , m , 0.0 , 01082 0. , B , C , 01083 0. , d , d , 01084 0. , b , c , 01085 -1., -2., -33., -11.); 01086 01087 blks[2].Set (2, -1, 8, 01088 0. , a , a , 01089 0. , A , A , 01090 0. , 0.0 , R , 01091 0. , 0.0 , r , 01092 0. , d , d , 01093 0. , C , B , 01094 0. , 0.0 , m , 01095 0. , c , b , 01096 -33., -2., -3., -22.); 01097 01098 blks[0].SetNx (Nx1); 01099 blks[0].SetNy (Ny ); 01100 blks[1].SetNx (Nx2); 01101 blks[1].SetNy (Ny ); 01102 blks[2].SetNx (Nx2); 01103 blks[2].SetNy (Nx1); 01104 01105 blks[0].AddArcCtr (1, 0.0, 0.0, r); 01106 blks[0].AddArcCtr (2, 0.0, 0.0, r); 01107 blks[1].AddArcCtr (1, 0.0, 0.0, R); 01108 blks[1].AddArcCtr (3, 0.0, 0.0, r); 01109 blks[2].AddArcCtr (1, 0.0, 0.0, R); 01110 blks[2].AddArcCtr (3, 0.0, 0.0, r); 01111 01112 NDim = 2; 01113 Generate (blks,O2); 01114 } 01115 01116 inline void Structured::GenQPlateHole (double r, double R, double L, int Nx1, int Nx2, int Ny1, int Ny2, bool O2) 01117 { 01118 /* ____________________________ 01119 * | Ny1 | | 01120 * | | | 01121 * | 3 | 4 |Ny2 01122 * |__ | | 01123 * | `--,__ | | 01124 * | 1 `,A ______ q_______| 01125 * |__ d/ `, | 01126 * `--,/ \B,C | 01127 * `- 0 \ 2 |Ny1 01128 * _________ | \ | | 01129 * c | | | | | 01130 * _|____ | |_Nx1_|____Nx2____| 01131 * | | p 01132 * |---a--| || | | | 01133 * || | | | 01134 * |---b----|| | | | 01135 * | | | | 01136 * |----r----| | | | 01137 * | | | 01138 * |------m------| | | 01139 * | | 01140 * |-------R--------| | 01141 * | 01142 * |-------------L--------------| */ 01143 01144 if (R-r<0.0) throw new Fatal("Mesh::Structured:GenQPlateHole: R=%g must be greater than r=%g",R,r); 01145 if (L-R<0.0) throw new Fatal("Mesh::Structured:GenQPlateHole: L=%g must be greater than R=%g",L,R); 01146 01147 Array<Block> blks(5); 01148 double m = r + (R-r)/2.0; 01149 double a = r*cos(Util::PI/4.0); 01150 double b = r*cos(Util::PI/8.0); 01151 double c = r*sin(Util::PI/8.0); 01152 double A = R*cos(Util::PI/4.0); 01153 double B = R*cos(Util::PI/8.0); 01154 double C = R*sin(Util::PI/8.0); 01155 double d = m*cos(Util::PI/4.0); 01156 double p = R + (L-R)/2.0; 01157 double q = A + (L-A)/2.0; 01158 01159 blks[0].Set (2, -1, 8, 01160 0. , r , 0.0 , 01161 0. , R , 0.0 , 01162 0. , A , A , 01163 0. , a , a , 01164 0. , m , 0.0 , 01165 0. , B , C , 01166 0. , d , d , 01167 0. , b , c , 01168 -10., 0., 0., -14.); 01169 01170 blks[1].Set (2, -1, 8, 01171 0. , a , a , 01172 0. , A , A , 01173 0. , 0.0 , R , 01174 0. , 0.0 , r , 01175 0. , d , d , 01176 0. , C , B , 01177 0. , 0.0 , m , 01178 0. , c , b , 01179 0., 0., -13., -14.); 01180 01181 blks[2].Set (2, -1, 8, 01182 0. , R , 0.0 , 01183 0. , L , 0.0 , 01184 0. , L , A , 01185 0. , A , A , 01186 0. , p , 0.0 , 01187 0. , L , A/2., 01188 0. , q , A , 01189 0. , B , C , 01190 -10., -11., 0., 0.); 01191 01192 blks[3].Set (2, -1, 8, 01193 0. , A , A , 01194 0. , A , L , 01195 0. , 0.0 , L , 01196 0. , 0.0 , R , 01197 0. , A , q , 01198 0. , A/2. , L , 01199 0. , 0.0 , p , 01200 0. , C , B , 01201 0., -12., -13., 0.); 01202 01203 blks[4].Set (2, -1, 8, 01204 0. , A , A , 01205 0. , L , A , 01206 0. , L , L , 01207 0. , A , L , 01208 0. , q , A , 01209 0. , L , q , 01210 0. , q , L , 01211 0. , A , q , 01212 0., -11., -12., 0.); 01213 01214 blks[0].SetNx(Nx1); blks[0].SetNy(Ny1); 01215 blks[1].SetNx(Nx1); blks[1].SetNy(Ny1); 01216 blks[2].SetNx(Nx2); blks[2].SetNy(Ny1); 01217 blks[3].SetNx(Ny2); blks[3].SetNy(Ny1); 01218 blks[4].SetNx(Nx2); blks[4].SetNy(Ny2); 01219 01220 blks[0].AddArcCtr(1, 0.0, 0.0, R); blks[0].AddArcCtr(3, 0.0, 0.0, r); 01221 blks[1].AddArcCtr(1, 0.0, 0.0, R); blks[1].AddArcCtr(3, 0.0, 0.0, r); 01222 blks[2].AddArcCtr(3, 0.0, 0.0, R); 01223 blks[3].AddArcCtr(3, 0.0, 0.0, R); 01224 01225 NDim = 2; 01226 Generate (blks,O2); 01227 } 01228 01229 inline void Structured::ShapeFunc (double r, double s, double t) 01230 { 01231 if (NDim==2) 01232 { 01233 /* 3 6 2 01234 * @---------@----------@ 01235 * | (1,1)| 01236 * | s ^ | 01237 * | | | 01238 * | | | 01239 * 7 @ +----> r @ 5 01240 * | (0,0) | 01241 * | | 01242 * | | 01243 * |(-1,-1) | 01244 * @---------@----------@ 01245 * 0 4 1 01246 */ 01247 double rp1=1.0+r; double rm1=1.0-r; 01248 double sp1=1.0+s; double sm1=1.0-s; 01249 01250 N(0) = 0.25*rm1*sm1*(rm1+sm1-3.0); 01251 N(1) = 0.25*rp1*sm1*(rp1+sm1-3.0); 01252 N(2) = 0.25*rp1*sp1*(rp1+sp1-3.0); 01253 N(3) = 0.25*rm1*sp1*(rm1+sp1-3.0); 01254 N(4) = 0.50*sm1*(1.0-r*r); 01255 N(5) = 0.50*rp1*(1.0-s*s); 01256 N(6) = 0.50*sp1*(1.0-r*r); 01257 N(7) = 0.50*rm1*(1.0-s*s); 01258 } 01259 else 01260 { 01261 /* t 01262 * | 01263 * +---s 4 15 7 01264 * ,' @_______@________@ 01265 * r ,'| ,'| The origin is in the 01266 * 12 @' | 14 ,' | centre of the cube: 01267 * ,' |16 ,@ |19 0 => (-1,-1) 01268 * 5 ,' @ 6 ,' @ 6 => ( 1, 1) 01269 * @'=======@=======@' | 01270 * | 13 | | | 01271 * | | | 11 | 01272 * 17 | 0 @______|_@_______@ 01273 * @ ,' @ ,' 3 01274 * | 8 @' 18 | ,' 01275 * | ,' | ,@ 10 01276 * | ,' | ,' 01277 * @_______@________@' 01278 * 1 9 2 01279 */ 01280 N( 0) = 0.125*(1.0-r) *(1.0-s) *(1.0-t) *(-r-s-t-2.0); 01281 N( 1) = 0.125*(1.0+r) *(1.0-s) *(1.0-t) *( r-s-t-2.0); 01282 N( 2) = 0.125*(1.0+r) *(1.0+s) *(1.0-t) *( r+s-t-2.0); 01283 N( 3) = 0.125*(1.0-r) *(1.0+s) *(1.0-t) *(-r+s-t-2.0); 01284 N( 4) = 0.125*(1.0-r) *(1.0-s) *(1.0+t) *(-r-s+t-2.0); 01285 N( 5) = 0.125*(1.0+r) *(1.0-s) *(1.0+t) *( r-s+t-2.0); 01286 N( 6) = 0.125*(1.0+r) *(1.0+s) *(1.0+t) *( r+s+t-2.0); 01287 N( 7) = 0.125*(1.0-r) *(1.0+s) *(1.0+t) *(-r+s+t-2.0); 01288 01289 N( 8) = 0.25 *(1.0-r*r)*(1.0-s) *(1.0-t); 01290 N( 9) = 0.25 *(1.0+r) *(1.0-s*s)*(1.0-t); 01291 N(10) = 0.25 *(1.0-r*r)*(1.0+s) *(1.0-t); 01292 N(11) = 0.25 *(1.0-r) *(1.0-s*s)*(1.0-t); 01293 01294 N(12) = 0.25 *(1.0-r*r)*(1.0-s) *(1.0+t); 01295 N(13) = 0.25 *(1.0+r) *(1.0-s*s)*(1.0+t); 01296 N(14) = 0.25 *(1.0-r*r)*(1.0+s) *(1.0+t); 01297 N(15) = 0.25 *(1.0-r) *(1.0-s*s)*(1.0+t); 01298 01299 N(16) = 0.25 *(1.0-r) *(1.0-s) *(1.0-t*t); 01300 N(17) = 0.25 *(1.0+r) *(1.0-s) *(1.0-t*t); 01301 N(18) = 0.25 *(1.0+r) *(1.0+s) *(1.0-t*t); 01302 N(19) = 0.25 *(1.0-r) *(1.0+s) *(1.0-t*t); 01303 } 01304 } 01305 01306 #ifdef USE_BOOST_PYTHON 01307 01308 inline void Structured::PyGenerate (BPy::list const & Blks, bool O2) 01309 { 01310 size_t nblks = BPy::len(Blks); 01311 Array<Block> blks(nblks); 01312 for (size_t i=0; i<nblks; ++i) blks[i].PySet (BPy::extract<BPy::dict>(Blks[i])()); 01313 Generate (blks, O2); 01314 } 01315 01316 #endif 01317 01318 }; // namespace Mesh 01319 01320 #endif // MECHSYS_MESH_STRUCTURED_H