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