dune-grid
2.1.1
|
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