dune-grid  2.1.1
structuredgridfactory.hh
Go to the documentation of this file.
00001 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002 // vi: set et ts=4 sw=4 sts=4:
00003 #ifndef DUNE_STRUCTURED_GRID_FACTORY_HH
00004 #define DUNE_STRUCTURED_GRID_FACTORY_HH
00005 
00010 #include <algorithm>
00011 #include <cstddef>
00012 #include <cstdlib>
00013 
00014 #include <dune/common/array.hh>
00015 #include <dune/common/classname.hh>
00016 #include <dune/common/exceptions.hh>
00017 #include <dune/common/fvector.hh>
00018 #include <dune/common/mpihelper.hh>
00019 #include <dune/common/shared_ptr.hh>
00020 
00021 #include <dune/grid/common/gridfactory.hh>
00022 #include <dune/grid/yaspgrid.hh>
00023 
00024 namespace Dune {
00025 
00028     template <class GridType>
00029     class StructuredGridFactory
00030     {
00031         typedef typename GridType::ctype ctype;
00032 
00033         static const int dim = GridType::dimension;
00034 
00035         static const int dimworld = GridType::dimensionworld;
00036 
00039         class MultiIndex
00040             : public array<unsigned int,dim>
00041         {
00042 
00043             // The range of each component
00044             array<unsigned int,dim> limits_;
00045 
00046         public:
00048             MultiIndex(const array<unsigned int,dim>& limits)
00049                 : limits_(limits)
00050             {
00051                 std::fill(this->begin(), this->end(), 0);
00052             }
00053 
00055             MultiIndex& operator++() {
00056 
00057                 for (int i=0; i<dim; i++) {
00058 
00059                     // Augment digit
00060                     (*this)[i]++;
00061 
00062                     // If there is no carry-over we can stop here
00063                     if ((*this)[i]<limits_[i])
00064                         break;
00065 
00066                     (*this)[i] = 0;
00067                     
00068                 }
00069                 return *this;
00070             }
00071 
00073             size_t cycle() const {
00074                 size_t result = 1;
00075                 for (int i=0; i<dim; i++)
00076                     result *= limits_[i];
00077                 return result;
00078             }
00079 
00080         };
00081         
00083         static void insertVertices(GridFactory<GridType>& factory,
00084                                    const FieldVector<ctype,dim>& lowerLeft,
00085                                    const FieldVector<ctype,dim>& upperRight,
00086                                    const array<unsigned int,dim>& vertices)
00087         {
00088 
00089             MultiIndex index(vertices);
00090 
00091             // Compute the total number of vertices to be created
00092             int numVertices = index.cycle();
00093 
00094             // Create vertices
00095             for (int i=0; i<numVertices; i++, ++index) {
00096                 
00097                 // scale the multiindex to obtain a world position
00098                 FieldVector<double,dimworld> pos(0);
00099                 for (int j=0; j<dim; j++)
00100                     pos[j] = lowerLeft[j] + index[j] * (upperRight[j]-lowerLeft[j])/(vertices[j]-1);
00101                         
00102                 factory.insertVertex(pos);
00103                         
00104             }
00105                     
00106         }
00107         
00108         // Compute the index offsets needed to move to the adjacent vertices
00109         // in the different coordinate directions
00110         static array<unsigned int, dim> computeUnitOffsets(const array<unsigned int,dim>& vertices)
00111         {
00112             array<unsigned int, dim> unitOffsets;
00113             if (dim>0)  // paranoia
00114                 unitOffsets[0] = 1;
00115             
00116             for (int i=1; i<dim; i++)
00117                 unitOffsets[i] = unitOffsets[i-1] * vertices[i-1];
00118 
00119             return unitOffsets;
00120         }
00121         
00122     public:
00123         
00129         static shared_ptr<GridType> createCubeGrid(const FieldVector<ctype,dimworld>& lowerLeft,
00130                                                    const FieldVector<ctype,dimworld>& upperRight,
00131                                                    const array<unsigned int,dim>& elements)
00132         {
00133             // The grid factory
00134             GridFactory<GridType> factory;
00135 
00136             if (MPIHelper::getCollectiveCommunication().rank() == 0)
00137             {
00138                 // Insert uniformly spaced vertices
00139                 array<unsigned int,dim> vertices = elements;
00140                 for( size_t i = 0; i < vertices.size(); ++i )
00141                     vertices[i]++;
00142 
00143                 // Insert vertices for structured grid into the factory
00144                 insertVertices(factory, lowerLeft, upperRight, vertices);
00145 
00146                 // Compute the index offsets needed to move to the adjacent
00147                 // vertices in the different coordinate directions
00148                 array<unsigned int, dim> unitOffsets =
00149                     computeUnitOffsets(vertices);
00150 
00151                 // Compute an element template (the cube at (0,...,0).  All
00152                 // other cubes are constructed by moving this template around
00153                 unsigned int nCorners = 1<<dim;
00154 
00155                 std::vector<unsigned int> cornersTemplate(nCorners,0);
00156 
00157                 for (size_t i=0; i<nCorners; i++)
00158                     for (int j=0; j<dim; j++)
00159                         if ( i & (1<<j) )
00160                             cornersTemplate[i] += unitOffsets[j];
00161 
00162                 // Insert elements
00163                 MultiIndex index(elements);
00164 
00165                 // Compute the total number of elementss to be created
00166                 int numElements = index.cycle();
00167 
00168                 for (int i=0; i<numElements; i++, ++index) {
00169 
00170                     // 'base' is the index of the lower left element corner
00171                     unsigned int base = 0;
00172                     for (int j=0; j<dim; j++)
00173                         base += index[j] * unitOffsets[j];
00174 
00175                     // insert new element
00176                     std::vector<unsigned int> corners = cornersTemplate;
00177                     for (size_t j=0; j<corners.size(); j++)
00178                         corners[j] += base;
00179 
00180                     factory.insertElement
00181                         (GeometryType(GeometryType::cube, dim), corners);
00182 
00183                 }
00184 
00185             } // if(rank == 0)
00186 
00187             // Create the grid and hand it to the calling method
00188             return shared_ptr<GridType>(factory.createGrid());
00189             
00190         }
00191         
00198         static shared_ptr<GridType> createSimplexGrid(const FieldVector<ctype,dimworld>& lowerLeft,
00199                                                       const FieldVector<ctype,dimworld>& upperRight,
00200                                                       const array<unsigned int,dim>& elements)
00201         {
00202             // The grid factory
00203             GridFactory<GridType> factory;
00204 
00205             if(MPIHelper::getCollectiveCommunication().rank() == 0)
00206             {
00207                 // Insert uniformly spaced vertices
00208                 array<unsigned int,dim> vertices = elements;
00209                 for (std::size_t i=0; i<vertices.size(); i++)
00210                     vertices[i]++;
00211 
00212                 insertVertices(factory, lowerLeft, upperRight, vertices);
00213 
00214                 // Compute the index offsets needed to move to the adjacent
00215                 // vertices in the different coordinate directions
00216                 array<unsigned int, dim> unitOffsets =
00217                     computeUnitOffsets(vertices);
00218 
00219                 // Insert the elements
00220                 std::vector<unsigned int> corners(dim+1);
00221 
00222                 // Loop over all "cubes", and split up each cube into dim!
00223                 // (factorial) simplices
00224                 MultiIndex elementsIndex(elements);
00225                 size_t cycle = elementsIndex.cycle();
00226 
00227                 for (size_t i=0; i<cycle; ++elementsIndex, i++) {
00228 
00229                     // 'base' is the index of the lower left element corner
00230                     unsigned int base = 0;
00231                     for (int j=0; j<dim; j++)
00232                         base += elementsIndex[j] * unitOffsets[j];
00233 
00234                     // each permutation of the unit vectors gives a simplex.
00235                     std::vector<unsigned int> permutation(dim);
00236                     for (int j=0; j<dim; j++)
00237                         permutation[j] = j;
00238 
00239                     do {
00240 
00241                         // Make a simplex
00242                         std::vector<unsigned int> corners(dim+1);
00243                         corners[0] = base;
00244 
00245                         for (int j=0; j<dim; j++)
00246                             corners[j+1] =
00247                                 corners[j] + unitOffsets[permutation[j]];
00248 
00249                         factory.insertElement
00250                             (GeometryType(GeometryType::simplex, dim),
00251                              corners);
00252 
00253                     } while (std::next_permutation(permutation.begin(),
00254                                                    permutation.end()));
00255 
00256                 }
00257 
00258             } // if(rank == 0)
00259 
00260             // Create the grid and hand it to the calling method
00261             return shared_ptr<GridType>(factory.createGrid());
00262         }
00263 
00264     };
00265 
00275     template<int dim>
00276     class StructuredGridFactory<YaspGrid<dim> > {
00277         typedef YaspGrid<dim> GridType;
00278         typedef typename GridType::ctype ctype;
00279         static const int dimworld = GridType::dimensionworld;
00280 
00281     public:
00291         static shared_ptr<GridType>
00292         createCubeGrid(const FieldVector<ctype,dimworld>& lowerLeft,
00293                        const FieldVector<ctype,dimworld>& upperRight,
00294                        const array<unsigned int,dim>& elements)
00295         {
00296             for(int d = 0; d < dimworld; ++d)
00297                 if(std::abs(lowerLeft[d]) > std::abs(upperRight[d])*1e-10)
00298                     DUNE_THROW(GridError, className<StructuredGridFactory>()
00299                                << "::createCubeGrid(): The lower coordinates "
00300                                "must be at the origin for YaspGrid.");
00301 
00302             FieldVector<int, dim> elements_;
00303             std::copy(elements.begin(), elements.end(), elements_.begin());
00304 
00305             return shared_ptr<GridType>
00306                 (new GridType(upperRight, elements_,
00307                               FieldVector<bool,dim>(false), 0));
00308         }
00309 
00315         static shared_ptr<GridType>
00316         createSimplexGrid(const FieldVector<ctype,dimworld>& lowerLeft,
00317                           const FieldVector<ctype,dimworld>& upperRight,
00318                           const array<unsigned int,dim>& elements)
00319         {
00320             DUNE_THROW(GridError, className<StructuredGridFactory>()
00321                        << "::createSimplexGrid(): Simplices are not supported "
00322                        "by YaspGrid.");
00323         }
00324 
00325     };
00326 
00327 }  // namespace Dune
00328 
00329 #endif