FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
coarse_fine_cell_mapping.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
10#include <kernel/adjacency/adjactor.hpp>
11
12namespace FEAT
13{
14 namespace Geometry
15 {
16 namespace Intern
17 {
18#ifdef DOXYGEN
34 template<typename FineMesh_, typename CoarseMesh_=FineMesh_, bool is_structured_=FineMesh_::is_structured>
36 {
37 public:
47 explicit CoarseFineCellMapping(const FineMesh_& fine_mesh, const CoarseMesh_& coarse_mesh);
48
61 Index calc_fcell(Index ccell, Index child=0) const;
62
70
73
76
79
81 ImageIterator image_begin(Index domain_node) const;
82
84 ImageIterator image_end(Index domain_node) const;
85 }; // class CoarseFineCellMapping<FineMesh_, CoarseMesh_, false>
86#else
87 template<typename FineMesh_, typename CoarseMesh_=FineMesh_, bool is_structured=FineMesh_::is_structured>
89#endif // DOXYGEN
90 } // namespace Intern
91
93 namespace Intern
94 {
95 // Mapping for structured meshes
96 template<typename FineMesh_, typename CoarseMesh_>
97 class CoarseFineCellMapping<FineMesh_, CoarseMesh_, true>
98 {
99 static_assert(FineMesh_::is_structured == true, "Do not provide the third template parameter manually!");
100
101 Index _num_elements;
102 Index _num_children;
103 Index _dim[3]={1,1,1}; // fine mesh dimension
104
105 public:
106 explicit CoarseFineCellMapping(const FineMesh_& fine_mesh, const CoarseMesh_& coarse_mesh) :
107 _num_elements(coarse_mesh.get_num_entities(CoarseMesh_::ShapeType::dimension)),
108 _num_children(fine_mesh.get_num_entities(FineMesh_::ShapeType::dimension) / _num_elements)
109 {
110 for (int d(0); d < FineMesh_::ShapeType::dimension; ++d)
111 {
112 _dim[d] = fine_mesh.get_num_slices(d);
113 }
114 }
115
116 Index calc_fcell(Index ccell, Index child=0) const
117 {
118 // extract cell position based on structured numbering
119 Index xy_plane_size = _dim[0]/2;
120 if (FineMesh_::shape_dim > 1)
121 {
122 xy_plane_size *= _dim[1]/2;
123 }
124 Index zpos = ccell / xy_plane_size; // yes, it is ok to point to a non-existent slice.
125 // see also the implementation of the operator++ of ImageIterator
126 Index ypos = (ccell - zpos * xy_plane_size) / (_dim[0]/2);
127 Index xpos = ccell - zpos * xy_plane_size - ypos * (_dim[0]/2);
128
129 // coarse position -> fine position
130 zpos = 2*zpos + (child / 4);
131 ypos = 2*ypos;
132 if (child == 2 || child == 3 || child == 6 || child == 7) { ++ypos; }
133 xpos = 2*xpos + (child % 2);
134
135 return zpos * _dim[1] * _dim[0] + ypos * _dim[0] + xpos;
136 }
137
138 Index get_num_children() const
139 {
140 return _num_children;
141 }
142
143 class ImageIterator
144 {
145 protected:
146 // the current index of the iterator
147 Index _index;
148 // the dimensions of the fine mesh
149 Index _dim[3]={1,1,1};
150
151 public:
152 ImageIterator() :
153 _index(0)
154 {
155 }
156
157 explicit ImageIterator(Index index, const Index dim[]) :
158 _index(index)
159 {
160 _dim[0] = dim[0];
161 _dim[1] = dim[1];
162 _dim[2] = dim[2];
163 }
164
166 _index(other._index),
167 _dim{other._dim[0], other._dim[1], other._dim[2]}
168 {
169 }
170
171 ImageIterator& operator=(const ImageIterator& other)
172 {
173 _index = other._index;
174 _dim[0] = other._dim[0];
175 _dim[1] = other._dim[1];
176 _dim[2] = other._dim[2];
177 return *this;
178 }
179
180 ImageIterator& operator++()
181 {
182 // extract cell position based on structured numbering
183 Index zpos = _index / (_dim[0] * _dim[1]);
184 Index ypos = (_index - zpos * _dim[0] * _dim[1]) / _dim[0];
185 Index xpos = _index - zpos * _dim[0] * _dim[1] - ypos * _dim[0];
186
187 // update cell position
188 if (xpos % 2 == 0)
189 {
190 // in-element jump
191 ++xpos;
192 }
193 else
194 {
195 --xpos;
196 if (FineMesh_::ShapeType::dimension > 1 && ypos % 2 == 0)
197 {
198 // still in-element jump
199 ++ypos;
200 }
201 else
202 {
203 if (FineMesh_::ShapeType::dimension > 1) --ypos;
204 if (FineMesh_::ShapeType::dimension > 2 && zpos % 2 == 0)
205 {
206 // still in-element jump
207 ++zpos;
208 }
209 else
210 {
211 // jump to next element
212 if (FineMesh_::ShapeType::dimension > 2) --zpos; // now we point to the first fine element of the coarse element
213 if (xpos + 2 < _dim[0])
214 {
215 xpos += 2;
216 }
217 else if (ypos + 2 < _dim[1])
218 {
219 xpos = 0;
220 ypos += 2;
221 }
222 else // dont check for limit. this means we can also jump into a non-existent slice.
223 // that's needed to have the iterator at the correct endpoint.
224 // see also the implementation of calc_fcell
225 {
226 xpos = 0;
227 ypos = 0;
228 zpos += 2;
229 }
230 }
231 }
232 }
233 _index = zpos * _dim[0] * _dim[1] + ypos * _dim[0] + xpos;
234 return *this;
235 }
236
237 Index operator*() const
238 {
239 return _index;
240 }
241
242 bool operator!=(const ImageIterator& other) const
243 {
244 return _index != other._index;
245 }
246 }; // class CoarseFineCellMapping<FineMesh_, CoarseMesh_, true>::ImageIterator
247
249 {
250 return _num_elements;
251 }
252
254 {
255 return _num_elements * _num_children;
256 }
257
258 ImageIterator image_begin(Index domain_node) const
259 {
260 return ImageIterator(calc_fcell(domain_node), _dim);
261 }
262
263 ImageIterator image_end(Index domain_node) const
264 {
265 return ImageIterator(calc_fcell(domain_node+1), _dim);
266 }
267 }; // class CoarseFineCellMapping<FineMesh_, CoarseMesh_, true>
268
269 // Mapping for unstructured meshes
270 template<typename FineMesh_, typename CoarseMesh_>
271 class CoarseFineCellMapping<FineMesh_, CoarseMesh_, false>
272 {
273 static_assert(FineMesh_::is_structured == false, "Do not provide the third template parameter manually!");
274
275 Index _num_elements;
276 Index _num_children;
277
278 public:
279 explicit CoarseFineCellMapping(const FineMesh_& fine_mesh, const CoarseMesh_& coarse_mesh) :
280 _num_elements(coarse_mesh.get_num_entities(CoarseMesh_::ShapeType::dimension)),
281 _num_children(fine_mesh.get_num_entities(FineMesh_::ShapeType::dimension) / _num_elements)
282 {
283 }
284
285 Index calc_fcell(Index ccell, Index child=0) const
286 {
287 return ccell*_num_children + child;
288 }
289
290 Index get_num_children() const
291 {
292 return _num_children;
293 }
294
295 typedef Adjacency::Adjactor::IndexImageIterator ImageIterator;
296
298 {
299 return _num_elements;
300 }
301
303 {
304 return _num_elements * _num_children;
305 }
306
307 ImageIterator image_begin(Index domain_node) const
308 {
309 return ImageIterator(calc_fcell(domain_node));
310 }
311
312 ImageIterator image_end(Index domain_node) const
313 {
314 return ImageIterator(calc_fcell(domain_node+1));
315 }
316 }; // class CoarseFineCellMapping<FineMesh_, CoarseMesh_, false>
317
318 } // namespace Intern
320 } // namespace Geometry
321} // namespace FEAT
FEAT Kernel base header.
Adjactor image node iterator class.
Definition: adjactor.hpp:36
A coarse cell to fine cell mapping class.
Index calc_fcell(Index ccell, Index child=0) const
Calculates the fine mesh cell index.
Adjacency::Adjactor::ImageIterator ImageIterator
Adjactor image node iterator class.
CoarseFineCellMapping(const FineMesh_ &fine_mesh, const CoarseMesh_ &coarse_mesh)
Constructor.
ImageIterator image_end(Index domain_node) const
Returns an iterator for the first position past the last adjacent image node.
ImageIterator image_begin(Index domain_node) const
Returns an iterator for the first adjacent image node.
Index get_num_nodes_image() const
Returns the number of image nodes.
Index get_num_children() const
Returns the number of fine mesh cells per coarse mesh cell.
Index get_num_nodes_domain() const
Returns the number of domain nodes.
@ child
indicates that the level is a child level
@ other
generic/other permutation strategy
FEAT namespace.
Definition: adjactor.hpp:12
static constexpr bool operator*(TrafoTags a)
bool conversion operator
Definition: eval_tags.hpp:81
std::uint64_t Index
Index data type.