Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)

src/sgrid.hh

00001 #ifndef HDNUM_SGRID_HH
00002 #define HDNUM_SGRID_HH
00003 #include <limits>
00004 #include <assert.h>
00005 
00006 namespace hdnum {
00013   template<class N, class DF, int dimension>
00014   class SGrid
00015   {
00016   public:
00017 
00019     typedef std::size_t size_type;
00020 
00022     typedef N number_type;
00023 
00025     typedef DF DomainFunction;
00026 
00027     enum { dim = dimension };
00028 
00030     static const int positive = 1;
00031     static const int negative = -1;
00032 
00033     
00034   private:
00035   
00036     const Vector<number_type> extent;
00037     const Vector<size_type>   size;
00038     const DomainFunction & df;
00039     Vector<number_type> h;
00040     Vector<size_type> offsets;
00041     std::vector<size_type> node_map;
00042     std::vector<size_type> grid_map;
00043     std::vector<bool> inside_map;
00044     std::vector<bool> boundary_map;
00045 
00046     size_t n_nodes;
00047     
00048     inline Vector<size_type> index2grid(size_type index) const 
00049     {
00050       Vector<size_type> c(dim);
00051       for(int d=dim-1; d>=0; --d){
00052         c[d] = index / offsets[d];
00053         index -= c[d] * offsets[d];
00054       }
00055       return c;
00056     }
00057 
00058     inline Vector<number_type> grid2world(const Vector<size_type> & c) const
00059     {
00060       Vector<number_type> w(dim);
00061       for(int d=dim-1; d>=0; --d)
00062         w[d] = c[d] * h[d];
00063       return w;
00064     }
00065 
00066     inline Vector<number_type> index2world(size_type index) const
00067     {
00068       Vector<number_type> w(dim);
00069       Vector<size_type> c = index2grid(index);
00070       return grid2world(c);
00071     }
00072 
00073 
00074   public:
00075 
00077     const size_type invalid_node;
00078     
00093     SGrid(const Vector<number_type> extent_, 
00094           const Vector<size_type> size_, 
00095           const DomainFunction & df_)
00096       : extent(extent_), size(size_), df(df_), 
00097         h(dim), offsets(dim),
00098         invalid_node(std::numeric_limits<size_type>::max())
00099     {
00100       // Determine total number of nodes, increment offsets, and cell
00101       // widths.
00102       n_nodes = 1;
00103       offsets.resize(dim);
00104       h.resize(dim);
00105       for(int d=0; d<dim; ++d){
00106         n_nodes *= size[d];
00107         offsets[d] = d==0 ? 1 : size[d-1] * offsets[d-1];
00108         h[d] = extent[d] / number_type(size[d]-1);
00109       }
00110 
00111       // Initialize maps.
00112       node_map.resize(0);
00113       inside_map.resize(n_nodes);
00114       grid_map.resize(n_nodes);
00115       boundary_map.resize(0);
00116       boundary_map.resize(n_nodes,false);
00117 
00118       for(size_type n=0; n<n_nodes; ++n){
00119         Vector<size_type> c = index2grid(n);
00120         Vector<number_type> x = grid2world(c);
00121       
00122         inside_map[n] = df.evaluate(x);
00123         if(inside_map[n]){
00124           node_map.push_back(n);
00125           grid_map[n] = node_map.size()-1;
00126         }
00127         else
00128           grid_map[n] = invalid_node;
00129       }
00130 
00131       // Find boundary nodes
00132       for(size_type n=0; n<node_map.size(); ++n){
00133         for(int d=0; d<dim; ++d){
00134           for(int s=0; s<2; ++s){
00135             const int side = s*2-1;
00136             const size_type neighbor = getNeighborIndex(n,d,side,1);
00137             if(neighbor == invalid_node)
00138               boundary_map[node_map[n]] = true;
00139           }
00140         }
00141       }
00142 
00143     }
00144 
00164     size_type getNeighborIndex(const size_type ln, const size_type n_dim, const int n_side, const int k = 1) const
00165     {
00166       const size_type n = node_map[ln];
00167       const Vector<size_type> c = index2grid(n);
00168       size_type neighbors[2];
00169       neighbors[0] = c[n_dim];
00170       neighbors[1] = size[n_dim]-c[n_dim]-1;
00171 
00172       assert(n_side == 1 || n_side == -1);
00173       if(size_type(k) > neighbors[(n_side+1)/2])
00174         return invalid_node;
00175 
00176       const size_type neighbor = n + offsets[n_dim] * n_side * k;
00177 
00178       if(!inside_map[neighbor])
00179         return invalid_node;
00180 
00181       return grid_map[neighbor];
00182     }
00183 
00187     bool isBoundaryNode(const size_type ln) const
00188     {
00189       return boundary_map[node_map[ln]];
00190     }
00191 
00195     size_type getNumberOfNodes() const
00196     {
00197       return node_map.size();
00198     }
00199 
00200     Vector<size_type> getGridSize() const
00201     {
00202       return size;
00203     }
00204 
00207     Vector<number_type> getCellWidth() const
00208     {
00209       return h;
00210     }
00211 
00215     Vector<number_type> getCoordinates(const size_type ln) const
00216     {
00217       return index2world(node_map[ln]);
00218     }
00219 
00220     std::vector<Vector<number_type> > getNodeCoordinates() const
00221     {
00222       std::vector<Vector<number_type> > coords;
00223       for(size_type n=0; n<node_map.size(); ++n){
00224         coords.push_back(Vector<number_type>(dim));
00225         coords.back() = index2world(node_map[n]);
00226       }
00227       return coords;
00228     }
00229   
00230   };
00231 
00232 };
00233 
00234 #endif // HDNUM_SGRID_HH