Line | Branch | Exec | Source |
---|---|---|---|
1 | // This file is part of Bembel, the higher order C++ boundary element library. | ||
2 | // | ||
3 | // Copyright (C) 2022 see <http://www.bembel.eu> | ||
4 | // | ||
5 | // It was written as part of a cooperation of J. Doelz, H. Harbrecht, S. Kurz, | ||
6 | // M. Multerer, S. Schoeps, and F. Wolf at Technische Universitaet Darmstadt, | ||
7 | // Universitaet Basel, and Universita della Svizzera italiana, Lugano. This | ||
8 | // source code is subject to the GNU General Public License version 3 and | ||
9 | // provided WITHOUT ANY WARRANTY, see <http://www.bembel.eu> for further | ||
10 | // information. | ||
11 | |||
12 | #ifndef BEMBEL_SRC_CLUSTERTREE_ELEMENTTREE_HPP_ | ||
13 | #define BEMBEL_SRC_CLUSTERTREE_ELEMENTTREE_HPP_ | ||
14 | |||
15 | namespace Bembel { | ||
16 | /** | ||
17 | * \ingroup ClusterTree | ||
18 | * \brief This class organizes an element structure on a Geometry object and | ||
19 | * handles refinement. | ||
20 | * | ||
21 | * This class implements a tree which realizes the refinement of the geometry. | ||
22 | * On the first level of refinement the leafs/elements are all patches of the | ||
23 | * geometry. Currently, the construction of the tree allows uniform refinement. | ||
24 | * In the refinement process each element get four sons and the neighborhood | ||
25 | * relations get updated. | ||
26 | * | ||
27 | * The heart of the ElementTree is the leaf iterator which implements a Morton | ||
28 | * Z-curve. If an element get refined it gets replaced by it four sons element. | ||
29 | * This core routine can handle adaptive refinement but with some limitations in | ||
30 | * the resolution of neighborhood relations. | ||
31 | */ | ||
32 | class ElementTree { | ||
33 | public: | ||
34 | ////////////////////////////////////////////////////////////////////////////// | ||
35 | /** | ||
36 | * \brief Deleted copy constructor for the ElementTree class. | ||
37 | * | ||
38 | * This copy constructor is explicitly deleted to prevent copying of | ||
39 | * ElementTree objects. | ||
40 | */ | ||
41 | ElementTree(const ElementTree &) = delete; | ||
42 | |||
43 | /** | ||
44 | * \brief Deleted move constructor for the ElementTree class. | ||
45 | * | ||
46 | * This move constructor is explicitly deleted to prevent moving of | ||
47 | * ElementTree objects. | ||
48 | */ | ||
49 | ElementTree(ElementTree &&) = delete; | ||
50 | |||
51 | /** | ||
52 | * \brief Deleted copy assignment operator for the ElementTree class. | ||
53 | * | ||
54 | * This copy assignment operator is explicitly deleted to prevent copying of | ||
55 | * ElementTree objects. | ||
56 | * | ||
57 | * \return A reference to the updated ElementTree object. | ||
58 | */ | ||
59 | ElementTree &operator=(const ElementTree &) = delete; | ||
60 | |||
61 | /** | ||
62 | * \brief Deleted move assignment operator for the ElementTree class. | ||
63 | * | ||
64 | * This move assignment operator is explicitly deleted to prevent moving of | ||
65 | * ElementTree objects. | ||
66 | * | ||
67 | * \return A reference to the updated ElementTree object. | ||
68 | */ | ||
69 | ElementTree &operator=(ElementTree &&) = delete; | ||
70 | ////////////////////////////////////////////////////////////////////////////// | ||
71 | /// constructors | ||
72 | ////////////////////////////////////////////////////////////////////////////// | ||
73 | /** | ||
74 | * \brief Default constructor for the ElementTree class. | ||
75 | */ | ||
76 | 168 | ElementTree() {} | |
77 | /** | ||
78 | * \brief Explicit constructor for the ElementTree class. | ||
79 | * | ||
80 | * This constructor initializes an ElementTree object for the provided | ||
81 | * geometry and maximum level. Currently this constructor is implemented for | ||
82 | * uniform refinement. | ||
83 | * | ||
84 | * \param g The geometry object defining the patches. | ||
85 | * \param max_level (optional) The maximum level of the ElementTree. Default | ||
86 | * is 0. | ||
87 | */ | ||
88 | explicit ElementTree(const Geometry &g, unsigned int max_level = 0) { | ||
89 | init_ElementTree(g, max_level); | ||
90 | } | ||
91 | ////////////////////////////////////////////////////////////////////////////// | ||
92 | /// init | ||
93 | ////////////////////////////////////////////////////////////////////////////// | ||
94 | /** | ||
95 | * \brief This function initializes the ElementTree | ||
96 | * | ||
97 | * First Each Patch becomes an ElementTreeNode. After resolving the patch | ||
98 | * neighborhood relations each patch gets refined to the common maximum level | ||
99 | * of refinement. | ||
100 | * | ||
101 | * \param g The geometry object defining the patches. | ||
102 | * \param max_level (optional) The maximum level of the ElementTree. Default | ||
103 | * is 0. | ||
104 | */ | ||
105 | 168 | void init_ElementTree(const Geometry &g, unsigned int max_level) { | |
106 | // initialise the data fields | ||
107 | 168 | geometry_ = g.get_geometry_ptr(); | |
108 | 168 | max_level_ = max_level; | |
109 | 168 | number_of_patches_ = geometry_->size(); | |
110 | // create the patches and set up the topology | ||
111 | { | ||
112 | 168 | std::vector<Eigen::Vector3d> uniquePts; | |
113 | 168 | std::vector<ElementTreeNode *> patches; | |
114 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
168 | Eigen::Vector3d v; |
115 | 168 | number_of_points_ = 0; | |
116 | 168 | number_of_elements_ = number_of_patches_; | |
117 | 168 | ElementTreeNode &root = root_; | |
118 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
168 | root.sons_.resize(number_of_patches_); |
119 |
2/2✓ Branch 0 taken 725 times.
✓ Branch 1 taken 168 times.
|
893 | for (auto i = 0; i < number_of_patches_; ++i) { |
120 |
1/2✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
|
725 | root.sons_[i].adjcents_ = std::vector<ElementTreeNode *>(4, nullptr); |
121 |
1/2✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
|
725 | root.sons_[i].vertices_.resize(4); |
122 | 725 | root.sons_[i].id_ = i; | |
123 | 725 | root.sons_[i].level_ = 0; | |
124 | 725 | root.sons_[i].patch_ = i; | |
125 | // add linked list structure to the panels | ||
126 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 557 times.
|
725 | if (i == 0) { |
127 | 168 | root.sons_[0].prev_ = nullptr; | |
128 | 168 | pfirst_ = std::addressof(root.sons_[0]); | |
129 | } else { | ||
130 | 557 | root.sons_[i].prev_ = std::addressof(root.sons_[i - 1]); | |
131 | } | ||
132 |
2/2✓ Branch 0 taken 168 times.
✓ Branch 1 taken 557 times.
|
725 | if (i == number_of_patches_ - 1) { |
133 | 168 | root.sons_[i].next_ = nullptr; | |
134 | 168 | plast_ = std::addressof(root.sons_[i]); | |
135 | } else { | ||
136 | 557 | root.sons_[i].next_ = std::addressof(root.sons_[i + 1]); | |
137 | } | ||
138 | // get images of the four corners of the unit square under the | ||
139 | // diffeomorphism geo[i] | ||
140 |
2/2✓ Branch 0 taken 2900 times.
✓ Branch 1 taken 725 times.
|
3625 | for (auto j = 0; j < 4; ++j) { |
141 | 2900 | v = (*geometry_)[i].eval(Constants::corners[0][j], | |
142 |
1/2✓ Branch 1 taken 2900 times.
✗ Branch 2 not taken.
|
2900 | Constants::corners[1][j]); |
143 | 2900 | unsigned int index = 0; | |
144 |
2/2✓ Branch 1 taken 12094 times.
✓ Branch 2 taken 1732 times.
|
13826 | for (; index < uniquePts.size(); ++index) |
145 |
4/6✓ Branch 2 taken 12094 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12094 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1168 times.
✓ Branch 8 taken 10926 times.
|
12094 | if ((uniquePts[index] - v).norm() < Constants::pt_comp_tolerance) |
146 | 1168 | break; | |
147 |
2/2✓ Branch 1 taken 1168 times.
✓ Branch 2 taken 1732 times.
|
2900 | if (index != uniquePts.size()) { |
148 | 1168 | root.sons_[i].vertices_[j] = index; | |
149 | } else { | ||
150 |
1/2✓ Branch 1 taken 1732 times.
✗ Branch 2 not taken.
|
1732 | uniquePts.push_back(v); |
151 | 1732 | root.sons_[i].vertices_[j] = number_of_points_; | |
152 | 1732 | ++number_of_points_; | |
153 | } | ||
154 | } | ||
155 |
1/2✓ Branch 3 taken 725 times.
✗ Branch 4 not taken.
|
725 | patches.push_back(std::addressof(root.sons_[i])); |
156 | } | ||
157 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
168 | updateTopology(patches); |
158 | 168 | } | |
159 |
2/2✓ Branch 1 taken 241 times.
✓ Branch 2 taken 168 times.
|
409 | for (auto i = 0; i < max_level; ++i) refineUniformly(); |
160 | 168 | return; | |
161 | } | ||
162 | ////////////////////////////////////////////////////////////////////////////// | ||
163 | /** | ||
164 | * \brief Refine the given element or it's sons. | ||
165 | * | ||
166 | * This function refines an element recursively. If the given element is | ||
167 | * already refined than iterate all sons and refine them and so on. | ||
168 | */ | ||
169 | 7801 | void refineUniformly_recursion(ElementTreeNode &el) { | |
170 |
2/2✓ Branch 1 taken 1865 times.
✓ Branch 2 taken 5936 times.
|
7801 | if (el.sons_.size()) { |
171 |
2/2✓ Branch 1 taken 7560 times.
✓ Branch 2 taken 1865 times.
|
9425 | for (auto i = 0; i < el.sons_.size(); ++i) |
172 | 7560 | refineUniformly_recursion(el.sons_[i]); | |
173 | } else { | ||
174 | 5936 | refineLeaf(el); | |
175 | } | ||
176 | 7801 | return; | |
177 | } | ||
178 | ////////////////////////////////////////////////////////////////////////////// | ||
179 | /** | ||
180 | * \brief Refine all patches uniformly | ||
181 | */ | ||
182 | 241 | void refineUniformly() { | |
183 | 241 | refineUniformly_recursion(root_); | |
184 | 241 | return; | |
185 | } | ||
186 | ////////////////////////////////////////////////////////////////////////////// | ||
187 | /** | ||
188 | * \brief Refine a given patch. | ||
189 | */ | ||
190 | void refinePatch(int patch) { | ||
191 | refineUniformly_recursion(root_.sons_[patch]); | ||
192 | return; | ||
193 | } | ||
194 | ////////////////////////////////////////////////////////////////////////////// | ||
195 | /** | ||
196 | * \brief Return the coordinates of all points of the elements. | ||
197 | * | ||
198 | * This function iterates all elements and returns the coordinates of the | ||
199 | * vertices. | ||
200 | * | ||
201 | * \param idct Pointer to an Eigen::VectorXi to count how often a vertex is | ||
202 | * part of all elements. | ||
203 | * | ||
204 | * \return A 3xN Matrix where N is the number of all vertices in the geometry. | ||
205 | */ | ||
206 | 168 | Eigen::MatrixXd generatePointList(Eigen::VectorXi *idct = nullptr) const { | |
207 |
1/2✓ Branch 1 taken 168 times.
✗ Branch 2 not taken.
|
168 | Eigen::MatrixXd pts(3, number_of_points_); |
208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
|
168 | if (idct != nullptr) { |
209 | ✗ | idct->resize(number_of_points_); | |
210 | ✗ | idct->setZero(); | |
211 | } | ||
212 |
2/2✓ Branch 4 taken 18533 times.
✓ Branch 5 taken 168 times.
|
18701 | for (auto it = pbegin(); it != pend(); ++it) { |
213 | 18533 | double h = double(1) / double(1 << it->level_); | |
214 |
1/2✓ Branch 3 taken 18533 times.
✗ Branch 4 not taken.
|
18533 | pts.col(it->vertices_[0]) = |
215 |
4/8✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18533 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 18533 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 18533 times.
✗ Branch 16 not taken.
|
37066 | (*geometry_)[it->patch_].eval(it->llc_(0), it->llc_(1)); |
216 |
1/2✓ Branch 3 taken 18533 times.
✗ Branch 4 not taken.
|
18533 | pts.col(it->vertices_[1]) = |
217 |
4/8✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18533 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 18533 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 18533 times.
✗ Branch 16 not taken.
|
37066 | (*geometry_)[it->patch_].eval(it->llc_(0) + h, it->llc_(1)); |
218 |
1/2✓ Branch 3 taken 18533 times.
✗ Branch 4 not taken.
|
18533 | pts.col(it->vertices_[2]) = |
219 |
4/8✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18533 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 18533 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 18533 times.
✗ Branch 16 not taken.
|
37066 | (*geometry_)[it->patch_].eval(it->llc_(0) + h, it->llc_(1) + h); |
220 |
1/2✓ Branch 3 taken 18533 times.
✗ Branch 4 not taken.
|
18533 | pts.col(it->vertices_[3]) = |
221 |
4/8✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18533 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 18533 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 18533 times.
✗ Branch 16 not taken.
|
37066 | (*geometry_)[it->patch_].eval(it->llc_(0), it->llc_(1) + h); |
222 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18533 times.
|
18533 | if (idct != nullptr) { |
223 | ✗ | ++((*idct)(it->vertices_[0])); | |
224 | ✗ | ++((*idct)(it->vertices_[1])); | |
225 | ✗ | ++((*idct)(it->vertices_[2])); | |
226 | ✗ | ++((*idct)(it->vertices_[3])); | |
227 | } | ||
228 | } | ||
229 | 168 | return pts; | |
230 | ✗ | } | |
231 | ////////////////////////////////////////////////////////////////////////////// | ||
232 | /** | ||
233 | * \brief Return list of elements containing the indices of the vertices. | ||
234 | * | ||
235 | * This function stores all indices of an element in the column of the | ||
236 | * returned matrix. | ||
237 | * | ||
238 | * \return A 4xN integer Matrix where N is the number elements. | ||
239 | */ | ||
240 | Eigen::MatrixXi generateElementList() const { | ||
241 | unsigned int elID = 0; | ||
242 | Eigen::MatrixXi retval(4, number_of_elements_); | ||
243 | for (auto it = pbegin(); it != pend(); ++it) { | ||
244 | retval.col(elID) << it->vertices_[0], it->vertices_[1], it->vertices_[2], | ||
245 | it->vertices_[3]; | ||
246 | ++elID; | ||
247 | } | ||
248 | return retval; | ||
249 | } | ||
250 | ////////////////////////////////////////////////////////////////////////////// | ||
251 | /// getter | ||
252 | ////////////////////////////////////////////////////////////////////////////// | ||
253 | /** | ||
254 | * \brief Return number of points in the ElementTree. | ||
255 | * | ||
256 | * \return Number of points. | ||
257 | */ | ||
258 | int get_number_of_points() const { return number_of_points_; } | ||
259 | /** | ||
260 | * \brief Return number of elements in the ElementTree. | ||
261 | * | ||
262 | * \return Number of elements. | ||
263 | */ | ||
264 | 40 | int get_number_of_elements() const { return number_of_elements_; } | |
265 | /** | ||
266 | * \brief Return maximum level of refinement. | ||
267 | * | ||
268 | * \return Level of refinement. | ||
269 | */ | ||
270 | 2567942 | int get_max_level() const { return max_level_; } | |
271 | /** | ||
272 | * \brief Return reference to the root ElementTreeNode. | ||
273 | * | ||
274 | * \return Reference to the root ElementTreeNode. | ||
275 | */ | ||
276 | ElementTreeNode &root() { return root_; } | ||
277 | /** | ||
278 | * \brief Return const reference to the root ElementTreeNode. | ||
279 | * | ||
280 | * \return Const Reference to the root ElementTreeNode. | ||
281 | */ | ||
282 | 15 | const ElementTreeNode &root() const { return root_; } | |
283 | /** | ||
284 | * \brief Return const reference to the Geometry. | ||
285 | * | ||
286 | * \return Const Reference to the PatchVector. | ||
287 | */ | ||
288 | 99825469 | const PatchVector &get_geometry() const { return *geometry_; } | |
289 | ////////////////////////////////////////////////////////////////////////////// | ||
290 | /// iterators | ||
291 | ////////////////////////////////////////////////////////////////////////////// | ||
292 | /** | ||
293 | * \brief Returns an iterator to the beginning of the sequence represented by | ||
294 | * the leafs as ElementTreeNodes of the ElementTree. | ||
295 | * | ||
296 | * \return Returns a ElementTreeNode::const_iterator object. | ||
297 | */ | ||
298 | 4585 | ElementTreeNode::const_iterator pbegin() const { | |
299 | 4585 | return ElementTreeNode::const_iterator(pfirst_); | |
300 | } | ||
301 | /** | ||
302 | * \brief Returns an iterator one past the end of the sequence represented by | ||
303 | * the leafs as ElementTreeNodes of the ElementTree. | ||
304 | * | ||
305 | * \return Returns a ElementTreeNode::const_iterator object. | ||
306 | */ | ||
307 | 69718 | ElementTreeNode::const_iterator pend() const { | |
308 | 69718 | return ElementTreeNode::const_iterator(plast_->next_); | |
309 | } | ||
310 | /** | ||
311 | * \brief Returns an iterator to the beginning of the sequence represented by | ||
312 | * the leafs as ElementTreeNodes of the ElementTree. | ||
313 | * | ||
314 | * \return Returns a ElementTreeNode::const_iterator object. | ||
315 | */ | ||
316 | 4271 | ElementTreeNode::const_iterator cpbegin() const { return pbegin(); } | |
317 | /** | ||
318 | * \brief Returns an iterator one past the end of the sequence represented by | ||
319 | * the leafs as ElementTreeNodes of the ElementTree. | ||
320 | * | ||
321 | * \return Returns a ElementTreeNode::const_iterator object. | ||
322 | */ | ||
323 | 36851 | ElementTreeNode::const_iterator cpend() const { return pend(); } | |
324 | /** | ||
325 | * \brief Returns a cluster iterator to the beginning of the sequence | ||
326 | * represented by the the given ElementTreeNode. | ||
327 | * | ||
328 | * \param cl Const reference to the ElementTreeNode to start the iterator. | ||
329 | * \return Returns a ElementTreeNode::const_iterator object. | ||
330 | */ | ||
331 | ElementTreeNode::const_iterator cluster_begin( | ||
332 | const ElementTreeNode &cl) const { | ||
333 | return cl.cbegin(); | ||
334 | } | ||
335 | /** | ||
336 | * \brief Returns a cluster iterator one past the end of the sequence | ||
337 | * represented by the the given ElementTreeNode. | ||
338 | * | ||
339 | * \param cl Const reference to the ElementTreeNode to start the iterator. | ||
340 | * \return Returns a ElementTreeNode::const_iterator object. | ||
341 | */ | ||
342 | ElementTreeNode::const_iterator cluster_end(const ElementTreeNode &cl) const { | ||
343 | return cl.cend(); | ||
344 | } | ||
345 | ////////////////////////////////////////////////////////////////////////////// | ||
346 | /** | ||
347 | * \brief Computes enclosing balls surrounding all elements. | ||
348 | * | ||
349 | * This functions sets the parameters midpoint_ radius_ of the ElementTreeNode | ||
350 | * objects stored in the tree. | ||
351 | * | ||
352 | * \return The point list as 3xN matrix with N the number of points. | ||
353 | */ | ||
354 | 168 | Eigen::MatrixXd computeElementEnclosings() { | |
355 | // compute point list | ||
356 | 168 | Eigen::MatrixXd P = generatePointList(); | |
357 |
2/2✓ Branch 1 taken 725 times.
✓ Branch 2 taken 168 times.
|
893 | for (auto i = 0; i < root_.sons_.size(); ++i) |
358 |
1/2✓ Branch 2 taken 725 times.
✗ Branch 3 not taken.
|
725 | computeElementEnclosings_recursion(root_.sons_[i], P); |
359 | 168 | return P; | |
360 | ✗ | } | |
361 | ////////////////////////////////////////////////////////////////////////////// | ||
362 | /** | ||
363 | * \brief Computes enclosing balls of one element and all its sons. | ||
364 | * | ||
365 | * \param el ElementTreeNode to start the recursion. | ||
366 | * \param P Point list of the vertices. | ||
367 | */ | ||
368 | 24469 | void computeElementEnclosings_recursion(ElementTreeNode &el, | |
369 | const Eigen::MatrixXd &P) { | ||
370 |
2/4✓ Branch 1 taken 24469 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24469 times.
✗ Branch 5 not taken.
|
24469 | Eigen::Vector3d mp1, mp2; |
371 | double r1, r2; | ||
372 | // compute point list | ||
373 |
2/2✓ Branch 1 taken 18533 times.
✓ Branch 2 taken 5936 times.
|
24469 | if (!el.sons_.size()) { |
374 | // assign enclosing balls to leafs | ||
375 |
4/8✓ Branch 1 taken 18533 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 18533 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 18533 times.
✗ Branch 12 not taken.
|
18533 | util::computeEnclosingBall(&mp1, &r1, P.col(el.vertices_[0]), 0, |
376 |
1/2✓ Branch 2 taken 18533 times.
✗ Branch 3 not taken.
|
18533 | P.col(el.vertices_[2]), 0); |
377 |
4/8✓ Branch 1 taken 18533 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 18533 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 18533 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 18533 times.
✗ Branch 12 not taken.
|
18533 | util::computeEnclosingBall(&mp2, &r2, P.col(el.vertices_[1]), 0, |
378 |
1/2✓ Branch 2 taken 18533 times.
✗ Branch 3 not taken.
|
18533 | P.col(el.vertices_[3]), 0); |
379 |
1/2✓ Branch 1 taken 18533 times.
✗ Branch 2 not taken.
|
18533 | util::computeEnclosingBall(&(el.midpoint_), &(el.radius_), mp1, r1, mp2, |
380 | r2); | ||
381 | } else { | ||
382 | // handle the four(!!!) children | ||
383 |
2/2✓ Branch 0 taken 23744 times.
✓ Branch 1 taken 5936 times.
|
29680 | for (auto i = 0; i < 4; ++i) |
384 |
1/2✓ Branch 2 taken 23744 times.
✗ Branch 3 not taken.
|
23744 | computeElementEnclosings_recursion(el.sons_[i], P); |
385 | // assign enclosing balls to fathers bottom up | ||
386 |
1/2✓ Branch 2 taken 5936 times.
✗ Branch 3 not taken.
|
5936 | util::computeEnclosingBall(&mp1, &r1, el.sons_[0].midpoint_, |
387 | 5936 | el.sons_[0].radius_, el.sons_[2].midpoint_, | |
388 | 5936 | el.sons_[2].radius_); | |
389 |
1/2✓ Branch 2 taken 5936 times.
✗ Branch 3 not taken.
|
5936 | util::computeEnclosingBall(&mp2, &r2, el.sons_[1].midpoint_, |
390 | 5936 | el.sons_[1].radius_, el.sons_[3].midpoint_, | |
391 | 5936 | el.sons_[3].radius_); | |
392 |
1/2✓ Branch 1 taken 5936 times.
✗ Branch 2 not taken.
|
5936 | util::computeEnclosingBall(&(el.midpoint_), &(el.radius_), mp1, r1, mp2, |
393 | r2); | ||
394 | } | ||
395 | 48938 | return; | |
396 | } | ||
397 | ////////////////////////////////////////////////////////////////////////////// | ||
398 | /** | ||
399 | * \brief Prints all Elements of the Tree. | ||
400 | */ | ||
401 | void printPanels() const { | ||
402 | auto i = 0; | ||
403 | for (auto it = pbegin(); it != pend(); ++it) { | ||
404 | std::cout << "element[" << i++ << "] = "; | ||
405 | it->print(); | ||
406 | } | ||
407 | return; | ||
408 | } | ||
409 | ////////////////////////////////////////////////////////////////////////////// | ||
410 | /// other Stuff | ||
411 | ////////////////////////////////////////////////////////////////////////////// | ||
412 | /** | ||
413 | * \brief Return a matrix with all midpoints of the elements. | ||
414 | * | ||
415 | * \return The midpoint list as 3xN matrix with N the number of points. | ||
416 | */ | ||
417 | Eigen::MatrixXd generateMidpointList() const { | ||
418 | Eigen::MatrixXd retval(3, number_of_elements_); | ||
419 | unsigned int i = 0; | ||
420 | for (auto it = pbegin(); it != pend(); ++it) { | ||
421 | retval.col(i) = it->midpoint_; | ||
422 | ++i; | ||
423 | } | ||
424 | return retval; | ||
425 | } | ||
426 | ////////////////////////////////////////////////////////////////////////////// | ||
427 | /** | ||
428 | * \brief Return a matrix with all radii of the element enclosing. | ||
429 | * | ||
430 | * \return A vector containing the radii of the element enclosing. | ||
431 | */ | ||
432 | Eigen::MatrixXd generateRadiusList() const { | ||
433 | Eigen::VectorXd retval(number_of_elements_); | ||
434 | unsigned int i = 0; | ||
435 | for (auto it = pbegin(); it != pend(); ++it) { | ||
436 | retval(i) = it->radius_; | ||
437 | ++i; | ||
438 | } | ||
439 | return retval; | ||
440 | } | ||
441 | ////////////////////////////////////////////////////////////////////////////// | ||
442 | /** | ||
443 | * \brief Return a vector with computed global indices of the elements. | ||
444 | * | ||
445 | * \return A vector with global indices of the elements. | ||
446 | */ | ||
447 | Eigen::VectorXi generateElementLabels() const { | ||
448 | Eigen::VectorXi retval(number_of_elements_); | ||
449 | unsigned int i = 0; | ||
450 | for (auto it = pbegin(); it != pend(); ++it) { | ||
451 | retval(i) = compute_global_id(*it); | ||
452 | ++i; | ||
453 | } | ||
454 | return retval; | ||
455 | } | ||
456 | ////////////////////////////////////////////////////////////////////////////// | ||
457 | /** | ||
458 | * \brief Generate list of labels if elements are on the patch boundary or at | ||
459 | * the boundary of the geometry. | ||
460 | * | ||
461 | * The value at the index of the element is 1 if the element is at the patch | ||
462 | * boundary and there is a neighbor patch. If there is no neighbor patch then | ||
463 | * the value is -1. | ||
464 | * | ||
465 | * \return A vector of integers of size N with N the number of elements. | ||
466 | */ | ||
467 | Eigen::VectorXi generatePatchBoundaryLabels() const { | ||
468 | Eigen::VectorXi retval(number_of_elements_); | ||
469 | retval.setZero(); | ||
470 | unsigned int i = 0; | ||
471 | for (auto it = pbegin(); it != pend(); ++it) { | ||
472 | for (auto j = 0; j < 4; ++j) | ||
473 | if (it->adjcents_[j] == nullptr) { | ||
474 | retval[i] = -1; | ||
475 | break; | ||
476 | } else if (it->adjcents_[j]->patch_ != it->patch_) { | ||
477 | ++(retval[i]); | ||
478 | } | ||
479 | ++i; | ||
480 | } | ||
481 | return retval; | ||
482 | } | ||
483 | ////////////////////////////////////////////////////////////////////////////// | ||
484 | /** | ||
485 | * \brief Generate list of labels if elements contained within a given patch. | ||
486 | * | ||
487 | * The value at the index of the element is 1 if the element is contained | ||
488 | * within the given patch. Otherwise its zero. | ||
489 | * | ||
490 | * \return A vector of integers of size N with N the number of elements. | ||
491 | */ | ||
492 | Eigen::VectorXi identifyPatch(unsigned int pn) const { | ||
493 | Eigen::VectorXi retval(number_of_elements_); | ||
494 | retval.setZero(); | ||
495 | assert(pn < number_of_patches_); | ||
496 | unsigned int i = 0; | ||
497 | for (auto it = pbegin(); it != pend(); ++it) { | ||
498 | retval[i] = it->patch_ == pn ? 1 : 0; | ||
499 | ++i; | ||
500 | } | ||
501 | return retval; | ||
502 | } | ||
503 | /** | ||
504 | * \brief Resolves neighborhood relations of the patches. | ||
505 | * | ||
506 | * \return A vector where each entry defines a patch interface or boundary. | ||
507 | * The entries correspond to [patchIndex1, edgeCase1, patchIndex2, edgeCase2]. | ||
508 | */ | ||
509 | ////////////////////////////////////////////////////////////////////////////// | ||
510 | 312 | std::vector<std::array<int, 4>> patchTopologyInfo() const { | |
511 | 312 | std::vector<std::array<int, 4>> retval; | |
512 |
2/2✓ Branch 4 taken 1426 times.
✓ Branch 5 taken 312 times.
|
1738 | for (auto it = root_.sons_.begin(); it != root_.sons_.end(); ++it) { |
513 |
2/2✓ Branch 0 taken 5704 times.
✓ Branch 1 taken 1426 times.
|
7130 | for (auto j = 0; j < 4; ++j) { |
514 | // do we have a neighbour? | ||
515 |
2/2✓ Branch 2 taken 2480 times.
✓ Branch 3 taken 3224 times.
|
5704 | if (it->adjcents_[j] != nullptr) { |
516 | 2480 | const ElementTreeNode &cur_neighbour = *(it->adjcents_[j]); | |
517 | // add the edge only if it->id_ < neighbour->id_ | ||
518 | // otherwise the edge has already been added | ||
519 |
2/2✓ Branch 1 taken 1240 times.
✓ Branch 2 taken 1240 times.
|
2480 | if (it->id_ < cur_neighbour.id_) { |
520 | 1240 | int k = 0; | |
521 |
1/2✓ Branch 0 taken 3086 times.
✗ Branch 1 not taken.
|
3086 | for (; k < 4; ++k) |
522 |
4/4✓ Branch 1 taken 1550 times.
✓ Branch 2 taken 1536 times.
✓ Branch 3 taken 1240 times.
✓ Branch 4 taken 1846 times.
|
4636 | if (cur_neighbour.adjcents_[k] != nullptr && |
523 |
2/2✓ Branch 2 taken 1240 times.
✓ Branch 3 taken 310 times.
|
1550 | cur_neighbour.adjcents_[k]->id_ == it->id_) |
524 | 1240 | break; | |
525 |
1/2✓ Branch 2 taken 1240 times.
✗ Branch 3 not taken.
|
1240 | retval.push_back({it->id_, cur_neighbour.id_, j, k}); |
526 | } | ||
527 | } else { | ||
528 |
1/2✓ Branch 2 taken 3224 times.
✗ Branch 3 not taken.
|
3224 | retval.push_back({it->id_, -1, j, -1}); |
529 | } | ||
530 | } | ||
531 | } | ||
532 | 312 | return retval; | |
533 | ✗ | } | |
534 | /** | ||
535 | * \brief The ordering of elements in the element tree does not correspond to | ||
536 | * the element order underlying the coefficient vector. This reordering can be | ||
537 | * computed for look ups by this function. | ||
538 | * | ||
539 | * Limitation to the uniform case! | ||
540 | * | ||
541 | * \return Vector with the tensor product index of the elements. | ||
542 | */ | ||
543 | ////////////////////////////////////////////////////////////////////////////// | ||
544 | 138 | std::vector<int> computeReorderingVector() const { | |
545 |
1/2✓ Branch 2 taken 138 times.
✗ Branch 3 not taken.
|
138 | std::vector<int> out(number_of_elements_); |
546 |
2/2✓ Branch 3 taken 14028 times.
✓ Branch 4 taken 138 times.
|
14166 | for (auto it = pbegin(); it != pend(); ++it) { |
547 | 14028 | const double h = it->get_h(); | |
548 | const Eigen::Vector2d ref_mid = | ||
549 |
3/6✓ Branch 1 taken 14028 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 14028 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 14028 times.
✗ Branch 9 not taken.
|
14028 | it->llc_ + Eigen::Vector2d(.5 * h, .5 * h); |
550 |
1/2✓ Branch 1 taken 14028 times.
✗ Branch 2 not taken.
|
14028 | const int x_idx = std::floor(ref_mid(0) / h); |
551 |
1/2✓ Branch 1 taken 14028 times.
✗ Branch 2 not taken.
|
14028 | const int y_idx = std::floor(ref_mid(1) / h); |
552 | 14028 | const int num_in_one_dir = 1 << max_level_; | |
553 | 14028 | const int num_per_patch = num_in_one_dir * num_in_one_dir; | |
554 | const int tp_idx = | ||
555 | 14028 | it->patch_ * num_per_patch + y_idx * num_in_one_dir + x_idx; | |
556 | 14028 | out[tp_idx] = it->id_; | |
557 | } | ||
558 | 138 | return out; | |
559 | ✗ | } | |
560 | ////////////////////////////////////////////////////////////////////////////// | ||
561 | size_t compute_global_id(const ElementTreeNode &el) const { | ||
562 | return number_of_patches_ * | ||
563 | (((1 << el.level_) * (1 << el.level_) - 1) / 3) + | ||
564 | el.id_; | ||
565 | } | ||
566 | ////////////////////////////////////////////////////////////////////////////// | ||
567 | /// private members | ||
568 | ////////////////////////////////////////////////////////////////////////////// | ||
569 | private: | ||
570 | ////////////////////////////////////////////////////////////////////////////// | ||
571 | /// methods | ||
572 | ////////////////////////////////////////////////////////////////////////////// | ||
573 | template <typename T> | ||
574 | struct isEqual { | ||
575 | bool operator()(const T &v1, const T &v2) const { | ||
576 | return ((v1 - v2).norm() < Constants::pt_comp_tolerance); | ||
577 | } | ||
578 | }; | ||
579 | /** | ||
580 | * \brief function to set up the local topology, i.e. the adjacents | ||
581 | * of a refined element | ||
582 | */ | ||
583 | ////////////////////////////////////////////////////////////////////////////// | ||
584 | 6104 | void updateTopology(const std::vector<ElementTreeNode *> &elements) { | |
585 | 6104 | std::map<std::array<int, 2>, ElementTreeNode *> edges; | |
586 | std::array<int, 2> e1, e2; | ||
587 | // generate edge list for all elements in question | ||
588 |
2/2✓ Branch 1 taken 43541 times.
✓ Branch 2 taken 6104 times.
|
49645 | for (auto i = 0; i < elements.size(); ++i) |
589 |
2/2✓ Branch 0 taken 174164 times.
✓ Branch 1 taken 43541 times.
|
217705 | for (auto j = 0; j < 4; ++j) { |
590 | // compute a unique id for each edge | ||
591 | 174164 | const int v1 = elements[i]->vertices_[j]; | |
592 | 174164 | const int v2 = elements[i]->vertices_[(j + 1) % 4]; | |
593 |
4/4✓ Branch 0 taken 87241 times.
✓ Branch 1 taken 86923 times.
✓ Branch 2 taken 87241 times.
✓ Branch 3 taken 86923 times.
|
174164 | e1 = {v1 < v2 ? v1 : v2, v1 < v2 ? v2 : v1}; |
594 | // perferm a look up if the edge is already existing. | ||
595 |
1/2✓ Branch 1 taken 174164 times.
✗ Branch 2 not taken.
|
174164 | auto it = edges.find(e1); |
596 | // if so, identify the two neighbours | ||
597 |
2/2✓ Branch 2 taken 53060 times.
✓ Branch 3 taken 121104 times.
|
174164 | if (it != edges.end()) { |
598 | 53060 | elements[i]->adjcents_[j] = it->second; | |
599 | // now find the edge also in the patch that added it to the set | ||
600 |
1/2✓ Branch 0 taken 156501 times.
✗ Branch 1 not taken.
|
156501 | for (auto k = 0; k < 4; ++k) { |
601 | 156501 | const int v3 = it->second->vertices_[k]; | |
602 | 156501 | const int v4 = it->second->vertices_[(k + 1) % 4]; | |
603 |
4/4✓ Branch 0 taken 86670 times.
✓ Branch 1 taken 69831 times.
✓ Branch 2 taken 86670 times.
✓ Branch 3 taken 69831 times.
|
156501 | e2 = {v3 < v4 ? v3 : v4, v3 < v4 ? v4 : v3}; |
604 |
3/4✓ Branch 1 taken 156501 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 53060 times.
✓ Branch 4 taken 103441 times.
|
156501 | if (e1 == e2) { |
605 | 53060 | it->second->adjcents_[k] = elements[i]; | |
606 | 53060 | break; | |
607 | } | ||
608 | } | ||
609 | // otherwise add the edge to the list | ||
610 | } else { | ||
611 |
2/4✓ Branch 2 taken 121104 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 121104 times.
✗ Branch 6 not taken.
|
121104 | edges.insert(std::make_pair(e1, elements[i])); |
612 | } | ||
613 | } | ||
614 | 12208 | return; | |
615 | 6104 | } | |
616 | ////////////////////////////////////////////////////////////////////////////// | ||
617 | /** | ||
618 | * \brief This function refines the given ElementTreeNode. | ||
619 | * | ||
620 | * The function introduces 4 new elements and takes care of the newly | ||
621 | * introduces vertices. Furthermore, all the neighborhood relation of all | ||
622 | * surrounding elements are resolved. | ||
623 | */ | ||
624 | 5936 | void refineLeaf(ElementTreeNode &cur_el) { | |
625 | // check if we have actually a panel | ||
626 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5936 times.
|
5936 | if (cur_el.sons_.size()) return; |
627 |
1/2✓ Branch 2 taken 5936 times.
✗ Branch 3 not taken.
|
5936 | std::vector<int> ptIds(5); |
628 |
1/2✓ Branch 2 taken 5936 times.
✗ Branch 3 not taken.
|
5936 | std::vector<int> refNeighbours(4); |
629 | 5936 | std::vector<ElementTreeNode *> elements; | |
630 | // determine position of p with respect to its neighbours | ||
631 |
2/2✓ Branch 0 taken 23744 times.
✓ Branch 1 taken 5936 times.
|
29680 | for (auto i = 0; i < 4; ++i) { |
632 | // is there a neighbour? | ||
633 |
2/2✓ Branch 1 taken 19072 times.
✓ Branch 2 taken 4672 times.
|
23744 | if (cur_el.adjcents_[i] != nullptr) { |
634 |
1/2✓ Branch 0 taken 47680 times.
✗ Branch 1 not taken.
|
47680 | for (auto j = 0; j < 4; ++j) |
635 |
2/2✓ Branch 3 taken 19072 times.
✓ Branch 4 taken 28608 times.
|
47680 | if (cur_el.adjcents_[i]->adjcents_[j] == std::addressof(cur_el)) { |
636 | 19072 | refNeighbours[i] = j; | |
637 | 19072 | break; | |
638 | } | ||
639 | } else { | ||
640 | 4672 | refNeighbours[i] = -1; | |
641 | } | ||
642 | } | ||
643 | // determine new points | ||
644 |
2/2✓ Branch 0 taken 23744 times.
✓ Branch 1 taken 5936 times.
|
29680 | for (auto i = 0; i < 4; ++i) { |
645 | // is there a neighbour? | ||
646 |
2/2✓ Branch 1 taken 19072 times.
✓ Branch 2 taken 4672 times.
|
23744 | if (cur_el.adjcents_[i] != nullptr) { |
647 | 19072 | ElementTreeNode &ref_cur_neighbour = *(cur_el.adjcents_[i]); | |
648 | // is the neighbour already refined? | ||
649 |
2/2✓ Branch 1 taken 9536 times.
✓ Branch 2 taken 9536 times.
|
19072 | if (ref_cur_neighbour.sons_.size()) { |
650 | // this is the midpoint of the shared edge | ||
651 | 19072 | ptIds[i] = ref_cur_neighbour.sons_[refNeighbours[i]] | |
652 | 19072 | .vertices_[(refNeighbours[i] + 1) % 4]; | |
653 | // these are the two elements adjacent to the edge | ||
654 | 9536 | elements.push_back( | |
655 |
1/2✓ Branch 4 taken 9536 times.
✗ Branch 5 not taken.
|
9536 | std::addressof(ref_cur_neighbour.sons_[refNeighbours[i]])); |
656 |
1/2✓ Branch 2 taken 9536 times.
✗ Branch 3 not taken.
|
9536 | elements.push_back(std::addressof( |
657 | 9536 | ref_cur_neighbour.sons_[(refNeighbours[i] + 1) % 4])); | |
658 | } else { | ||
659 | // otherwise add the point id to the tree | ||
660 | 9536 | ptIds[i] = number_of_points_; | |
661 | 9536 | ++number_of_points_; | |
662 | } | ||
663 | } else { | ||
664 | // otherwise add the point id to the tree | ||
665 | 4672 | ptIds[i] = number_of_points_; | |
666 | 4672 | ++number_of_points_; | |
667 | } | ||
668 | } | ||
669 | // add midpoint of the current element, which is always a new point | ||
670 | 5936 | ptIds[4] = number_of_points_; | |
671 | 5936 | ++number_of_points_; | |
672 | // set up new elements | ||
673 |
1/2✓ Branch 1 taken 5936 times.
✗ Branch 2 not taken.
|
5936 | cur_el.sons_.resize(4); |
674 | 5936 | number_of_elements_ += 3; | |
675 | 5936 | max_level_ = | |
676 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5936 times.
|
5936 | max_level_ < cur_el.level_ + 1 ? cur_el.level_ + 1 : max_level_; |
677 | // auto it = leafs_.find(compute_global_id(cur_el)); | ||
678 | // if (it != leafs_.end()) leafs_.erase(it); | ||
679 |
2/2✓ Branch 0 taken 23744 times.
✓ Branch 1 taken 5936 times.
|
29680 | for (auto i = 0; i < 4; ++i) { |
680 | // add linked list structure to the panels | ||
681 | ////////////////////////////////////////////////////////////////////////// | ||
682 |
2/2✓ Branch 0 taken 5936 times.
✓ Branch 1 taken 17808 times.
|
23744 | if (i == 0) { |
683 | 5936 | cur_el.sons_[i].prev_ = cur_el.prev_; | |
684 |
2/2✓ Branch 0 taken 5695 times.
✓ Branch 1 taken 241 times.
|
5936 | if (cur_el.prev_ != nullptr) |
685 | 5695 | (cur_el.prev_)->next_ = std::addressof(cur_el.sons_[i]); | |
686 | 5936 | cur_el.prev_ = nullptr; | |
687 |
2/2✓ Branch 1 taken 241 times.
✓ Branch 2 taken 5695 times.
|
5936 | if (std::addressof(cur_el) == pfirst_) |
688 | 241 | pfirst_ = std::addressof(cur_el.sons_[i]); | |
689 | |||
690 | } else { | ||
691 | 17808 | cur_el.sons_[i].prev_ = std::addressof(cur_el.sons_[i - 1]); | |
692 | } | ||
693 |
2/2✓ Branch 0 taken 5936 times.
✓ Branch 1 taken 17808 times.
|
23744 | if (i == 3) { |
694 | 5936 | cur_el.sons_[i].next_ = cur_el.next_; | |
695 |
2/2✓ Branch 0 taken 5695 times.
✓ Branch 1 taken 241 times.
|
5936 | if (cur_el.next_ != nullptr) |
696 | 5695 | (cur_el.next_)->prev_ = std::addressof(cur_el.sons_[i]); | |
697 | 5936 | cur_el.next_ = nullptr; | |
698 |
2/2✓ Branch 1 taken 241 times.
✓ Branch 2 taken 5695 times.
|
5936 | if (std::addressof(cur_el) == plast_) |
699 | 241 | plast_ = std::addressof(cur_el.sons_[i]); | |
700 | } else { | ||
701 | 17808 | cur_el.sons_[i].next_ = std::addressof(cur_el.sons_[i + 1]); | |
702 | } | ||
703 | ////////////////////////////////////////////////////////////////////////// | ||
704 | 23744 | cur_el.sons_[i].patch_ = cur_el.patch_; | |
705 | 23744 | cur_el.sons_[i].level_ = cur_el.level_ + 1; | |
706 | 23744 | cur_el.sons_[i].id_ = 4 * cur_el.id_ + i; | |
707 |
1/2✓ Branch 2 taken 23744 times.
✗ Branch 3 not taken.
|
23744 | cur_el.sons_[i].adjcents_ = std::vector<ElementTreeNode *>(4, nullptr); |
708 |
1/2✓ Branch 1 taken 23744 times.
✗ Branch 2 not taken.
|
23744 | cur_el.sons_[i].llc_(0) = |
709 |
1/2✓ Branch 1 taken 23744 times.
✗ Branch 2 not taken.
|
23744 | cur_el.llc_(0) + Constants::llcs[0][i] / double(1 << cur_el.level_); |
710 |
1/2✓ Branch 1 taken 23744 times.
✗ Branch 2 not taken.
|
23744 | cur_el.sons_[i].llc_(1) = |
711 |
1/2✓ Branch 1 taken 23744 times.
✗ Branch 2 not taken.
|
23744 | cur_el.llc_(1) + Constants::llcs[1][i] / double(1 << cur_el.level_); |
712 |
1/2✓ Branch 3 taken 23744 times.
✗ Branch 4 not taken.
|
23744 | elements.push_back(std::addressof(cur_el.sons_[i])); |
713 | } | ||
714 | // set vertices | ||
715 | // first element | ||
716 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[0].vertices_.push_back(cur_el.vertices_[0]); |
717 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[0].vertices_.push_back(ptIds[0]); |
718 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[0].vertices_.push_back(ptIds[4]); |
719 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[0].vertices_.push_back(ptIds[3]); |
720 | // second element | ||
721 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[1].vertices_.push_back(ptIds[0]); |
722 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[1].vertices_.push_back(cur_el.vertices_[1]); |
723 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[1].vertices_.push_back(ptIds[1]); |
724 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[1].vertices_.push_back(ptIds[4]); |
725 | // third element | ||
726 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[2].vertices_.push_back(ptIds[4]); |
727 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[2].vertices_.push_back(ptIds[1]); |
728 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[2].vertices_.push_back(cur_el.vertices_[2]); |
729 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[2].vertices_.push_back(ptIds[2]); |
730 | // fourth element | ||
731 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[3].vertices_.push_back(ptIds[3]); |
732 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[3].vertices_.push_back(ptIds[4]); |
733 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[3].vertices_.push_back(ptIds[2]); |
734 |
1/2✓ Branch 3 taken 5936 times.
✗ Branch 4 not taken.
|
5936 | cur_el.sons_[3].vertices_.push_back(cur_el.vertices_[3]); |
735 | // fix adjecency relations | ||
736 |
1/2✓ Branch 1 taken 5936 times.
✗ Branch 2 not taken.
|
5936 | updateTopology(elements); |
737 | |||
738 | 5936 | return; | |
739 | 5936 | } | |
740 | ////////////////////////////////////////////////////////////////////////////// | ||
741 | /// member variables | ||
742 | ////////////////////////////////////////////////////////////////////////////// | ||
743 | std::shared_ptr<PatchVector> geometry_; | ||
744 | ElementTreeNode root_; | ||
745 | ElementTreeNode *pfirst_; | ||
746 | ElementTreeNode *plast_; | ||
747 | int number_of_patches_; | ||
748 | int max_level_; | ||
749 | int number_of_points_; | ||
750 | int number_of_elements_; | ||
751 | ////////////////////////////////////////////////////////////////////////////// | ||
752 | }; | ||
753 | } // namespace Bembel | ||
754 | #endif // BEMBEL_SRC_CLUSTERTREE_ELEMENTTREE_HPP_ | ||
755 |