Heidelberg Educational Numerics Library Version 0.24 (from 9 September 2011)
|
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