1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2020 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15
16
17 #include <deal.II/base/geometry_info.h>
18 #include <deal.II/base/memory_consumption.h>
19
20 #include <deal.II/fe/mapping_q1.h>
21
22 #include <deal.II/grid/connectivity.h>
23 #include <deal.II/grid/grid_tools.h>
24 #include <deal.II/grid/magic_numbers.h>
25 #include <deal.II/grid/manifold.h>
26 #include <deal.II/grid/tria.h>
27 #include <deal.II/grid/tria_accessor.h>
28 #include <deal.II/grid/tria_faces.h>
29 #include <deal.II/grid/tria_iterator.h>
30 #include <deal.II/grid/tria_levels.h>
31
32 #include <deal.II/lac/full_matrix.h>
33 #include <deal.II/lac/vector.h>
34
35 #include <algorithm>
36 #include <array>
37 #include <cmath>
38 #include <functional>
39 #include <list>
40 #include <map>
41 #include <memory>
42 #include <numeric>
43
44
45 DEAL_II_NAMESPACE_OPEN
46
47
48 namespace internal
49 {
50 namespace TriangulationImplementation
51 {
NumberCache()52 NumberCache<1>::NumberCache()
53 : n_levels(0)
54 , n_lines(0)
55 , n_active_lines(0)
56 // all other fields are
57 // default constructed
58 {}
59
60
61
62 std::size_t
memory_consumption() const63 NumberCache<1>::memory_consumption() const
64 {
65 return (MemoryConsumption::memory_consumption(n_levels) +
66 MemoryConsumption::memory_consumption(n_lines) +
67 MemoryConsumption::memory_consumption(n_lines_level) +
68 MemoryConsumption::memory_consumption(n_active_lines) +
69 MemoryConsumption::memory_consumption(n_active_lines_level));
70 }
71
72
NumberCache()73 NumberCache<2>::NumberCache()
74 : n_quads(0)
75 , n_active_quads(0)
76 // all other fields are
77 // default constructed
78 {}
79
80
81
82 std::size_t
memory_consumption() const83 NumberCache<2>::memory_consumption() const
84 {
85 return (NumberCache<1>::memory_consumption() +
86 MemoryConsumption::memory_consumption(n_quads) +
87 MemoryConsumption::memory_consumption(n_quads_level) +
88 MemoryConsumption::memory_consumption(n_active_quads) +
89 MemoryConsumption::memory_consumption(n_active_quads_level));
90 }
91
92
93
NumberCache()94 NumberCache<3>::NumberCache()
95 : n_hexes(0)
96 , n_active_hexes(0)
97 // all other fields are
98 // default constructed
99 {}
100
101
102
103 std::size_t
memory_consumption() const104 NumberCache<3>::memory_consumption() const
105 {
106 return (NumberCache<2>::memory_consumption() +
107 MemoryConsumption::memory_consumption(n_hexes) +
108 MemoryConsumption::memory_consumption(n_hexes_level) +
109 MemoryConsumption::memory_consumption(n_active_hexes) +
110 MemoryConsumption::memory_consumption(n_active_hexes_level));
111 }
112 } // namespace TriangulationImplementation
113 } // namespace internal
114
115 // anonymous namespace for internal helper functions
116 namespace
117 {
118 // return whether the given cell is
119 // patch_level_1, i.e. determine
120 // whether either all or none of
121 // its children are further
122 // refined. this function can only
123 // be called for non-active cells.
124 template <int dim, int spacedim>
125 bool
cell_is_patch_level_1(const TriaIterator<dealii::CellAccessor<dim,spacedim>> & cell)126 cell_is_patch_level_1(
127 const TriaIterator<dealii::CellAccessor<dim, spacedim>> &cell)
128 {
129 Assert(cell->is_active() == false, ExcInternalError());
130
131 unsigned int n_active_children = 0;
132 for (unsigned int i = 0; i < cell->n_children(); ++i)
133 if (cell->child(i)->is_active())
134 ++n_active_children;
135
136 return (n_active_children == 0) ||
137 (n_active_children == cell->n_children());
138 }
139
140
141
142 // return, whether a given @p cell will be
143 // coarsened, which is the case if all
144 // children are active and have their coarsen
145 // flag set. In case only part of the coarsen
146 // flags are set, remove them.
147 template <int dim, int spacedim>
148 bool
cell_will_be_coarsened(const TriaIterator<dealii::CellAccessor<dim,spacedim>> & cell)149 cell_will_be_coarsened(
150 const TriaIterator<dealii::CellAccessor<dim, spacedim>> &cell)
151 {
152 // only cells with children should be
153 // considered for coarsening
154
155 if (cell->has_children())
156 {
157 unsigned int children_to_coarsen = 0;
158 const unsigned int n_children = cell->n_children();
159
160 for (unsigned int c = 0; c < n_children; ++c)
161 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
162 ++children_to_coarsen;
163 if (children_to_coarsen == n_children)
164 return true;
165 else
166 for (unsigned int c = 0; c < n_children; ++c)
167 if (cell->child(c)->is_active())
168 cell->child(c)->clear_coarsen_flag();
169 }
170 // no children, so no coarsening
171 // possible. however, no children also
172 // means that this cell will be in the same
173 // state as if it had children and was
174 // coarsened. So, what should we return -
175 // false or true?
176 // make sure we do not have to do this at
177 // all...
178 Assert(cell->has_children(), ExcInternalError());
179 // ... and then simply return false
180 return false;
181 }
182
183
184 // return, whether the face @p face_no of the
185 // given @p cell will be refined after the
186 // current refinement step, considering
187 // refine and coarsen flags and considering
188 // only those refinemnts that will be caused
189 // by the neighboring cell.
190
191 // this function is used on both active cells
192 // and cells with children. on cells with
193 // children it also of interest to know 'how'
194 // the face will be refined. thus there is an
195 // additional third argument @p
196 // expected_face_ref_case returning just
197 // that. be aware, that this variable will
198 // only contain useful information if this
199 // function is called for an active cell.
200 //
201 // thus, this is an internal function, users
202 // should call one of the two alternatives
203 // following below.
204 template <int dim, int spacedim>
205 bool
face_will_be_refined_by_neighbor_internal(const TriaIterator<dealii::CellAccessor<dim,spacedim>> & cell,const unsigned int face_no,RefinementCase<dim-1> & expected_face_ref_case)206 face_will_be_refined_by_neighbor_internal(
207 const TriaIterator<dealii::CellAccessor<dim, spacedim>> &cell,
208 const unsigned int face_no,
209 RefinementCase<dim - 1> &expected_face_ref_case)
210 {
211 // first of all: set the default value for
212 // expected_face_ref_case, which is no
213 // refinement at all
214 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
215
216 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
217 cell->neighbor(face_no);
218
219 // If we are at the boundary, there is no
220 // neighbor which could refine the face
221 if (neighbor.state() != IteratorState::valid)
222 return false;
223
224 if (neighbor->has_children())
225 {
226 // if the neighbor is refined, it may be
227 // coarsened. if so, then it won't refine
228 // the face, no matter what else happens
229 if (cell_will_be_coarsened(neighbor))
230 return false;
231 else
232 // if the neighbor is refined, then it
233 // is also refined at our current
234 // face. He will stay so without
235 // coarsening, so return true in that
236 // case.
237 {
238 expected_face_ref_case = cell->face(face_no)->refinement_case();
239 return true;
240 }
241 }
242
243 // now, the neighbor is not refined, but
244 // perhaps it will be
245 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
246 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
247 {
248 // now we need to know, which of the
249 // neighbors faces points towards us
250 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
251 // check, whether the cell will be
252 // refined in a way that refines our
253 // face
254 const RefinementCase<dim - 1> face_ref_case =
255 GeometryInfo<dim>::face_refinement_case(
256 nb_ref_flag,
257 neighbor_neighbor,
258 neighbor->face_orientation(neighbor_neighbor),
259 neighbor->face_flip(neighbor_neighbor),
260 neighbor->face_rotation(neighbor_neighbor));
261 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
262 {
263 const typename Triangulation<dim, spacedim>::face_iterator
264 neighbor_face = neighbor->face(neighbor_neighbor);
265 const int this_face_index = cell->face_index(face_no);
266
267 // there are still two basic
268 // possibilities here: the neighbor
269 // might be coarser or as coarse
270 // as we are
271 if (neighbor_face->index() == this_face_index)
272 // the neighbor is as coarse as
273 // we are and will be refined at
274 // the face of consideration, so
275 // return true
276 {
277 expected_face_ref_case = face_ref_case;
278 return true;
279 }
280 else
281 {
282 // the neighbor is coarser.
283 // this is the most complicated
284 // case. It might be, that the
285 // neighbor's face will be
286 // refined, but that we will
287 // not see this, as we are
288 // refined in a similar way.
289
290 // so, the neighbor's face must
291 // have children. check, if our
292 // cell's face is one of these
293 // (it could also be a
294 // grand_child)
295 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
296 if (neighbor_face->child_index(c) == this_face_index)
297 {
298 // if the flagged refine
299 // case of the face is a
300 // subset or the same as
301 // the current refine case,
302 // then the face, as seen
303 // from our cell, won't be
304 // refined by the neighbor
305 if ((neighbor_face->refinement_case() | face_ref_case) ==
306 neighbor_face->refinement_case())
307 return false;
308 else
309 {
310 // if we are active, we
311 // must be an
312 // anisotropic child
313 // and the coming
314 // face_ref_case is
315 // isotropic. Thus,
316 // from our cell we
317 // will see exactly the
318 // opposite refine case
319 // that the face has
320 // now...
321 Assert(
322 face_ref_case ==
323 RefinementCase<dim - 1>::isotropic_refinement,
324 ExcInternalError());
325 expected_face_ref_case =
326 ~neighbor_face->refinement_case();
327 return true;
328 }
329 }
330
331 // so, obviously we were not
332 // one of the children, but a
333 // grandchild. This is only
334 // possible in 3d.
335 Assert(dim == 3, ExcInternalError());
336 // In that case, however, no
337 // matter what the neighbor
338 // does, it won't be finer
339 // after the next refinement
340 // step.
341 return false;
342 }
343 } // if face will be refined
344 } // if neighbor is flagged for refinement
345
346 // no cases left, so the neighbor will not
347 // refine the face
348 return false;
349 }
350
351 // version of above function for both active
352 // and non-active cells
353 template <int dim, int spacedim>
354 bool
face_will_be_refined_by_neighbor(const TriaIterator<dealii::CellAccessor<dim,spacedim>> & cell,const unsigned int face_no)355 face_will_be_refined_by_neighbor(
356 const TriaIterator<dealii::CellAccessor<dim, spacedim>> &cell,
357 const unsigned int face_no)
358 {
359 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
360 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
361 }
362
363 // version of above function for active cells
364 // only. Additionally returning the refine
365 // case (to come) of the face under
366 // consideration
367 template <int dim, int spacedim>
368 bool
face_will_be_refined_by_neighbor(const TriaActiveIterator<dealii::CellAccessor<dim,spacedim>> & cell,const unsigned int face_no,RefinementCase<dim-1> & expected_face_ref_case)369 face_will_be_refined_by_neighbor(
370 const TriaActiveIterator<dealii::CellAccessor<dim, spacedim>> &cell,
371 const unsigned int face_no,
372 RefinementCase<dim - 1> &expected_face_ref_case)
373 {
374 return face_will_be_refined_by_neighbor_internal(cell,
375 face_no,
376 expected_face_ref_case);
377 }
378
379
380
381 template <int dim, int spacedim>
382 bool
satisfies_level1_at_vertex_rule(const Triangulation<dim,spacedim> & triangulation)383 satisfies_level1_at_vertex_rule(
384 const Triangulation<dim, spacedim> &triangulation)
385 {
386 std::vector<unsigned int> min_adjacent_cell_level(
387 triangulation.n_vertices(), triangulation.n_levels());
388 std::vector<unsigned int> max_adjacent_cell_level(
389 triangulation.n_vertices(), 0);
390
391 for (const auto &cell : triangulation.active_cell_iterators())
392 for (const unsigned int v : GeometryInfo<dim>::vertex_indices())
393 {
394 min_adjacent_cell_level[cell->vertex_index(v)] =
395 std::min<unsigned int>(
396 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
397 max_adjacent_cell_level[cell->vertex_index(v)] =
398 std::max<unsigned int>(
399 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
400 }
401
402 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
403 if (triangulation.vertex_used(k))
404 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
405 return false;
406 return true;
407 }
408
409
410
411 /**
412 * Fill the vector @p line_cell_count
413 * needed by @p delete_children with the
414 * number of cells bounded by a given
415 * line.
416 */
417 template <int dim, int spacedim>
418 std::vector<unsigned int>
count_cells_bounded_by_line(const Triangulation<dim,spacedim> & triangulation)419 count_cells_bounded_by_line(const Triangulation<dim, spacedim> &triangulation)
420 {
421 if (dim >= 2)
422 {
423 std::vector<unsigned int> line_cell_count(triangulation.n_raw_lines(),
424 0);
425 for (const auto &cell : triangulation.cell_iterators())
426 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
427 ++line_cell_count[cell->line_index(l)];
428 return line_cell_count;
429 }
430 else
431 return std::vector<unsigned int>();
432 }
433
434
435
436 /**
437 * Fill the vector @p quad_cell_count
438 * needed by @p delete_children with the
439 * number of cells bounded by a given
440 * quad.
441 */
442 template <int dim, int spacedim>
443 std::vector<unsigned int>
count_cells_bounded_by_quad(const Triangulation<dim,spacedim> & triangulation)444 count_cells_bounded_by_quad(const Triangulation<dim, spacedim> &triangulation)
445 {
446 if (dim >= 3)
447 {
448 std::vector<unsigned int> quad_cell_count(triangulation.n_raw_quads(),
449 0);
450 for (const auto &cell : triangulation.cell_iterators())
451 for (unsigned int q : GeometryInfo<dim>::face_indices())
452 ++quad_cell_count[cell->quad_index(q)];
453 return quad_cell_count;
454 }
455 else
456 return std::vector<unsigned int>();
457 }
458
459
460
461 /**
462 * A set of three functions that
463 * reorder the data given to
464 * create_triangulation_compatibility
465 * from the "classic" to the
466 * "current" format of vertex
467 * numbering of cells and
468 * faces. These functions do the
469 * reordering of their arguments
470 * in-place.
471 */
472 void
reorder_compatibility(const std::vector<CellData<1>> &,const SubCellData &)473 reorder_compatibility(const std::vector<CellData<1>> &, const SubCellData &)
474 {
475 // nothing to do here: the format
476 // hasn't changed for 1d
477 }
478
479
reorder_compatibility(std::vector<CellData<2>> & cells,const SubCellData &)480 void reorder_compatibility(std::vector<CellData<2>> &cells,
481 const SubCellData &)
482 {
483 for (auto &cell : cells)
484 std::swap(cell.vertices[2], cell.vertices[3]);
485 }
486
487
reorder_compatibility(std::vector<CellData<3>> & cells,SubCellData & subcelldata)488 void reorder_compatibility(std::vector<CellData<3>> &cells,
489 SubCellData & subcelldata)
490 {
491 unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
492 for (auto &cell : cells)
493 {
494 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
495 tmp[i] = cell.vertices[i];
496 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
497 cell.vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
498 }
499
500 // now points in boundary quads
501 std::vector<CellData<2>>::iterator boundary_quad =
502 subcelldata.boundary_quads.begin();
503 std::vector<CellData<2>>::iterator end_quad =
504 subcelldata.boundary_quads.end();
505 for (unsigned int quad_no = 0; boundary_quad != end_quad;
506 ++boundary_quad, ++quad_no)
507 std::swap(boundary_quad->vertices[2], boundary_quad->vertices[3]);
508 }
509
510
511
512 /**
513 * Return the index of the vertex
514 * in the middle of this object,
515 * if it exists. In order to
516 * exist, the object needs to be
517 * refined - for 2D and 3D it
518 * needs to be refined
519 * isotropically or else the
520 * anisotropic children have to
521 * be refined again. If the
522 * middle vertex does not exist,
523 * return
524 * <tt>numbers::invalid_unsigned_int</tt>.
525 *
526 * This function should not really be
527 * used in application programs.
528 */
529 template <int dim, int spacedim>
530 unsigned int
middle_vertex_index(const typename Triangulation<dim,spacedim>::line_iterator & line)531 middle_vertex_index(
532 const typename Triangulation<dim, spacedim>::line_iterator &line)
533 {
534 if (line->has_children())
535 return line->child(0)->vertex_index(1);
536 return numbers::invalid_unsigned_int;
537 }
538
539
540 template <int dim, int spacedim>
541 unsigned int
middle_vertex_index(const typename Triangulation<dim,spacedim>::quad_iterator & quad)542 middle_vertex_index(
543 const typename Triangulation<dim, spacedim>::quad_iterator &quad)
544 {
545 switch (static_cast<unsigned char>(quad->refinement_case()))
546 {
547 case RefinementCase<2>::cut_x:
548 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
549 break;
550 case RefinementCase<2>::cut_y:
551 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
552 break;
553 case RefinementCase<2>::cut_xy:
554 return quad->child(0)->vertex_index(3);
555 break;
556 default:
557 break;
558 }
559 return numbers::invalid_unsigned_int;
560 }
561
562
563 template <int dim, int spacedim>
564 unsigned int
middle_vertex_index(const typename Triangulation<dim,spacedim>::hex_iterator & hex)565 middle_vertex_index(
566 const typename Triangulation<dim, spacedim>::hex_iterator &hex)
567 {
568 switch (static_cast<unsigned char>(hex->refinement_case()))
569 {
570 case RefinementCase<3>::cut_x:
571 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
572 break;
573 case RefinementCase<3>::cut_y:
574 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
575 break;
576 case RefinementCase<3>::cut_z:
577 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
578 break;
579 case RefinementCase<3>::cut_xy:
580 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
581 break;
582 case RefinementCase<3>::cut_xz:
583 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
584 break;
585 case RefinementCase<3>::cut_yz:
586 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
587 break;
588 case RefinementCase<3>::cut_xyz:
589 return hex->child(0)->vertex_index(7);
590 break;
591 default:
592 break;
593 }
594 return numbers::invalid_unsigned_int;
595 }
596
597
598 /**
599 * Collect all coarse mesh cells
600 * with at least one vertex at
601 * which the determinant of the
602 * Jacobian is zero or
603 * negative. This is the function
604 * for the case dim!=spacedim,
605 * where we can not determine
606 * whether a cell is twisted as it
607 * may, for example, discretize a
608 * manifold with a twist.
609 */
610 template <class TRIANGULATION>
611 inline typename TRIANGULATION::DistortedCellList
collect_distorted_coarse_cells(const TRIANGULATION &)612 collect_distorted_coarse_cells(const TRIANGULATION &)
613 {
614 return typename TRIANGULATION::DistortedCellList();
615 }
616
617
618
619 /**
620 * Collect all coarse mesh cells
621 * with at least one vertex at
622 * which the determinant of the
623 * Jacobian is zero or
624 * negative. This is the function
625 * for the case dim==spacedim.
626 */
627 template <int dim>
628 inline typename Triangulation<dim, dim>::DistortedCellList
collect_distorted_coarse_cells(const Triangulation<dim,dim> & triangulation)629 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
630 {
631 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
632 for (const auto &cell : triangulation.cell_iterators_on_level(0))
633 {
634 Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
635 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
636 vertices[i] = cell->vertex(i);
637
638 Tensor<0, dim> determinants[GeometryInfo<dim>::vertices_per_cell];
639 GeometryInfo<dim>::alternating_form_at_vertices(vertices, determinants);
640
641 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
642 if (determinants[i] <= 1e-9 * std::pow(cell->diameter(), 1. * dim))
643 {
644 distorted_cells.distorted_cells.push_back(cell);
645 break;
646 }
647 }
648
649 return distorted_cells;
650 }
651
652
653 /**
654 * Return whether any of the
655 * children of the given cell is
656 * distorted or not. This is the
657 * function for dim==spacedim.
658 */
659 template <int dim>
660 bool
has_distorted_children(const typename Triangulation<dim,dim>::cell_iterator & cell,std::integral_constant<int,dim>,std::integral_constant<int,dim>)661 has_distorted_children(
662 const typename Triangulation<dim, dim>::cell_iterator &cell,
663 std::integral_constant<int, dim>,
664 std::integral_constant<int, dim>)
665 {
666 Assert(cell->has_children(), ExcInternalError());
667
668 for (unsigned int c = 0; c < cell->n_children(); ++c)
669 {
670 Point<dim> vertices[GeometryInfo<dim>::vertices_per_cell];
671 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
672 vertices[i] = cell->child(c)->vertex(i);
673
674 Tensor<0, dim> determinants[GeometryInfo<dim>::vertices_per_cell];
675 GeometryInfo<dim>::alternating_form_at_vertices(vertices, determinants);
676
677 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
678 if (determinants[i] <=
679 1e-9 * std::pow(cell->child(c)->diameter(), 1. * dim))
680 return true;
681 }
682
683 return false;
684 }
685
686
687 /**
688 * Function for dim!=spacedim. As
689 * for
690 * collect_distorted_coarse_cells,
691 * there is nothing that we can do
692 * in this case.
693 */
694 template <int dim, int spacedim>
695 bool
has_distorted_children(const typename Triangulation<dim,spacedim>::cell_iterator &,std::integral_constant<int,dim>,std::integral_constant<int,spacedim>)696 has_distorted_children(
697 const typename Triangulation<dim, spacedim>::cell_iterator &,
698 std::integral_constant<int, dim>,
699 std::integral_constant<int, spacedim>)
700 {
701 return false;
702 }
703
704
705
706 /**
707 * For a given triangulation: set up the
708 * neighbor information on all cells.
709 */
710 template <int spacedim>
update_neighbors(Triangulation<1,spacedim> &)711 void update_neighbors(Triangulation<1, spacedim> &)
712 {}
713
714
715 template <int dim, int spacedim>
716 void
update_neighbors(Triangulation<dim,spacedim> & triangulation)717 update_neighbors(Triangulation<dim, spacedim> &triangulation)
718 {
719 // each face can be neighbored on two sides
720 // by cells. according to the face's
721 // intrinsic normal we define the left
722 // neighbor as the one for which the face
723 // normal points outward, and store that
724 // one first; the second one is then
725 // the right neighbor for which the
726 // face normal points inward. This
727 // information depends on the type of cell
728 // and local number of face for the
729 // 'standard ordering and orientation' of
730 // faces and then on the face_orientation
731 // information for the real mesh. Set up a
732 // table to have fast access to those
733 // offsets (0 for left and 1 for
734 // right). Some of the values are invalid
735 // as they reference too large face
736 // numbers, but we just leave them at a
737 // zero value.
738 //
739 // Note, that in 2d for lines as faces the
740 // normal direction given in the
741 // GeometryInfo class is not consistent. We
742 // thus define here that the normal for a
743 // line points to the right if the line
744 // points upwards.
745 //
746 // There is one more point to
747 // consider, however: if we have
748 // dim<spacedim, then we may have
749 // cases where cells are
750 // inverted. In effect, both
751 // cells think they are the left
752 // neighbor of an edge, for
753 // example, which leads us to
754 // forget neighborship
755 // information (a case that shows
756 // this is
757 // codim_one/hanging_nodes_02). We
758 // store whether a cell is
759 // inverted using the
760 // direction_flag, so if a cell
761 // has a false direction_flag,
762 // then we need to invert our
763 // selection whether we are a
764 // left or right neighbor in all
765 // following computations.
766 //
767 // first index: dimension (minus 2)
768 // second index: local face index
769 // third index: face_orientation (false and true)
770 static const unsigned int left_right_offset[2][6][2] = {
771 // quadrilateral
772 {{0, 1}, // face 0, face_orientation = false and true
773 {1, 0}, // face 1, face_orientation = false and true
774 {1, 0}, // face 2, face_orientation = false and true
775 {0, 1}, // face 3, face_orientation = false and true
776 {0, 0}, // face 4, invalid face
777 {0, 0}}, // face 5, invalid face
778 // hexahedron
779 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
780
781 // now create a vector of the two active
782 // neighbors (left and right) for each face
783 // and fill it by looping over all cells. For
784 // cases with anisotropic refinement and more
785 // then one cell neighboring at a given side
786 // of the face we will automatically get the
787 // active one on the highest level as we loop
788 // over cells from lower levels first.
789 const typename Triangulation<dim, spacedim>::cell_iterator dummy;
790 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
791 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
792
793 for (const auto &cell : triangulation.cell_iterators())
794 for (auto f : GeometryInfo<dim>::face_indices())
795 {
796 const typename Triangulation<dim, spacedim>::face_iterator face =
797 cell->face(f);
798
799 const unsigned int offset =
800 (cell->direction_flag() ?
801 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
802 1 - left_right_offset[dim - 2][f][cell->face_orientation(f)]);
803
804 adjacent_cells[2 * face->index() + offset] = cell;
805
806 // if this cell is not refined, but the
807 // face is, then we'll have to set our
808 // cell as neighbor for the child faces
809 // as well. Fortunately the normal
810 // orientation of children will be just
811 // the same.
812 if (dim == 2)
813 {
814 if (cell->is_active() && face->has_children())
815 {
816 adjacent_cells[2 * face->child(0)->index() + offset] = cell;
817 adjacent_cells[2 * face->child(1)->index() + offset] = cell;
818 }
819 }
820 else // -> dim == 3
821 {
822 // We need the same as in 2d
823 // here. Furthermore, if the face is
824 // refined with cut_x or cut_y then
825 // those children again in the other
826 // direction, and if this cell is
827 // refined isotropically (along the
828 // face) then the neighbor will
829 // (probably) be refined as cut_x or
830 // cut_y along the face. For those
831 // neighboring children cells, their
832 // neighbor will be the current,
833 // inactive cell, as our children are
834 // too fine to be neighbors. Catch that
835 // case by also acting on inactive
836 // cells with isotropic refinement
837 // along the face. If the situation
838 // described is not present, the data
839 // will be overwritten later on when we
840 // visit cells on finer levels, so no
841 // harm will be done.
842 if (face->has_children() &&
843 (cell->is_active() ||
844 GeometryInfo<dim>::face_refinement_case(
845 cell->refinement_case(), f) ==
846 RefinementCase<dim - 1>::isotropic_refinement))
847 {
848 for (unsigned int c = 0; c < face->n_children(); ++c)
849 adjacent_cells[2 * face->child(c)->index() + offset] = cell;
850 if (face->child(0)->has_children())
851 {
852 adjacent_cells[2 * face->child(0)->child(0)->index() +
853 offset] = cell;
854 adjacent_cells[2 * face->child(0)->child(1)->index() +
855 offset] = cell;
856 }
857 if (face->child(1)->has_children())
858 {
859 adjacent_cells[2 * face->child(1)->child(0)->index() +
860 offset] = cell;
861 adjacent_cells[2 * face->child(1)->child(1)->index() +
862 offset] = cell;
863 }
864 } // if cell active and face refined
865 } // else -> dim==3
866 } // for all faces of all cells
867
868 // now loop again over all cells and set the
869 // corresponding neighbor cell. Note, that we
870 // have to use the opposite of the
871 // left_right_offset in this case as we want
872 // the offset of the neighbor, not our own.
873 for (const auto &cell : triangulation.cell_iterators())
874 for (auto f : GeometryInfo<dim>::face_indices())
875 {
876 const unsigned int offset =
877 (cell->direction_flag() ?
878 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
879 1 - left_right_offset[dim - 2][f][cell->face_orientation(f)]);
880 cell->set_neighbor(
881 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
882 }
883 }
884
885
886 template <int dim, int spacedim>
887 void
update_periodic_face_map_recursively(const typename Triangulation<dim,spacedim>::cell_iterator & cell_1,const typename Triangulation<dim,spacedim>::cell_iterator & cell_2,unsigned int n_face_1,unsigned int n_face_2,const std::bitset<3> & orientation,typename std::map<std::pair<typename Triangulation<dim,spacedim>::cell_iterator,unsigned int>,std::pair<std::pair<typename Triangulation<dim,spacedim>::cell_iterator,unsigned int>,std::bitset<3>>> & periodic_face_map)888 update_periodic_face_map_recursively(
889 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
890 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
891 unsigned int n_face_1,
892 unsigned int n_face_2,
893 const std::bitset<3> & orientation,
894 typename std::map<
895 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
896 unsigned int>,
897 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
898 unsigned int>,
899 std::bitset<3>>> &periodic_face_map)
900 {
901 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
902 const FaceIterator face_1 = cell_1->face(n_face_1);
903 const FaceIterator face_2 = cell_2->face(n_face_2);
904
905 const bool face_orientation = orientation[0];
906 const bool face_flip = orientation[1];
907 const bool face_rotation = orientation[2];
908
909 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
910 face_rotation == false),
911 ExcMessage("The supplied orientation "
912 "(face_orientation, face_flip, face_rotation) "
913 "is invalid for 1D"));
914
915 Assert((dim != 2) || (face_orientation == true && face_rotation == false),
916 ExcMessage("The supplied orientation "
917 "(face_orientation, face_flip, face_rotation) "
918 "is invalid for 2D"));
919
920 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
921
922 Assert(face_1->at_boundary() && face_2->at_boundary(),
923 ExcMessage("Periodic faces must be on the boundary"));
924
925 // Check if the requirement that each edge can only have at most one hanging
926 // node, and as a consequence neighboring cells can differ by at most
927 // one refinement level is enforced. In 1d, there are no hanging nodes and
928 // so neighboring cells can differ by more than one refinement level.
929 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
930 ExcInternalError());
931
932 // insert periodic face pair for both cells
933 using CellFace =
934 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
935 unsigned int>;
936 const CellFace cell_face_1(cell_1, n_face_1);
937 const CellFace cell_face_2(cell_2, n_face_2);
938 const std::pair<CellFace, std::bitset<3>> cell_face_orientation_2(
939 cell_face_2, orientation);
940
941 const std::pair<CellFace, std::pair<CellFace, std::bitset<3>>>
942 periodic_faces(cell_face_1, cell_face_orientation_2);
943
944 // Only one periodic neighbor is allowed
945 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
946 periodic_face_map.insert(periodic_faces);
947
948 if (dim == 1)
949 {
950 if (cell_1->has_children())
951 {
952 if (cell_2->has_children())
953 {
954 update_periodic_face_map_recursively<dim, spacedim>(
955 cell_1->child(n_face_1),
956 cell_2->child(n_face_2),
957 n_face_1,
958 n_face_2,
959 orientation,
960 periodic_face_map);
961 }
962 else // only face_1 has children
963 {
964 update_periodic_face_map_recursively<dim, spacedim>(
965 cell_1->child(n_face_1),
966 cell_2,
967 n_face_1,
968 n_face_2,
969 orientation,
970 periodic_face_map);
971 }
972 }
973 }
974 else // dim == 2 || dim == 3
975 {
976 // A lookup table on how to go through the child cells depending on the
977 // orientation:
978 // see Documentation of GeometryInfo for details
979
980 static const int lookup_table_2d[2][2] =
981 // flip:
982 {
983 {0, 1}, // false
984 {1, 0} // true
985 };
986
987 static const int lookup_table_3d[2][2][2][4] =
988 // orientation flip rotation
989 {{{
990 {0, 2, 1, 3}, // false false false
991 {2, 3, 0, 1} // false false true
992 },
993 {
994 {3, 1, 2, 0}, // false true false
995 {1, 0, 3, 2} // false true true
996 }},
997 {{
998 {0, 1, 2, 3}, // true false false
999 {1, 3, 0, 2} // true false true
1000 },
1001 {
1002 {3, 2, 1, 0}, // true true false
1003 {2, 0, 3, 1} // true true true
1004 }}};
1005
1006 if (cell_1->has_children())
1007 {
1008 if (cell_2->has_children())
1009 {
1010 // In the case that both faces have children, we loop over all
1011 // children and apply update_periodic_face_map_recursively
1012 // recursively:
1013
1014 Assert(face_1->n_children() ==
1015 GeometryInfo<dim>::max_children_per_face &&
1016 face_2->n_children() ==
1017 GeometryInfo<dim>::max_children_per_face,
1018 ExcNotImplemented());
1019
1020 for (unsigned int i = 0;
1021 i < GeometryInfo<dim>::max_children_per_face;
1022 ++i)
1023 {
1024 // Lookup the index for the second face
1025 unsigned int j = 0;
1026 switch (dim)
1027 {
1028 case 2:
1029 j = lookup_table_2d[face_flip][i];
1030 break;
1031 case 3:
1032 j = lookup_table_3d[face_orientation][face_flip]
1033 [face_rotation][i];
1034 break;
1035 default:
1036 AssertThrow(false, ExcNotImplemented());
1037 }
1038
1039 // find subcell ids that belong to the subface indices
1040 unsigned int child_cell_1 =
1041 GeometryInfo<dim>::child_cell_on_face(
1042 cell_1->refinement_case(),
1043 n_face_1,
1044 i,
1045 cell_1->face_orientation(n_face_1),
1046 cell_1->face_flip(n_face_1),
1047 cell_1->face_rotation(n_face_1),
1048 face_1->refinement_case());
1049 unsigned int child_cell_2 =
1050 GeometryInfo<dim>::child_cell_on_face(
1051 cell_2->refinement_case(),
1052 n_face_2,
1053 j,
1054 cell_2->face_orientation(n_face_2),
1055 cell_2->face_flip(n_face_2),
1056 cell_2->face_rotation(n_face_2),
1057 face_2->refinement_case());
1058
1059 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1060 face_1->child(i),
1061 ExcInternalError());
1062 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1063 face_2->child(j),
1064 ExcInternalError());
1065
1066 // precondition: subcell has the same orientation as cell
1067 // (so that the face numbers coincide) recursive call
1068 update_periodic_face_map_recursively<dim, spacedim>(
1069 cell_1->child(child_cell_1),
1070 cell_2->child(child_cell_2),
1071 n_face_1,
1072 n_face_2,
1073 orientation,
1074 periodic_face_map);
1075 }
1076 }
1077 else // only face_1 has children
1078 {
1079 for (unsigned int i = 0;
1080 i < GeometryInfo<dim>::max_children_per_face;
1081 ++i)
1082 {
1083 // find subcell ids that belong to the subface indices
1084 unsigned int child_cell_1 =
1085 GeometryInfo<dim>::child_cell_on_face(
1086 cell_1->refinement_case(),
1087 n_face_1,
1088 i,
1089 cell_1->face_orientation(n_face_1),
1090 cell_1->face_flip(n_face_1),
1091 cell_1->face_rotation(n_face_1),
1092 face_1->refinement_case());
1093
1094 // recursive call
1095 update_periodic_face_map_recursively<dim, spacedim>(
1096 cell_1->child(child_cell_1),
1097 cell_2,
1098 n_face_1,
1099 n_face_2,
1100 orientation,
1101 periodic_face_map);
1102 }
1103 }
1104 }
1105 }
1106 }
1107
1108
1109 } // end of anonymous namespace
1110
1111
1112 namespace internal
1113 {
1114 namespace TriangulationImplementation
1115 {
1116 // make sure that if in the following we
1117 // write Triangulation<dim,spacedim>
1118 // we mean the *class*
1119 // dealii::Triangulation, not the
1120 // enclosing namespace
1121 // internal::TriangulationImplementation
1122 using dealii::Triangulation;
1123
1124 /**
1125 * Exception
1126 * @ingroup Exceptions
1127 */
1128 DeclException1(ExcGridHasInvalidCell,
1129 int,
1130 << "Something went wrong when making cell " << arg1
1131 << ". Read the docs and the source code "
1132 << "for more information.");
1133 /**
1134 * Exception
1135 * @ingroup Exceptions
1136 */
1137 DeclException1(ExcInternalErrorOnCell,
1138 int,
1139 << "Something went wrong upon construction of cell "
1140 << arg1);
1141 /**
1142 * A cell was entered which has
1143 * negative measure. In most
1144 * cases, this is due to a wrong
1145 * order of the vertices of the
1146 * cell.
1147 *
1148 * @ingroup Exceptions
1149 */
1150 DeclException1(ExcCellHasNegativeMeasure,
1151 int,
1152 << "Cell " << arg1
1153 << " has negative measure. This typically "
1154 << "indicates some distortion in the cell, or a mistakenly "
1155 << "swapped pair of vertices in the input to "
1156 << "Triangulation::create_triangulation().");
1157 /**
1158 * A cell is created with a
1159 * vertex number exceeding the
1160 * vertex array.
1161 *
1162 * @ingroup Exceptions
1163 */
1164 DeclException3(ExcInvalidVertexIndex,
1165 int,
1166 int,
1167 int,
1168 << "Error while creating cell " << arg1
1169 << ": the vertex index " << arg2 << " must be between 0 and "
1170 << arg3 << ".");
1171 /**
1172 * Exception
1173 * @ingroup Exceptions
1174 */
1175 DeclException2(ExcLineInexistant,
1176 int,
1177 int,
1178 << "While trying to assign a boundary indicator to a line: "
1179 << "the line with end vertices " << arg1 << " and " << arg2
1180 << " does not exist.");
1181 /**
1182 * Exception
1183 * @ingroup Exceptions
1184 */
1185 DeclException4(ExcQuadInexistant,
1186 int,
1187 int,
1188 int,
1189 int,
1190 << "While trying to assign a boundary indicator to a quad: "
1191 << "the quad with bounding lines " << arg1 << ", " << arg2
1192 << ", " << arg3 << ", " << arg4 << " does not exist.");
1193 /**
1194 * Exception
1195 * @ingroup Exceptions
1196 */
1197 DeclException3(
1198 ExcInteriorLineCantBeBoundary,
1199 int,
1200 int,
1201 types::boundary_id,
1202 << "The input data for creating a triangulation contained "
1203 << "information about a line with indices " << arg1 << " and " << arg2
1204 << " that is described to have boundary indicator "
1205 << static_cast<int>(arg3)
1206 << ". However, this is an internal line not located on the "
1207 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1208 << std::endl
1209 << "If this happened at a place where you call "
1210 << "Triangulation::create_triangulation() yourself, you need "
1211 << "to check the SubCellData object you pass to this function."
1212 << std::endl
1213 << std::endl
1214 << "If this happened in a place where you are reading a mesh "
1215 << "from a file, then you need to investigate why such a line "
1216 << "ended up in the input file. A typical case is a geometry "
1217 << "that consisted of multiple parts and for which the mesh "
1218 << "generator program assumes that the interface between "
1219 << "two parts is a boundary when that isn't supposed to be "
1220 << "the case, or where the mesh generator simply assigns "
1221 << "'geometry indicators' to lines at the perimeter of "
1222 << "a part that are not supposed to be interpreted as "
1223 << "'boundary indicators'.");
1224 /**
1225 * Exception
1226 * @ingroup Exceptions
1227 */
1228 DeclException5(
1229 ExcInteriorQuadCantBeBoundary,
1230 int,
1231 int,
1232 int,
1233 int,
1234 types::boundary_id,
1235 << "The input data for creating a triangulation contained "
1236 << "information about a quad with indices " << arg1 << ", " << arg2
1237 << ", " << arg3 << ", and " << arg4
1238 << " that is described to have boundary indicator "
1239 << static_cast<int>(arg5)
1240 << ". However, this is an internal quad not located on the "
1241 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1242 << std::endl
1243 << "If this happened at a place where you call "
1244 << "Triangulation::create_triangulation() yourself, you need "
1245 << "to check the SubCellData object you pass to this function."
1246 << std::endl
1247 << std::endl
1248 << "If this happened in a place where you are reading a mesh "
1249 << "from a file, then you need to investigate why such a quad "
1250 << "ended up in the input file. A typical case is a geometry "
1251 << "that consisted of multiple parts and for which the mesh "
1252 << "generator program assumes that the interface between "
1253 << "two parts is a boundary when that isn't supposed to be "
1254 << "the case, or where the mesh generator simply assigns "
1255 << "'geometry indicators' to quads at the surface of "
1256 << "a part that are not supposed to be interpreted as "
1257 << "'boundary indicators'.");
1258 /**
1259 * Exception
1260 * @ingroup Exceptions
1261 */
1262 DeclException2(
1263 ExcMultiplySetLineInfoOfLine,
1264 int,
1265 int,
1266 << "In SubCellData the line info of the line with vertex indices " << arg1
1267 << " and " << arg2 << " appears more than once. "
1268 << "This is not allowed.");
1269 /**
1270 * Exception
1271 * @ingroup Exceptions
1272 */
1273 DeclException3(
1274 ExcInconsistentLineInfoOfLine,
1275 int,
1276 int,
1277 std::string,
1278 << "In SubCellData the line info of the line with vertex indices " << arg1
1279 << " and " << arg2 << " appears multiple times with different (valid) "
1280 << arg3 << ". This is not allowed.");
1281 /**
1282 * Exception
1283 * @ingroup Exceptions
1284 */
1285 DeclException5(
1286 ExcInconsistentQuadInfoOfQuad,
1287 int,
1288 int,
1289 int,
1290 int,
1291 std::string,
1292 << "In SubCellData the quad info of the quad with line indices " << arg1
1293 << ", " << arg2 << ", " << arg3 << " and " << arg4
1294 << " appears multiple times with different (valid) " << arg5
1295 << ". This is not allowed.");
1296
1297 /*
1298 * Reserve space for TriaFaces. Details:
1299 *
1300 * Reserve space for line_orientations.
1301 *
1302 * @note Used only for dim=3.
1303 */
1304 void
reserve_space(TriaFaces & tria_faces,const unsigned int new_quads_in_pairs,const unsigned int new_quads_single)1305 reserve_space(TriaFaces & tria_faces,
1306 const unsigned int new_quads_in_pairs,
1307 const unsigned int new_quads_single)
1308 {
1309 AssertDimension(tria_faces.dim, 3);
1310
1311 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
1312
1313 unsigned int next_free_single = 0;
1314 unsigned int next_free_pair = 0;
1315
1316 // count the number of objects, of unused single objects and of
1317 // unused pairs of objects
1318 unsigned int n_quads = 0;
1319 unsigned int n_unused_pairs = 0;
1320 unsigned int n_unused_singles = 0;
1321 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
1322 {
1323 if (tria_faces.quads.used[i])
1324 ++n_quads;
1325 else if (i + 1 < tria_faces.quads.used.size())
1326 {
1327 if (tria_faces.quads.used[i + 1])
1328 {
1329 ++n_unused_singles;
1330 if (next_free_single == 0)
1331 next_free_single = i;
1332 }
1333 else
1334 {
1335 ++n_unused_pairs;
1336 if (next_free_pair == 0)
1337 next_free_pair = i;
1338 ++i;
1339 }
1340 }
1341 else
1342 ++n_unused_singles;
1343 }
1344 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
1345 tria_faces.quads.used.size(),
1346 ExcInternalError());
1347
1348 // how many single quads are needed in addition to n_unused_quads?
1349 const int additional_single_quads = new_quads_single - n_unused_singles;
1350
1351 unsigned int new_size =
1352 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
1353 if (additional_single_quads > 0)
1354 new_size += additional_single_quads;
1355
1356 // see above...
1357 if (new_size > tria_faces.quads.n_objects())
1358 {
1359 // reserve the field of the derived class
1360 tria_faces.quads_line_orientations.reserve(
1361 new_size * GeometryInfo<2>::lines_per_cell);
1362 tria_faces.quads_line_orientations.insert(
1363 tria_faces.quads_line_orientations.end(),
1364 new_size * GeometryInfo<2>::lines_per_cell -
1365 tria_faces.quads_line_orientations.size(),
1366 true);
1367
1368 tria_faces.quad_reference_cell_type.reserve(new_size);
1369 tria_faces.quad_reference_cell_type.insert(
1370 tria_faces.quad_reference_cell_type.end(),
1371 new_size - tria_faces.quad_reference_cell_type.size(),
1372 ReferenceCell::Type::Quad);
1373 }
1374 }
1375
1376
1377
1378 /**
1379 * Reserve space for TriaLevel. Details:
1380 *
1381 * Reserve enough space to accommodate @p total_cells cells on this
1382 * level. Since there are no @p used flags on this level, you have to
1383 * give the total number of cells, not only the number of newly to
1384 * accommodate ones, like in the <tt>TriaLevel<N>::reserve_space</tt>
1385 * functions, with <tt>N>0</tt>.
1386 *
1387 * Since the number of neighbors per cell depends on the dimensions, you
1388 * have to pass that additionally.
1389 */
1390
1391 void
reserve_space(TriaLevel & tria_level,const unsigned int total_cells,const unsigned int dimension,const unsigned int space_dimension)1392 reserve_space(TriaLevel & tria_level,
1393 const unsigned int total_cells,
1394 const unsigned int dimension,
1395 const unsigned int space_dimension)
1396 {
1397 // we need space for total_cells cells. Maybe we have more already
1398 // with those cells which are unused, so only allocate new space if
1399 // needed.
1400 //
1401 // note that all arrays should have equal sizes (checked by
1402 // @p{monitor_memory}
1403 if (total_cells > tria_level.refine_flags.size())
1404 {
1405 tria_level.refine_flags.reserve(total_cells);
1406 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
1407 total_cells -
1408 tria_level.refine_flags.size(),
1409 /*RefinementCase::no_refinement=*/0);
1410
1411 tria_level.coarsen_flags.reserve(total_cells);
1412 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
1413 total_cells -
1414 tria_level.coarsen_flags.size(),
1415 false);
1416
1417 tria_level.active_cell_indices.reserve(total_cells);
1418 tria_level.active_cell_indices.insert(
1419 tria_level.active_cell_indices.end(),
1420 total_cells - tria_level.active_cell_indices.size(),
1421 numbers::invalid_unsigned_int);
1422
1423 tria_level.subdomain_ids.reserve(total_cells);
1424 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
1425 total_cells -
1426 tria_level.subdomain_ids.size(),
1427 0);
1428
1429 tria_level.level_subdomain_ids.reserve(total_cells);
1430 tria_level.level_subdomain_ids.insert(
1431 tria_level.level_subdomain_ids.end(),
1432 total_cells - tria_level.level_subdomain_ids.size(),
1433 0);
1434
1435 if (dimension < space_dimension)
1436 {
1437 tria_level.direction_flags.reserve(total_cells);
1438 tria_level.direction_flags.insert(
1439 tria_level.direction_flags.end(),
1440 total_cells - tria_level.direction_flags.size(),
1441 true);
1442 }
1443 else
1444 tria_level.direction_flags.clear();
1445
1446 tria_level.parents.reserve((total_cells + 1) / 2);
1447 tria_level.parents.insert(tria_level.parents.end(),
1448 (total_cells + 1) / 2 -
1449 tria_level.parents.size(),
1450 -1);
1451
1452 tria_level.neighbors.reserve(total_cells * (2 * dimension));
1453 tria_level.neighbors.insert(tria_level.neighbors.end(),
1454 total_cells * (2 * dimension) -
1455 tria_level.neighbors.size(),
1456 std::make_pair(-1, -1));
1457
1458
1459 if (tria_level.dim == 3)
1460 {
1461 tria_level.face_orientations.reserve(
1462 total_cells * GeometryInfo<3>::faces_per_cell);
1463 tria_level.face_orientations.insert(
1464 tria_level.face_orientations.end(),
1465 total_cells * GeometryInfo<3>::faces_per_cell -
1466 tria_level.face_orientations.size(),
1467 true);
1468 }
1469
1470 if (tria_level.dim == 2 || tria_level.dim == 3)
1471 {
1472 tria_level.reference_cell_type.reserve(total_cells);
1473 tria_level.reference_cell_type.insert(
1474 tria_level.reference_cell_type.end(),
1475 total_cells - tria_level.reference_cell_type.size(),
1476 tria_level.dim == 2 ? ReferenceCell::Type::Quad :
1477 ReferenceCell::Type::Hex);
1478 }
1479 }
1480 }
1481
1482
1483
1484 /**
1485 * Exception
1486 */
1487 DeclException2(ExcMemoryInexact,
1488 int,
1489 int,
1490 << "The containers have sizes " << arg1 << " and " << arg2
1491 << ", which is not as expected.");
1492
1493 /**
1494 * Check the memory consistency of the different containers. Should only
1495 * be called with the preprocessor flag @p DEBUG set. The function
1496 * should be called from the functions of the higher TriaLevel classes.
1497 */
1498 void
monitor_memory(const TriaLevel & tria_level,const unsigned int true_dimension)1499 monitor_memory(const TriaLevel & tria_level,
1500 const unsigned int true_dimension)
1501 {
1502 (void)tria_level;
1503 (void)true_dimension;
1504 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
1505 tria_level.neighbors.size(),
1506 ExcMemoryInexact(tria_level.refine_flags.size(),
1507 tria_level.neighbors.size()));
1508 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
1509 tria_level.neighbors.size(),
1510 ExcMemoryInexact(tria_level.coarsen_flags.size(),
1511 tria_level.neighbors.size()));
1512 }
1513
1514
1515
1516 /**
1517 * Reserve space for TriaObjects. Details:
1518 *
1519 * Assert that enough space is allocated to accommodate
1520 * <code>new_objs_in_pairs</code> new objects, stored in pairs, plus
1521 * <code>new_obj_single</code> stored individually. This function does
1522 * not only call <code>vector::reserve()</code>, but does really append
1523 * the needed elements.
1524 *
1525 * In 2D e.g. refined lines have to be stored in pairs, whereas new
1526 * lines in the interior of refined cells can be stored as single lines.
1527 */
1528 void
reserve_space(TriaObjects & tria_objects,const unsigned int new_objects_in_pairs,const unsigned int new_objects_single=0)1529 reserve_space(TriaObjects & tria_objects,
1530 const unsigned int new_objects_in_pairs,
1531 const unsigned int new_objects_single = 0)
1532 {
1533 if (tria_objects.structdim <= 2)
1534 {
1535 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
1536
1537 tria_objects.next_free_single = 0;
1538 tria_objects.next_free_pair = 0;
1539 tria_objects.reverse_order_next_free_single = false;
1540
1541 // count the number of objects, of unused single objects and of
1542 // unused pairs of objects
1543 unsigned int n_objects = 0;
1544 unsigned int n_unused_pairs = 0;
1545 unsigned int n_unused_singles = 0;
1546 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
1547 {
1548 if (tria_objects.used[i])
1549 ++n_objects;
1550 else if (i + 1 < tria_objects.used.size())
1551 {
1552 if (tria_objects.used[i + 1])
1553 {
1554 ++n_unused_singles;
1555 if (tria_objects.next_free_single == 0)
1556 tria_objects.next_free_single = i;
1557 }
1558 else
1559 {
1560 ++n_unused_pairs;
1561 if (tria_objects.next_free_pair == 0)
1562 tria_objects.next_free_pair = i;
1563 ++i;
1564 }
1565 }
1566 else
1567 ++n_unused_singles;
1568 }
1569 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
1570 tria_objects.used.size(),
1571 ExcInternalError());
1572
1573 // how many single objects are needed in addition to
1574 // n_unused_objects?
1575 const int additional_single_objects =
1576 new_objects_single - n_unused_singles;
1577
1578 unsigned int new_size = tria_objects.used.size() +
1579 new_objects_in_pairs - 2 * n_unused_pairs;
1580 if (additional_single_objects > 0)
1581 new_size += additional_single_objects;
1582
1583 // only allocate space if necessary
1584 if (new_size > tria_objects.n_objects())
1585 {
1586 unsigned int faces_per_cell = 1;
1587 unsigned int max_children_per_cell = 1;
1588
1589 if (tria_objects.structdim == 1)
1590 faces_per_cell = GeometryInfo<1>::faces_per_cell;
1591 else if (tria_objects.structdim == 2)
1592 faces_per_cell = GeometryInfo<2>::faces_per_cell;
1593 else if (tria_objects.structdim == 3)
1594 faces_per_cell = GeometryInfo<3>::faces_per_cell;
1595 else
1596 AssertThrow(false, ExcNotImplemented());
1597
1598 if (tria_objects.structdim == 1)
1599 max_children_per_cell = GeometryInfo<1>::max_children_per_cell;
1600 else if (tria_objects.structdim == 2)
1601 max_children_per_cell = GeometryInfo<2>::max_children_per_cell;
1602 else if (tria_objects.structdim == 3)
1603 max_children_per_cell = GeometryInfo<3>::max_children_per_cell;
1604 else
1605 AssertThrow(false, ExcNotImplemented());
1606
1607 tria_objects.cells.reserve(new_size * faces_per_cell);
1608 tria_objects.cells.insert(tria_objects.cells.end(),
1609 (new_size - tria_objects.n_objects()) *
1610 faces_per_cell,
1611 -1);
1612
1613 tria_objects.used.reserve(new_size);
1614 tria_objects.used.insert(tria_objects.used.end(),
1615 new_size - tria_objects.used.size(),
1616 false);
1617
1618 tria_objects.user_flags.reserve(new_size);
1619 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1620 new_size -
1621 tria_objects.user_flags.size(),
1622 false);
1623
1624 const unsigned int factor = max_children_per_cell / 2;
1625 tria_objects.children.reserve(factor * new_size);
1626 tria_objects.children.insert(tria_objects.children.end(),
1627 factor * new_size -
1628 tria_objects.children.size(),
1629 -1);
1630
1631 if (tria_objects.structdim > 1)
1632 {
1633 tria_objects.refinement_cases.reserve(new_size);
1634 tria_objects.refinement_cases.insert(
1635 tria_objects.refinement_cases.end(),
1636 new_size - tria_objects.refinement_cases.size(),
1637 /*RefinementCase::no_refinement=*/0);
1638 }
1639
1640 // first reserve, then resize. Otherwise the std library can
1641 // decide to allocate more entries.
1642 tria_objects.boundary_or_material_id.reserve(new_size);
1643 tria_objects.boundary_or_material_id.resize(new_size);
1644
1645 tria_objects.user_data.reserve(new_size);
1646 tria_objects.user_data.resize(new_size);
1647
1648 tria_objects.manifold_id.reserve(new_size);
1649 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1650 new_size -
1651 tria_objects.manifold_id.size(),
1652 numbers::flat_manifold_id);
1653 }
1654
1655 if (n_unused_singles == 0)
1656 {
1657 tria_objects.next_free_single = new_size - 1;
1658 tria_objects.reverse_order_next_free_single = true;
1659 }
1660 }
1661 else
1662 {
1663 const unsigned int new_hexes = new_objects_in_pairs;
1664
1665 const unsigned int new_size =
1666 new_hexes + std::count(tria_objects.used.begin(),
1667 tria_objects.used.end(),
1668 true);
1669
1670 // see above...
1671 if (new_size > tria_objects.n_objects())
1672 {
1673 unsigned int faces_per_cell = 1;
1674
1675 if (tria_objects.structdim == 1)
1676 faces_per_cell = GeometryInfo<1>::faces_per_cell;
1677 else if (tria_objects.structdim == 2)
1678 faces_per_cell = GeometryInfo<2>::faces_per_cell;
1679 else if (tria_objects.structdim == 3)
1680 faces_per_cell = GeometryInfo<3>::faces_per_cell;
1681 else
1682 AssertThrow(false, ExcNotImplemented());
1683
1684 tria_objects.cells.reserve(new_size * faces_per_cell);
1685 tria_objects.cells.insert(tria_objects.cells.end(),
1686 (new_size - tria_objects.n_objects()) *
1687 faces_per_cell,
1688 -1);
1689
1690 tria_objects.used.reserve(new_size);
1691 tria_objects.used.insert(tria_objects.used.end(),
1692 new_size - tria_objects.used.size(),
1693 false);
1694
1695 tria_objects.user_flags.reserve(new_size);
1696 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1697 new_size -
1698 tria_objects.user_flags.size(),
1699 false);
1700
1701 tria_objects.children.reserve(4 * new_size);
1702 tria_objects.children.insert(tria_objects.children.end(),
1703 4 * new_size -
1704 tria_objects.children.size(),
1705 -1);
1706
1707 // for the following fields, we know exactly how many elements
1708 // we need, so first reserve then resize (resize itself, at least
1709 // with some compiler libraries, appears to round up the size it
1710 // actually reserves)
1711 tria_objects.boundary_or_material_id.reserve(new_size);
1712 tria_objects.boundary_or_material_id.resize(new_size);
1713
1714 tria_objects.manifold_id.reserve(new_size);
1715 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1716 new_size -
1717 tria_objects.manifold_id.size(),
1718 numbers::flat_manifold_id);
1719
1720 tria_objects.user_data.reserve(new_size);
1721 tria_objects.user_data.resize(new_size);
1722
1723 tria_objects.refinement_cases.reserve(new_size);
1724 tria_objects.refinement_cases.insert(
1725 tria_objects.refinement_cases.end(),
1726 new_size - tria_objects.refinement_cases.size(),
1727 /*RefinementCase::no_refinement=*/0);
1728 }
1729 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
1730 }
1731 }
1732
1733
1734
1735 /**
1736 * Check the memory consistency of the different containers. Should only
1737 * be called with the preprocessor flag @p DEBUG set. The function
1738 * should be called from the functions of the higher TriaLevel classes.
1739 */
1740 void
monitor_memory(const TriaObjects & tria_object,const unsigned int)1741 monitor_memory(const TriaObjects &tria_object, const unsigned int)
1742 {
1743 Assert(tria_object.n_objects() == tria_object.used.size(),
1744 ExcMemoryInexact(tria_object.n_objects(),
1745 tria_object.used.size()));
1746 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
1747 ExcMemoryInexact(tria_object.n_objects(),
1748 tria_object.user_flags.size()));
1749 Assert(tria_object.n_objects() ==
1750 tria_object.boundary_or_material_id.size(),
1751 ExcMemoryInexact(tria_object.n_objects(),
1752 tria_object.boundary_or_material_id.size()));
1753 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
1754 ExcMemoryInexact(tria_object.n_objects(),
1755 tria_object.manifold_id.size()));
1756 Assert(tria_object.n_objects() == tria_object.user_data.size(),
1757 ExcMemoryInexact(tria_object.n_objects(),
1758 tria_object.user_data.size()));
1759
1760 if (tria_object.structdim == 1)
1761 {
1762 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
1763 ExcMemoryInexact(tria_object.n_objects(),
1764 tria_object.children.size()));
1765 }
1766 else if (tria_object.structdim == 2)
1767 {
1768 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
1769 ExcMemoryInexact(tria_object.n_objects(),
1770 tria_object.children.size()));
1771 }
1772 else if (tria_object.structdim == 3)
1773 {
1774 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
1775 ExcMemoryInexact(tria_object.n_objects(),
1776 tria_object.children.size()));
1777 }
1778 }
1779
1780 /**
1781 * A class into which we put many of the functions that implement
1782 * functionality of the Triangulation class. The main reason for this
1783 * class is as follows: the majority of the functions in Triangulation
1784 * need to be implemented differently for dim==1, dim==2, and
1785 * dim==3. However, their implementation is largly independent of the
1786 * spacedim template parameter. So we would like to write things like
1787 *
1788 * @code
1789 * template <int spacedim>
1790 * void Triangulation<1,spacedim>::create_triangulation (...) {...}
1791 * @endcode
1792 *
1793 * Unfortunately, C++ doesn't allow this: member functions of class
1794 * templates have to be either not specialized at all, or fully
1795 * specialized. No partial specialization is allowed. One possible
1796 * solution would be to just duplicate the bodies of the functions and
1797 * have equally implemented functions
1798 *
1799 * @code
1800 * template <>
1801 * void Triangulation<1,1>::create_triangulation (...) {...}
1802 *
1803 * template <>
1804 * void Triangulation<1,2>::create_triangulation (...) {...}
1805 * @endcode
1806 *
1807 * but that is clearly an unsatisfactory solution. Rather, what we do
1808 * is introduce the current Implementation class in which we can write
1809 * these functions as member templates over spacedim, i.e. we can have
1810 *
1811 * @code
1812 * template <int dim_, int spacedim_>
1813 * template <int spacedim>
1814 * void Triangulation<dim_,spacedim_>::Implementation::
1815 * create_triangulation (...,
1816 * Triangulation<1,spacedim> &tria ) {...}
1817 * @endcode
1818 *
1819 * The outer template parameters are here unused, only the inner
1820 * ones are of real interest.
1821 *
1822 * One may ask why we put these functions into an class rather
1823 * than an anonymous namespace, for example?
1824 *
1825 * First, these implementation functions need to be friends of the
1826 * Triangulation class. It is simpler to make the entire class a friend
1827 * rather than listing all members of an implementation namespace as
1828 * friends of the Triangulation class (there is no such thing as a "friend
1829 * namespace XXX" directive).
1830 *
1831 * Ideally, we would make this class a member class of the
1832 * Triangulation<dim,spacedim> class, since then our implementation
1833 * functions have immediate access to the alias and static functions of
1834 * the surrounding Triangulation class. I.e., we do not have to write
1835 * "typename Triangulation<dim,spacedim>::active_cell_iterator" but can
1836 * write "active_cell_iterator" right away. This is, in fact, the way it was
1837 * implemented first, but we ran into a bug in gcc4.0:
1838 * @code
1839 * class Triangulation {
1840 * struct Implementation;
1841 * friend class TriaAccessor;
1842 * };
1843 *
1844 * class TriaAccessor {
1845 * struct Implementation;
1846 * friend class Triangulation;
1847 * };
1848 * @endcode
1849 *
1850 * Here, friendship (per C++ standard) is supposed to extend to all members
1851 * of the befriended class, including its 'Implementation' member class. But
1852 * gcc4.0 gets this wrong: the members of Triangulation::Implementation are
1853 * not friends of TriaAccessor and the other way around. Ideally, one would
1854 * fix this by saying
1855 * @code
1856 * class Triangulation {
1857 * struct Implementation;
1858 * friend class TriaAccessor;
1859 * friend class TriaAccessor::Implementation; // **
1860 * };
1861 *
1862 * class TriaAccessor {
1863 * struct Implementation;
1864 * friend class Triangulation;
1865 * friend class Triangulation::Implementation;
1866 * };
1867 * @endcode
1868 * but that's not legal because in ** we don't know yet that TriaAccessor
1869 * has a member class Implementation and so we can't make it a friend. The
1870 * only way forward at this point was to make Implementation a class in the
1871 * internal namespace so that we can forward declare it and make it a friend
1872 * of the respective other outer class -- not quite what we wanted but the
1873 * only way I could see to make it work...
1874 */
1875 struct Implementation
1876 {
1877 /**
1878 * For a given Triangulation, update that part of the number
1879 * cache that relates to lines. For 1d, we have to deal with the
1880 * fact that lines have levels, whereas for higher dimensions
1881 * they do not.
1882 *
1883 * The second argument indicates for how many levels the
1884 * Triangulation has objects, though the highest levels need not
1885 * contain active cells if they have previously all been
1886 * coarsened away.
1887 */
1888 template <int dim, int spacedim>
1889 static void
compute_number_cacheinternal::TriangulationImplementation::Implementation1890 compute_number_cache(
1891 const Triangulation<dim, spacedim> & triangulation,
1892 const unsigned int level_objects,
1893 internal::TriangulationImplementation::NumberCache<1> &number_cache)
1894 {
1895 using line_iterator =
1896 typename Triangulation<dim, spacedim>::line_iterator;
1897
1898 number_cache.n_levels = 0;
1899 if (level_objects > 0)
1900 // find the last level on which there are used cells
1901 for (unsigned int level = 0; level < level_objects; ++level)
1902 if (triangulation.begin(level) != triangulation.end(level))
1903 number_cache.n_levels = level + 1;
1904
1905 // no cells at all?
1906 Assert(number_cache.n_levels > 0, ExcInternalError());
1907
1908 ///////////////////////////////////
1909 // update the number of lines on the different levels in the
1910 // cache
1911 number_cache.n_lines = 0;
1912 number_cache.n_active_lines = 0;
1913
1914 // for 1d, lines have levels so take count the objects per
1915 // level and globally
1916 if (dim == 1)
1917 {
1918 number_cache.n_lines_level.resize(number_cache.n_levels);
1919 number_cache.n_active_lines_level.resize(number_cache.n_levels);
1920
1921 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
1922 {
1923 // count lines on this level
1924 number_cache.n_lines_level[level] = 0;
1925 number_cache.n_active_lines_level[level] = 0;
1926
1927 line_iterator line = triangulation.begin_line(level),
1928 endc =
1929 (level == number_cache.n_levels - 1 ?
1930 line_iterator(triangulation.end_line()) :
1931 triangulation.begin_line(level + 1));
1932 for (; line != endc; ++line)
1933 {
1934 ++number_cache.n_lines_level[level];
1935 if (line->has_children() == false)
1936 ++number_cache.n_active_lines_level[level];
1937 }
1938
1939 // update total number of lines
1940 number_cache.n_lines += number_cache.n_lines_level[level];
1941 number_cache.n_active_lines +=
1942 number_cache.n_active_lines_level[level];
1943 }
1944 }
1945 else
1946 {
1947 // for dim>1, there are no levels for lines
1948 number_cache.n_lines_level.clear();
1949 number_cache.n_active_lines_level.clear();
1950
1951 line_iterator line = triangulation.begin_line(),
1952 endc = triangulation.end_line();
1953 for (; line != endc; ++line)
1954 {
1955 ++number_cache.n_lines;
1956 if (line->has_children() == false)
1957 ++number_cache.n_active_lines;
1958 }
1959 }
1960 }
1961
1962 /**
1963 * For a given Triangulation, update that part of the number
1964 * cache that relates to quads. For 2d, we have to deal with the
1965 * fact that quads have levels, whereas for higher dimensions
1966 * they do not.
1967 *
1968 * The second argument indicates for how many levels the
1969 * Triangulation has objects, though the highest levels need not
1970 * contain active cells if they have previously all been
1971 * coarsened away.
1972 *
1973 * At the beginning of the function, we call the respective
1974 * function to update the number cache for lines.
1975 */
1976 template <int dim, int spacedim>
1977 static void
compute_number_cacheinternal::TriangulationImplementation::Implementation1978 compute_number_cache(
1979 const Triangulation<dim, spacedim> & triangulation,
1980 const unsigned int level_objects,
1981 internal::TriangulationImplementation::NumberCache<2> &number_cache)
1982 {
1983 // update lines and n_levels in number_cache. since we don't
1984 // access any of these numbers, we can do this in the
1985 // background
1986 Threads::Task<void> update_lines = Threads::new_task(
1987 static_cast<
1988 void (*)(const Triangulation<dim, spacedim> &,
1989 const unsigned int,
1990 internal::TriangulationImplementation::NumberCache<1> &)>(
1991 &compute_number_cache<dim, spacedim>),
1992 triangulation,
1993 level_objects,
1994 static_cast<internal::TriangulationImplementation::NumberCache<1> &>(
1995 number_cache));
1996
1997 using quad_iterator =
1998 typename Triangulation<dim, spacedim>::quad_iterator;
1999
2000 ///////////////////////////////////
2001 // update the number of quads on the different levels in the
2002 // cache
2003 number_cache.n_quads = 0;
2004 number_cache.n_active_quads = 0;
2005
2006 // for 2d, quads have levels so take count the objects per
2007 // level and globally
2008 if (dim == 2)
2009 {
2010 // count the number of levels; the function we called above
2011 // on a separate Task for lines also does this and puts it into
2012 // number_cache.n_levels, but this datum may not yet be
2013 // available as we call the function on a separate task
2014 unsigned int n_levels = 0;
2015 if (level_objects > 0)
2016 // find the last level on which there are used cells
2017 for (unsigned int level = 0; level < level_objects; ++level)
2018 if (triangulation.begin(level) != triangulation.end(level))
2019 n_levels = level + 1;
2020
2021 number_cache.n_quads_level.resize(n_levels);
2022 number_cache.n_active_quads_level.resize(n_levels);
2023
2024 for (unsigned int level = 0; level < n_levels; ++level)
2025 {
2026 // count quads on this level
2027 number_cache.n_quads_level[level] = 0;
2028 number_cache.n_active_quads_level[level] = 0;
2029
2030 quad_iterator quad = triangulation.begin_quad(level),
2031 endc =
2032 (level == n_levels - 1 ?
2033 quad_iterator(triangulation.end_quad()) :
2034 triangulation.begin_quad(level + 1));
2035 for (; quad != endc; ++quad)
2036 {
2037 ++number_cache.n_quads_level[level];
2038 if (quad->has_children() == false)
2039 ++number_cache.n_active_quads_level[level];
2040 }
2041
2042 // update total number of quads
2043 number_cache.n_quads += number_cache.n_quads_level[level];
2044 number_cache.n_active_quads +=
2045 number_cache.n_active_quads_level[level];
2046 }
2047 }
2048 else
2049 {
2050 // for dim>2, there are no levels for quads
2051 number_cache.n_quads_level.clear();
2052 number_cache.n_active_quads_level.clear();
2053
2054 quad_iterator quad = triangulation.begin_quad(),
2055 endc = triangulation.end_quad();
2056 for (; quad != endc; ++quad)
2057 {
2058 ++number_cache.n_quads;
2059 if (quad->has_children() == false)
2060 ++number_cache.n_active_quads;
2061 }
2062 }
2063
2064 // wait for the background computation for lines
2065 update_lines.join();
2066 }
2067
2068 /**
2069 * For a given Triangulation, update that part of the number
2070 * cache that relates to hexes. For 3d, we have to deal with the
2071 * fact that hexes have levels, whereas for higher dimensions
2072 * they do not.
2073 *
2074 * The second argument indicates for how many levels the
2075 * Triangulation has objects, though the highest levels need not
2076 * contain active cells if they have previously all been
2077 * coarsened away.
2078 *
2079 * At the end of the function, we call the respective function
2080 * to update the number cache for quads, which will in turn call
2081 * the respective function for lines.
2082 */
2083 template <int dim, int spacedim>
2084 static void
compute_number_cacheinternal::TriangulationImplementation::Implementation2085 compute_number_cache(
2086 const Triangulation<dim, spacedim> & triangulation,
2087 const unsigned int level_objects,
2088 internal::TriangulationImplementation::NumberCache<3> &number_cache)
2089 {
2090 // update quads, lines and n_levels in number_cache. since we
2091 // don't access any of these numbers, we can do this in the
2092 // background
2093 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2094 static_cast<
2095 void (*)(const Triangulation<dim, spacedim> &,
2096 const unsigned int,
2097 internal::TriangulationImplementation::NumberCache<2> &)>(
2098 &compute_number_cache<dim, spacedim>),
2099 triangulation,
2100 level_objects,
2101 static_cast<internal::TriangulationImplementation::NumberCache<2> &>(
2102 number_cache));
2103
2104 using hex_iterator =
2105 typename Triangulation<dim, spacedim>::hex_iterator;
2106
2107 ///////////////////////////////////
2108 // update the number of hexes on the different levels in the
2109 // cache
2110 number_cache.n_hexes = 0;
2111 number_cache.n_active_hexes = 0;
2112
2113 // for 3d, hexes have levels so take count the objects per
2114 // level and globally
2115 if (dim == 3)
2116 {
2117 // count the number of levels; the function we called
2118 // above on a separate Task for quads (recursively, via
2119 // the lines function) also does this and puts it into
2120 // number_cache.n_levels, but this datum may not yet be
2121 // available as we call the function on a separate task
2122 unsigned int n_levels = 0;
2123 if (level_objects > 0)
2124 // find the last level on which there are used cells
2125 for (unsigned int level = 0; level < level_objects; ++level)
2126 if (triangulation.begin(level) != triangulation.end(level))
2127 n_levels = level + 1;
2128
2129 number_cache.n_hexes_level.resize(n_levels);
2130 number_cache.n_active_hexes_level.resize(n_levels);
2131
2132 for (unsigned int level = 0; level < n_levels; ++level)
2133 {
2134 // count hexes on this level
2135 number_cache.n_hexes_level[level] = 0;
2136 number_cache.n_active_hexes_level[level] = 0;
2137
2138 hex_iterator hex = triangulation.begin_hex(level),
2139 endc = (level == n_levels - 1 ?
2140 hex_iterator(triangulation.end_hex()) :
2141 triangulation.begin_hex(level + 1));
2142 for (; hex != endc; ++hex)
2143 {
2144 ++number_cache.n_hexes_level[level];
2145 if (hex->has_children() == false)
2146 ++number_cache.n_active_hexes_level[level];
2147 }
2148
2149 // update total number of hexes
2150 number_cache.n_hexes += number_cache.n_hexes_level[level];
2151 number_cache.n_active_hexes +=
2152 number_cache.n_active_hexes_level[level];
2153 }
2154 }
2155 else
2156 {
2157 // for dim>3, there are no levels for hexes
2158 number_cache.n_hexes_level.clear();
2159 number_cache.n_active_hexes_level.clear();
2160
2161 hex_iterator hex = triangulation.begin_hex(),
2162 endc = triangulation.end_hex();
2163 for (; hex != endc; ++hex)
2164 {
2165 ++number_cache.n_hexes;
2166 if (hex->has_children() == false)
2167 ++number_cache.n_active_hexes;
2168 }
2169 }
2170
2171 // wait for the background computation for quads
2172 update_quads_and_lines.join();
2173 }
2174
2175
2176 /**
2177 * Create a triangulation from given data.
2178 */
2179 template <int dim, int spacedim>
2180 static void
create_triangulationinternal::TriangulationImplementation::Implementation2181 create_triangulation(const std::vector<Point<spacedim>> &vertices,
2182 const std::vector<CellData<dim>> & cells,
2183 const SubCellData & subcelldata,
2184 Triangulation<dim, spacedim> & tria)
2185 {
2186 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
2187 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
2188
2189 // Check that all cells have positive volume.
2190 #ifndef _MSC_VER
2191 // TODO: The following code does not compile with MSVC. Find a way
2192 // around it
2193 if (dim == spacedim)
2194 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
2195 {
2196 // If we should check for distorted cells, then we permit them
2197 // to exist. If a cell has negative measure, then it must be
2198 // distorted (the converse is not necessarily true); hence
2199 // throw an exception if no such cells should exist.
2200 if (tria.check_for_distorted_cells)
2201 {
2202 const double cell_measure = GridTools::cell_measure<spacedim>(
2203 vertices,
2204 ArrayView<const unsigned int>(cells[cell_no].vertices));
2205 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
2206 }
2207 }
2208 #endif
2209
2210 // clear old content
2211 tria.levels.clear();
2212 tria.levels.push_back(
2213 std::make_unique<
2214 dealii::internal::TriangulationImplementation::TriaLevel>(dim));
2215
2216 if (dim > 1)
2217 tria.faces = std::make_unique<
2218 dealii::internal::TriangulationImplementation::TriaFaces>(dim);
2219
2220 // copy vertices
2221 tria.vertices = vertices;
2222 tria.vertices_used.assign(vertices.size(), true);
2223
2224 // compute connectivity
2225 const auto connectivity = build_connectivity<unsigned int>(cells);
2226 const unsigned int n_cell = cells.size();
2227
2228 // TriaObjects: lines
2229 if (dim >= 2)
2230 {
2231 auto &lines_0 = tria.faces->lines; // data structure to be filled
2232
2233 // get connectivity between quads and lines
2234 const auto & crs = connectivity.entity_to_entities(1, 0);
2235 const unsigned int n_lines = crs.ptr.size() - 1;
2236
2237 // allocate memory
2238 reserve_space_(lines_0, n_lines);
2239
2240 // loop over lines
2241 for (unsigned int line = 0; line < n_lines; ++line)
2242 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
2243 ++i, ++j)
2244 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
2245 crs.col[i]; // set vertex indices
2246 }
2247
2248 // TriaObjects: quads
2249 if (dim == 3)
2250 {
2251 auto &quads_0 = tria.faces->quads; // data structures to be filled
2252 auto &faces = *tria.faces;
2253
2254 // get connectivity between quads and lines
2255 const auto & crs = connectivity.entity_to_entities(2, 1);
2256 const unsigned int n_quads = crs.ptr.size() - 1;
2257
2258 // allocate memory
2259 reserve_space_(quads_0, n_quads);
2260 reserve_space_(faces, 2 /*structdim*/, n_quads);
2261
2262 // loop over all quads -> entity type, line indices/orientations
2263 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
2264 {
2265 // set entity type of quads
2266 faces.quad_reference_cell_type[q] =
2267 connectivity.entity_types(2)[q];
2268
2269 // loop over all its lines
2270 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
2271 ++i, ++j, ++k)
2272 {
2273 // set line index
2274 quads_0.cells[q * GeometryInfo<2>::faces_per_cell + j] =
2275 crs.col[i];
2276
2277 // set line orientations
2278 faces.quads_line_orientations
2279 [q * GeometryInfo<2>::faces_per_cell + j] =
2280 connectivity.entity_orientations(1)[k];
2281 }
2282 }
2283 }
2284
2285 // TriaObjects/TriaLevel: cell
2286 {
2287 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
2288 auto &level = *tria.levels[0];
2289
2290 // get connectivity between cells/faces and cells/cells
2291 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2292 const auto &nei = connectivity.entity_to_entities(dim, dim);
2293
2294 // in 2D optional: since in in pure QUAD meshes same line
2295 // orientations can be guaranteed
2296 const bool orientation_needed =
2297 dim == 3 ||
2298 (dim == 2 &&
2299 std::any_of(connectivity.entity_orientations(1).begin(),
2300 connectivity.entity_orientations(1).end(),
2301 [](const auto &i) { return i == 0; }));
2302
2303 // allocate memory
2304 reserve_space_(cells_0, n_cell);
2305 reserve_space_(level, spacedim, n_cell, orientation_needed);
2306
2307 // loop over all cells
2308 for (unsigned int cell = 0; cell < n_cell; ++cell)
2309 {
2310 // set material ids
2311 cells_0.boundary_or_material_id[cell].material_id =
2312 cells[cell].material_id;
2313
2314 // set manifold ids
2315 cells_0.manifold_id[cell] = cells[cell].manifold_id;
2316
2317 // set entity types
2318 level.reference_cell_type[cell] =
2319 connectivity.entity_types(dim)[cell];
2320
2321 // loop over faces
2322 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2323 ++i, ++j)
2324 {
2325 // set neighbor if not at boundary
2326 if (nei.col[i] != static_cast<unsigned int>(-1))
2327 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
2328 j] = {0, nei.col[i]};
2329
2330 // set face indices
2331 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
2332 crs.col[i];
2333
2334 // set face orientation if needed
2335 if (orientation_needed)
2336 level.face_orientations
2337 [cell * GeometryInfo<dim>::faces_per_cell + j] =
2338 connectivity.entity_orientations(dim - 1)[i];
2339 }
2340 }
2341 }
2342
2343 // TriaFaces: boundary id of boundary faces
2344 if (dim > 1)
2345 {
2346 auto &bids_face = dim == 3 ?
2347 tria.faces->quads.boundary_or_material_id :
2348 tria.faces->lines.boundary_or_material_id;
2349
2350 // count number of cells a face is belonging to
2351 std::vector<unsigned int> count(bids_face.size(), 0);
2352
2353 // get connectivity between cells/faces
2354 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2355
2356 // count how many cells are adjacent to the same face
2357 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2358 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
2359 count[crs.col[i]]++;
2360
2361 // loop over all faces
2362 for (unsigned int face = 0; face < count.size(); ++face)
2363 {
2364 if (count[face] != 1) // inner face
2365 continue;
2366
2367 // boundary faces ...
2368 bids_face[face].boundary_id = 0;
2369
2370 if (dim != 3)
2371 continue;
2372
2373 // ... and the lines of quads in 3D
2374 const auto &crs = connectivity.entity_to_entities(2, 1);
2375 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
2376 tria.faces->lines.boundary_or_material_id[crs.col[i]]
2377 .boundary_id = 0;
2378 }
2379 }
2380 else // 1D
2381 {
2382 static const unsigned int t_tba = static_cast<unsigned int>(-1);
2383 static const unsigned int t_inner = static_cast<unsigned int>(-2);
2384
2385 std::vector<unsigned int> type(vertices.size(), t_tba);
2386
2387 const auto &crs = connectivity.entity_to_entities(1, 0);
2388
2389 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2390 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2391 ++i, ++j)
2392 if (type[crs.col[i]] != t_inner)
2393 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
2394
2395 for (unsigned int face = 0; face < type.size(); ++face)
2396 {
2397 // note: we also treat manifolds here!?
2398 (*tria.vertex_to_manifold_id_map_1d)[face] =
2399 numbers::flat_manifold_id;
2400 if (type[face] != t_inner && type[face] != t_tba)
2401 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
2402 }
2403 }
2404
2405 // SubCellData: line
2406 if (dim >= 2)
2407 process_subcelldata(connectivity.entity_to_entities(1, 0),
2408 tria.faces->lines,
2409 subcelldata.boundary_lines);
2410
2411 // SubCellData: quad
2412 if (dim == 3)
2413 process_subcelldata(connectivity.entity_to_entities(2, 0),
2414 tria.faces->quads,
2415 subcelldata.boundary_quads);
2416 }
2417
2418
2419 template <int structdim, typename T>
2420 static void
process_subcelldatainternal::TriangulationImplementation::Implementation2421 process_subcelldata(
2422 const CRS<T> & crs,
2423 TriaObjects & obj,
2424 const std::vector<CellData<structdim>> &boundary_objects_in)
2425 {
2426 AssertDimension(obj.structdim, structdim);
2427
2428 if (boundary_objects_in.size() == 0)
2429 return; // empty subcelldata -> nothing to do
2430
2431 // pre-sort subcelldata
2432 auto boundary_objects = boundary_objects_in;
2433
2434 // ... sort vertices
2435 for (auto &boundary_object : boundary_objects)
2436 std::sort(boundary_object.vertices.begin(),
2437 boundary_object.vertices.end());
2438
2439 // ... sort cells
2440 std::sort(boundary_objects.begin(),
2441 boundary_objects.end(),
2442 [](const auto &a, const auto &b) {
2443 return a.vertices < b.vertices;
2444 });
2445
2446 unsigned int counter = 0;
2447
2448 std::vector<unsigned int> key;
2449 key.reserve(GeometryInfo<structdim>::vertices_per_cell);
2450
2451 for (unsigned int o = 0; o < obj.n_objects(); ++o)
2452 {
2453 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
2454 auto &manifold_id = obj.manifold_id[o];
2455
2456 // assert that object has not been visited yet and its value
2457 // has not been modified yet
2458 AssertThrow(boundary_id == 0 ||
2459 boundary_id == numbers::internal_face_boundary_id,
2460 ExcNotImplemented());
2461 AssertThrow(manifold_id == numbers::flat_manifold_id,
2462 ExcNotImplemented());
2463
2464 // create key
2465 key.assign(crs.col.data() + crs.ptr[o],
2466 crs.col.data() + crs.ptr[o + 1]);
2467 std::sort(key.begin(), key.end());
2468
2469 // is subcelldata provided? -> binary search
2470 const auto subcell_object =
2471 std::lower_bound(boundary_objects.begin(),
2472 boundary_objects.end(),
2473 key,
2474 [&](const auto &cell, const auto &key) {
2475 return cell.vertices < key;
2476 });
2477
2478 // no subcelldata provided for this object
2479 if (subcell_object == boundary_objects.end() ||
2480 subcell_object->vertices != key)
2481 continue;
2482
2483 counter++;
2484
2485 // set manifold id
2486 manifold_id = subcell_object->manifold_id;
2487
2488 // set boundary id
2489 if (subcell_object->boundary_id !=
2490 numbers::internal_face_boundary_id)
2491 {
2492 AssertThrow(boundary_id != numbers::internal_face_boundary_id,
2493 ExcNotImplemented());
2494 boundary_id = subcell_object->boundary_id;
2495 }
2496 }
2497
2498 // make sure that all subcelldata entries have been processed
2499 // TODO: this is not guaranteed, why?
2500 // AssertDimension(counter, boundary_objects_in.size());
2501 }
2502
2503
2504
2505 static void
reserve_space_internal::TriangulationImplementation::Implementation2506 reserve_space_(TriaFaces & faces,
2507 const unsigned structdim,
2508 const unsigned int size)
2509 {
2510 const unsigned int dim = faces.dim;
2511
2512 const unsigned int faces_per_cell =
2513 structdim == 1 ? GeometryInfo<1>::faces_per_cell :
2514 (structdim == 2 ? GeometryInfo<2>::faces_per_cell :
2515 GeometryInfo<3>::faces_per_cell);
2516
2517 if (dim == 3 && structdim == 2)
2518 {
2519 // quad entity types
2520 faces.quad_reference_cell_type.assign(size,
2521 ReferenceCell::Type::Invalid);
2522
2523 // quad line orientations
2524 faces.quads_line_orientations.assign(size * faces_per_cell, -1);
2525 }
2526 }
2527
2528
2529
2530 static void
reserve_space_internal::TriangulationImplementation::Implementation2531 reserve_space_(TriaLevel & level,
2532 const unsigned int spacedim,
2533 const unsigned int size,
2534 const bool orientation_needed)
2535 {
2536 const unsigned int dim = level.dim;
2537
2538 const unsigned int faces_per_cell =
2539 dim == 1 ? GeometryInfo<1>::faces_per_cell :
2540 (dim == 2 ? GeometryInfo<2>::faces_per_cell :
2541 GeometryInfo<3>::faces_per_cell);
2542
2543 level.active_cell_indices.assign(size, -1);
2544 level.subdomain_ids.assign(size, 0);
2545 level.level_subdomain_ids.assign(size, 0);
2546
2547 level.refine_flags.assign(size, false);
2548 level.coarsen_flags.assign(size, false);
2549
2550 level.parents.assign((size + 1) / 2, -1);
2551
2552 if (dim < spacedim)
2553 level.direction_flags.assign(size, true);
2554
2555 level.neighbors.assign(size * faces_per_cell, {-1, -1});
2556
2557 level.reference_cell_type.assign(size, ReferenceCell::Type::Invalid);
2558
2559 if (orientation_needed)
2560 level.face_orientations.assign(size * faces_per_cell, -1);
2561 }
2562
2563
2564
2565 static void
reserve_space_internal::TriangulationImplementation::Implementation2566 reserve_space_(TriaObjects &obj, const unsigned int size)
2567 {
2568 const unsigned int structdim = obj.structdim;
2569
2570 const unsigned int max_children_per_cell =
2571 structdim == 1 ?
2572 GeometryInfo<1>::max_children_per_cell :
2573 (structdim == 2 ? GeometryInfo<2>::max_children_per_cell :
2574 GeometryInfo<3>::max_children_per_cell);
2575 const unsigned int faces_per_cell =
2576 structdim == 1 ? GeometryInfo<1>::faces_per_cell :
2577 (structdim == 2 ? GeometryInfo<2>::faces_per_cell :
2578 GeometryInfo<3>::faces_per_cell);
2579
2580 obj.used.assign(size, true);
2581 obj.boundary_or_material_id.assign(
2582 size,
2583 internal::TriangulationImplementation::TriaObjects::
2584 BoundaryOrMaterialId());
2585 obj.manifold_id.assign(size, -1);
2586 obj.user_flags.assign(size, false);
2587 obj.user_data.resize(size);
2588
2589 if (structdim > 1) // TODO: why?
2590 obj.refinement_cases.assign(size, 0);
2591
2592 obj.children.assign(max_children_per_cell / 2 * size, -1);
2593
2594 obj.cells.assign(faces_per_cell * size, -1);
2595
2596 if (structdim <= 2)
2597 {
2598 obj.next_free_single = size - 1;
2599 obj.next_free_pair = 0;
2600 obj.reverse_order_next_free_single = true;
2601 }
2602 else
2603 {
2604 obj.next_free_single = obj.next_free_pair = 0;
2605 }
2606 }
2607
2608
2609 /**
2610 * Actually delete a cell, or rather all
2611 * its children, which is the main step for
2612 * the coarsening process. This is the
2613 * dimension dependent part of @p
2614 * execute_coarsening. The second argument
2615 * is a vector which gives for each line
2616 * index the number of cells containing
2617 * this line. This information is needed to
2618 * decide whether a refined line may be
2619 * coarsened or not in 3D. In 1D and 2D
2620 * this argument is not needed and thus
2621 * ignored. The same applies for the last
2622 * argument and quads instead of lines.
2623 */
2624 template <int spacedim>
delete_childreninternal::TriangulationImplementation::Implementation2625 static void delete_children(
2626 Triangulation<1, spacedim> & triangulation,
2627 typename Triangulation<1, spacedim>::cell_iterator &cell,
2628 std::vector<unsigned int> &,
2629 std::vector<unsigned int> &)
2630 {
2631 const unsigned int dim = 1;
2632
2633 // first we need to reset the
2634 // neighbor pointers of the
2635 // neighbors of this cell's
2636 // children to this cell. This is
2637 // different for one dimension,
2638 // since there neighbors can have a
2639 // refinement level differing from
2640 // that of this cell's children by
2641 // more than one level.
2642
2643 Assert(!cell->child(0)->has_children() &&
2644 !cell->child(1)->has_children(),
2645 ExcInternalError());
2646
2647 // first do it for the cells to the
2648 // left
2649 if (cell->neighbor(0).state() == IteratorState::valid)
2650 if (cell->neighbor(0)->has_children())
2651 {
2652 typename Triangulation<dim, spacedim>::cell_iterator neighbor =
2653 cell->neighbor(0);
2654 Assert(neighbor->level() == cell->level(), ExcInternalError());
2655
2656 // right child
2657 neighbor = neighbor->child(1);
2658 while (true)
2659 {
2660 Assert(neighbor->neighbor(1) == cell->child(0),
2661 ExcInternalError());
2662 neighbor->set_neighbor(1, cell);
2663
2664 // move on to further
2665 // children on the
2666 // boundary between this
2667 // cell and its neighbor
2668 if (neighbor->has_children())
2669 neighbor = neighbor->child(1);
2670 else
2671 break;
2672 }
2673 }
2674
2675 // now do it for the cells to the
2676 // left
2677 if (cell->neighbor(1).state() == IteratorState::valid)
2678 if (cell->neighbor(1)->has_children())
2679 {
2680 typename Triangulation<dim, spacedim>::cell_iterator neighbor =
2681 cell->neighbor(1);
2682 Assert(neighbor->level() == cell->level(), ExcInternalError());
2683
2684 // left child
2685 neighbor = neighbor->child(0);
2686 while (true)
2687 {
2688 Assert(neighbor->neighbor(0) == cell->child(1),
2689 ExcInternalError());
2690 neighbor->set_neighbor(0, cell);
2691
2692 // move on to further
2693 // children on the
2694 // boundary between this
2695 // cell and its neighbor
2696 if (neighbor->has_children())
2697 neighbor = neighbor->child(0);
2698 else
2699 break;
2700 }
2701 }
2702
2703
2704 // delete the vertex which will not
2705 // be needed anymore. This vertex
2706 // is the second of the first child
2707 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
2708
2709 // invalidate children. clear user
2710 // pointers, to avoid that they may
2711 // appear at unwanted places later
2712 // on...
2713 for (unsigned int child = 0; child < cell->n_children(); ++child)
2714 {
2715 cell->child(child)->clear_user_data();
2716 cell->child(child)->clear_user_flag();
2717 cell->child(child)->clear_used_flag();
2718 }
2719
2720
2721 // delete pointer to children
2722 cell->clear_children();
2723 cell->clear_user_flag();
2724 }
2725
2726
2727
2728 template <int spacedim>
delete_childreninternal::TriangulationImplementation::Implementation2729 static void delete_children(
2730 Triangulation<2, spacedim> & triangulation,
2731 typename Triangulation<2, spacedim>::cell_iterator &cell,
2732 std::vector<unsigned int> & line_cell_count,
2733 std::vector<unsigned int> &)
2734 {
2735 const unsigned int dim = 2;
2736 const RefinementCase<dim> ref_case = cell->refinement_case();
2737
2738 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2739 ExcInternalError());
2740
2741 // vectors to hold all lines which
2742 // may be deleted
2743 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2744 lines_to_delete(0);
2745
2746 lines_to_delete.reserve(4 * 2 + 4);
2747
2748 // now we decrease the counters for
2749 // lines contained in the child
2750 // cells
2751 for (unsigned int c = 0; c < cell->n_children(); ++c)
2752 {
2753 typename Triangulation<dim, spacedim>::cell_iterator child =
2754 cell->child(c);
2755 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
2756 --line_cell_count[child->line_index(l)];
2757 }
2758
2759
2760 // delete the vertex which will not
2761 // be needed anymore. This vertex
2762 // is the second of the second line
2763 // of the first child, if the cell
2764 // is refined with cut_xy, else there
2765 // is no inner vertex.
2766 // additionally delete unneeded inner
2767 // lines
2768 if (ref_case == RefinementCase<dim>::cut_xy)
2769 {
2770 triangulation
2771 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
2772
2773 lines_to_delete.push_back(cell->child(0)->line(1));
2774 lines_to_delete.push_back(cell->child(0)->line(3));
2775 lines_to_delete.push_back(cell->child(3)->line(0));
2776 lines_to_delete.push_back(cell->child(3)->line(2));
2777 }
2778 else
2779 {
2780 unsigned int inner_face_no =
2781 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
2782
2783 // the inner line will not be
2784 // used any more
2785 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
2786 }
2787
2788 // invalidate children
2789 for (unsigned int child = 0; child < cell->n_children(); ++child)
2790 {
2791 cell->child(child)->clear_user_data();
2792 cell->child(child)->clear_user_flag();
2793 cell->child(child)->clear_used_flag();
2794 }
2795
2796
2797 // delete pointer to children
2798 cell->clear_children();
2799 cell->clear_refinement_case();
2800 cell->clear_user_flag();
2801
2802 // look at the refinement of outer
2803 // lines. if nobody needs those
2804 // anymore we can add them to the
2805 // list of lines to be deleted.
2806 for (unsigned int line_no = 0;
2807 line_no < GeometryInfo<dim>::lines_per_cell;
2808 ++line_no)
2809 {
2810 typename Triangulation<dim, spacedim>::line_iterator line =
2811 cell->line(line_no);
2812
2813 if (line->has_children())
2814 {
2815 // if one of the cell counters is
2816 // zero, the other has to be as well
2817
2818 Assert((line_cell_count[line->child_index(0)] == 0 &&
2819 line_cell_count[line->child_index(1)] == 0) ||
2820 (line_cell_count[line->child_index(0)] > 0 &&
2821 line_cell_count[line->child_index(1)] > 0),
2822 ExcInternalError());
2823
2824 if (line_cell_count[line->child_index(0)] == 0)
2825 {
2826 for (unsigned int c = 0; c < 2; ++c)
2827 Assert(!line->child(c)->has_children(),
2828 ExcInternalError());
2829
2830 // we may delete the line's
2831 // children and the middle vertex
2832 // as no cell references them
2833 // anymore
2834 triangulation
2835 .vertices_used[line->child(0)->vertex_index(1)] = false;
2836
2837 lines_to_delete.push_back(line->child(0));
2838 lines_to_delete.push_back(line->child(1));
2839
2840 line->clear_children();
2841 }
2842 }
2843 }
2844
2845 // finally, delete unneeded lines
2846
2847 // clear user pointers, to avoid that
2848 // they may appear at unwanted places
2849 // later on...
2850 // same for user flags, then finally
2851 // delete the lines
2852 typename std::vector<
2853 typename Triangulation<dim, spacedim>::line_iterator>::iterator
2854 line = lines_to_delete.begin(),
2855 endline = lines_to_delete.end();
2856 for (; line != endline; ++line)
2857 {
2858 (*line)->clear_user_data();
2859 (*line)->clear_user_flag();
2860 (*line)->clear_used_flag();
2861 }
2862 }
2863
2864
2865
2866 template <int spacedim>
delete_childreninternal::TriangulationImplementation::Implementation2867 static void delete_children(
2868 Triangulation<3, spacedim> & triangulation,
2869 typename Triangulation<3, spacedim>::cell_iterator &cell,
2870 std::vector<unsigned int> & line_cell_count,
2871 std::vector<unsigned int> & quad_cell_count)
2872 {
2873 const unsigned int dim = 3;
2874
2875 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2876 ExcInternalError());
2877 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
2878 ExcInternalError());
2879
2880 // first of all, we store the RefineCase of
2881 // this cell
2882 const RefinementCase<dim> ref_case = cell->refinement_case();
2883 // vectors to hold all lines and quads which
2884 // may be deleted
2885 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2886 lines_to_delete(0);
2887 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
2888 quads_to_delete(0);
2889
2890 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
2891 quads_to_delete.reserve(6 * 4 + 12);
2892
2893 // now we decrease the counters for lines and
2894 // quads contained in the child cells
2895 for (unsigned int c = 0; c < cell->n_children(); ++c)
2896 {
2897 typename Triangulation<dim, spacedim>::cell_iterator child =
2898 cell->child(c);
2899 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
2900 --line_cell_count[child->line_index(l)];
2901 for (auto f : GeometryInfo<dim>::face_indices())
2902 --quad_cell_count[child->quad_index(f)];
2903 }
2904
2905 ///////////////////////////////////////
2906 // delete interior quads and lines and the
2907 // interior vertex, depending on the
2908 // refinement case of the cell
2909 //
2910 // for append quads and lines: only append
2911 // them to the list of objects to be deleted
2912
2913 switch (ref_case)
2914 {
2915 case RefinementCase<dim>::cut_x:
2916 quads_to_delete.push_back(cell->child(0)->face(1));
2917 break;
2918 case RefinementCase<dim>::cut_y:
2919 quads_to_delete.push_back(cell->child(0)->face(3));
2920 break;
2921 case RefinementCase<dim>::cut_z:
2922 quads_to_delete.push_back(cell->child(0)->face(5));
2923 break;
2924 case RefinementCase<dim>::cut_xy:
2925 quads_to_delete.push_back(cell->child(0)->face(1));
2926 quads_to_delete.push_back(cell->child(0)->face(3));
2927 quads_to_delete.push_back(cell->child(3)->face(0));
2928 quads_to_delete.push_back(cell->child(3)->face(2));
2929
2930 lines_to_delete.push_back(cell->child(0)->line(11));
2931 break;
2932 case RefinementCase<dim>::cut_xz:
2933 quads_to_delete.push_back(cell->child(0)->face(1));
2934 quads_to_delete.push_back(cell->child(0)->face(5));
2935 quads_to_delete.push_back(cell->child(3)->face(0));
2936 quads_to_delete.push_back(cell->child(3)->face(4));
2937
2938 lines_to_delete.push_back(cell->child(0)->line(5));
2939 break;
2940 case RefinementCase<dim>::cut_yz:
2941 quads_to_delete.push_back(cell->child(0)->face(3));
2942 quads_to_delete.push_back(cell->child(0)->face(5));
2943 quads_to_delete.push_back(cell->child(3)->face(2));
2944 quads_to_delete.push_back(cell->child(3)->face(4));
2945
2946 lines_to_delete.push_back(cell->child(0)->line(7));
2947 break;
2948 case RefinementCase<dim>::cut_xyz:
2949 quads_to_delete.push_back(cell->child(0)->face(1));
2950 quads_to_delete.push_back(cell->child(2)->face(1));
2951 quads_to_delete.push_back(cell->child(4)->face(1));
2952 quads_to_delete.push_back(cell->child(6)->face(1));
2953
2954 quads_to_delete.push_back(cell->child(0)->face(3));
2955 quads_to_delete.push_back(cell->child(1)->face(3));
2956 quads_to_delete.push_back(cell->child(4)->face(3));
2957 quads_to_delete.push_back(cell->child(5)->face(3));
2958
2959 quads_to_delete.push_back(cell->child(0)->face(5));
2960 quads_to_delete.push_back(cell->child(1)->face(5));
2961 quads_to_delete.push_back(cell->child(2)->face(5));
2962 quads_to_delete.push_back(cell->child(3)->face(5));
2963
2964 lines_to_delete.push_back(cell->child(0)->line(5));
2965 lines_to_delete.push_back(cell->child(0)->line(7));
2966 lines_to_delete.push_back(cell->child(0)->line(11));
2967 lines_to_delete.push_back(cell->child(7)->line(0));
2968 lines_to_delete.push_back(cell->child(7)->line(2));
2969 lines_to_delete.push_back(cell->child(7)->line(8));
2970 // delete the vertex which will not
2971 // be needed anymore. This vertex
2972 // is the vertex at the heart of
2973 // this cell, which is the sixth of
2974 // the first child
2975 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
2976 false;
2977 break;
2978 default:
2979 // only remaining case is
2980 // no_refinement, thus an error
2981 Assert(false, ExcInternalError());
2982 break;
2983 }
2984
2985
2986 // invalidate children
2987 for (unsigned int child = 0; child < cell->n_children(); ++child)
2988 {
2989 cell->child(child)->clear_user_data();
2990 cell->child(child)->clear_user_flag();
2991
2992 for (auto f : GeometryInfo<dim>::face_indices())
2993 {
2994 // set flags denoting deviations from
2995 // standard orientation of faces back
2996 // to initialization values
2997 cell->child(child)->set_face_orientation(f, true);
2998 cell->child(child)->set_face_flip(f, false);
2999 cell->child(child)->set_face_rotation(f, false);
3000 }
3001
3002 cell->child(child)->clear_used_flag();
3003 }
3004
3005
3006 // delete pointer to children
3007 cell->clear_children();
3008 cell->clear_refinement_case();
3009 cell->clear_user_flag();
3010
3011 // so far we only looked at inner quads,
3012 // lines and vertices. Now we have to
3013 // consider outer ones as well. here, we have
3014 // to check, whether there are other cells
3015 // still needing these objects. otherwise we
3016 // can delete them. first for quads (and
3017 // their inner lines).
3018
3019 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
3020 {
3021 typename Triangulation<dim, spacedim>::quad_iterator quad =
3022 cell->face(quad_no);
3023
3024 Assert(
3025 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
3026 quad->has_children()) ||
3027 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
3028 RefinementCase<dim - 1>::no_refinement,
3029 ExcInternalError());
3030
3031 switch (quad->refinement_case())
3032 {
3033 case RefinementCase<dim - 1>::no_refinement:
3034 // nothing to do as the quad
3035 // is not refined
3036 break;
3037 case RefinementCase<dim - 1>::cut_x:
3038 case RefinementCase<dim - 1>::cut_y:
3039 {
3040 // if one of the cell counters is
3041 // zero, the other has to be as
3042 // well
3043 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3044 quad_cell_count[quad->child_index(1)] == 0) ||
3045 (quad_cell_count[quad->child_index(0)] > 0 &&
3046 quad_cell_count[quad->child_index(1)] > 0),
3047 ExcInternalError());
3048 // it might be, that the quad is
3049 // refined twice anisotropically,
3050 // first check, whether we may
3051 // delete possible grand_children
3052 unsigned int deleted_grandchildren = 0;
3053 unsigned int number_of_child_refinements = 0;
3054
3055 for (unsigned int c = 0; c < 2; ++c)
3056 if (quad->child(c)->has_children())
3057 {
3058 ++number_of_child_refinements;
3059 // if one of the cell counters is
3060 // zero, the other has to be as
3061 // well
3062 Assert(
3063 (quad_cell_count[quad->child(c)->child_index(0)] ==
3064 0 &&
3065 quad_cell_count[quad->child(c)->child_index(1)] ==
3066 0) ||
3067 (quad_cell_count[quad->child(c)->child_index(0)] >
3068 0 &&
3069 quad_cell_count[quad->child(c)->child_index(1)] >
3070 0),
3071 ExcInternalError());
3072 if (quad_cell_count[quad->child(c)->child_index(0)] ==
3073 0)
3074 {
3075 // Assert, that the two
3076 // anisotropic
3077 // refinements add up to
3078 // isotropic refinement
3079 Assert(quad->refinement_case() +
3080 quad->child(c)->refinement_case() ==
3081 RefinementCase<dim>::cut_xy,
3082 ExcInternalError());
3083 // we may delete the
3084 // quad's children and
3085 // the inner line as no
3086 // cell references them
3087 // anymore
3088 quads_to_delete.push_back(
3089 quad->child(c)->child(0));
3090 quads_to_delete.push_back(
3091 quad->child(c)->child(1));
3092 if (quad->child(c)->refinement_case() ==
3093 RefinementCase<2>::cut_x)
3094 lines_to_delete.push_back(
3095 quad->child(c)->child(0)->line(1));
3096 else
3097 lines_to_delete.push_back(
3098 quad->child(c)->child(0)->line(3));
3099 quad->child(c)->clear_children();
3100 quad->child(c)->clear_refinement_case();
3101 ++deleted_grandchildren;
3102 }
3103 }
3104 // if no grandchildren are left, we
3105 // may as well delete the
3106 // refinement of the inner line
3107 // between our children and the
3108 // corresponding vertex
3109 if (number_of_child_refinements > 0 &&
3110 deleted_grandchildren == number_of_child_refinements)
3111 {
3112 typename Triangulation<dim, spacedim>::line_iterator
3113 middle_line;
3114 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3115 middle_line = quad->child(0)->line(1);
3116 else
3117 middle_line = quad->child(0)->line(3);
3118
3119 lines_to_delete.push_back(middle_line->child(0));
3120 lines_to_delete.push_back(middle_line->child(1));
3121 triangulation
3122 .vertices_used[middle_vertex_index<dim, spacedim>(
3123 middle_line)] = false;
3124 middle_line->clear_children();
3125 }
3126
3127 // now consider the direct children
3128 // of the given quad
3129 if (quad_cell_count[quad->child_index(0)] == 0)
3130 {
3131 // we may delete the quad's
3132 // children and the inner line
3133 // as no cell references them
3134 // anymore
3135 quads_to_delete.push_back(quad->child(0));
3136 quads_to_delete.push_back(quad->child(1));
3137 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3138 lines_to_delete.push_back(quad->child(0)->line(1));
3139 else
3140 lines_to_delete.push_back(quad->child(0)->line(3));
3141
3142 // if the counters just dropped
3143 // to zero, otherwise the
3144 // children would have been
3145 // deleted earlier, then this
3146 // cell's children must have
3147 // contained the anisotropic
3148 // quad children. thus, if
3149 // those have again anisotropic
3150 // children, which are in
3151 // effect isotropic children of
3152 // the original quad, those are
3153 // still needed by a
3154 // neighboring cell and we
3155 // cannot delete them. instead,
3156 // we have to reset this quad's
3157 // refine case to isotropic and
3158 // set the children
3159 // accordingly.
3160 if (quad->child(0)->has_children())
3161 if (quad->refinement_case() ==
3162 RefinementCase<2>::cut_x)
3163 {
3164 // now evereything is
3165 // quite complicated. we
3166 // have the children
3167 // numbered according to
3168 //
3169 // *---*---*
3170 // |n+1|m+1|
3171 // *---*---*
3172 // | n | m |
3173 // *---*---*
3174 //
3175 // from the original
3176 // anisotropic
3177 // refinement. we have to
3178 // reorder them as
3179 //
3180 // *---*---*
3181 // | m |m+1|
3182 // *---*---*
3183 // | n |n+1|
3184 // *---*---*
3185 //
3186 // for isotropic refinement.
3187 //
3188 // this is a bit ugly, of
3189 // course: loop over all
3190 // cells on all levels
3191 // and look for faces n+1
3192 // (switch_1) and m
3193 // (switch_2).
3194 const typename Triangulation<dim, spacedim>::
3195 quad_iterator switch_1 =
3196 quad->child(0)->child(1),
3197 switch_2 =
3198 quad->child(1)->child(0);
3199
3200 Assert(!switch_1->has_children(),
3201 ExcInternalError());
3202 Assert(!switch_2->has_children(),
3203 ExcInternalError());
3204
3205 const int switch_1_index = switch_1->index();
3206 const int switch_2_index = switch_2->index();
3207 for (unsigned int l = 0;
3208 l < triangulation.levels.size();
3209 ++l)
3210 for (unsigned int h = 0;
3211 h <
3212 triangulation.levels[l]->cells.n_objects();
3213 ++h)
3214 for (const unsigned int q :
3215 GeometryInfo<dim>::face_indices())
3216 {
3217 const int index =
3218 triangulation.levels[l]
3219 ->cells.get_bounding_object_indices(
3220 h)[q];
3221 if (index == switch_1_index)
3222 triangulation.levels[l]
3223 ->cells.get_bounding_object_indices(
3224 h)[q] = switch_2_index;
3225 else if (index == switch_2_index)
3226 triangulation.levels[l]
3227 ->cells.get_bounding_object_indices(
3228 h)[q] = switch_1_index;
3229 }
3230 // now we have to copy
3231 // all information of the
3232 // two quads
3233 const int switch_1_lines[4] = {
3234 static_cast<signed int>(
3235 switch_1->line_index(0)),
3236 static_cast<signed int>(
3237 switch_1->line_index(1)),
3238 static_cast<signed int>(
3239 switch_1->line_index(2)),
3240 static_cast<signed int>(
3241 switch_1->line_index(3))};
3242 const bool switch_1_line_orientations[4] = {
3243 switch_1->line_orientation(0),
3244 switch_1->line_orientation(1),
3245 switch_1->line_orientation(2),
3246 switch_1->line_orientation(3)};
3247 const types::boundary_id switch_1_boundary_id =
3248 switch_1->boundary_id();
3249 const unsigned int switch_1_user_index =
3250 switch_1->user_index();
3251 const bool switch_1_user_flag =
3252 switch_1->user_flag_set();
3253
3254 switch_1->set_bounding_object_indices(
3255 {switch_2->line_index(0),
3256 switch_2->line_index(1),
3257 switch_2->line_index(2),
3258 switch_2->line_index(3)});
3259 switch_1->set_line_orientation(
3260 0, switch_2->line_orientation(0));
3261 switch_1->set_line_orientation(
3262 1, switch_2->line_orientation(1));
3263 switch_1->set_line_orientation(
3264 2, switch_2->line_orientation(2));
3265 switch_1->set_line_orientation(
3266 3, switch_2->line_orientation(3));
3267 switch_1->set_boundary_id_internal(
3268 switch_2->boundary_id());
3269 switch_1->set_manifold_id(
3270 switch_2->manifold_id());
3271 switch_1->set_user_index(switch_2->user_index());
3272 if (switch_2->user_flag_set())
3273 switch_1->set_user_flag();
3274 else
3275 switch_1->clear_user_flag();
3276
3277 switch_2->set_bounding_object_indices(
3278 {switch_1_lines[0],
3279 switch_1_lines[1],
3280 switch_1_lines[2],
3281 switch_1_lines[3]});
3282 switch_2->set_line_orientation(
3283 0, switch_1_line_orientations[0]);
3284 switch_2->set_line_orientation(
3285 1, switch_1_line_orientations[1]);
3286 switch_2->set_line_orientation(
3287 2, switch_1_line_orientations[2]);
3288 switch_2->set_line_orientation(
3289 3, switch_1_line_orientations[3]);
3290 switch_2->set_boundary_id_internal(
3291 switch_1_boundary_id);
3292 switch_2->set_manifold_id(
3293 switch_1->manifold_id());
3294 switch_2->set_user_index(switch_1_user_index);
3295 if (switch_1_user_flag)
3296 switch_2->set_user_flag();
3297 else
3298 switch_2->clear_user_flag();
3299
3300 const unsigned int child_0 =
3301 quad->child(0)->child_index(0);
3302 const unsigned int child_2 =
3303 quad->child(1)->child_index(0);
3304 quad->clear_children();
3305 quad->clear_refinement_case();
3306 quad->set_refinement_case(
3307 RefinementCase<2>::cut_xy);
3308 quad->set_children(0, child_0);
3309 quad->set_children(2, child_2);
3310 std::swap(quad_cell_count[child_0 + 1],
3311 quad_cell_count[child_2]);
3312 }
3313 else
3314 {
3315 // the face was refined
3316 // with cut_y, thus the
3317 // children are already
3318 // in correct order. we
3319 // only have to set them
3320 // correctly, deleting
3321 // the indirection of two
3322 // anisotropic refinement
3323 // and going directly
3324 // from the quad to
3325 // isotropic children
3326 const unsigned int child_0 =
3327 quad->child(0)->child_index(0);
3328 const unsigned int child_2 =
3329 quad->child(1)->child_index(0);
3330 quad->clear_children();
3331 quad->clear_refinement_case();
3332 quad->set_refinement_case(
3333 RefinementCase<2>::cut_xy);
3334 quad->set_children(0, child_0);
3335 quad->set_children(2, child_2);
3336 }
3337 else
3338 {
3339 quad->clear_children();
3340 quad->clear_refinement_case();
3341 }
3342 }
3343 break;
3344 }
3345 case RefinementCase<dim - 1>::cut_xy:
3346 {
3347 // if one of the cell counters is
3348 // zero, the others have to be as
3349 // well
3350
3351 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3352 quad_cell_count[quad->child_index(1)] == 0 &&
3353 quad_cell_count[quad->child_index(2)] == 0 &&
3354 quad_cell_count[quad->child_index(3)] == 0) ||
3355 (quad_cell_count[quad->child_index(0)] > 0 &&
3356 quad_cell_count[quad->child_index(1)] > 0 &&
3357 quad_cell_count[quad->child_index(2)] > 0 &&
3358 quad_cell_count[quad->child_index(3)] > 0),
3359 ExcInternalError());
3360
3361 if (quad_cell_count[quad->child_index(0)] == 0)
3362 {
3363 // we may delete the quad's
3364 // children, the inner lines
3365 // and the middle vertex as no
3366 // cell references them anymore
3367 lines_to_delete.push_back(quad->child(0)->line(1));
3368 lines_to_delete.push_back(quad->child(3)->line(0));
3369 lines_to_delete.push_back(quad->child(0)->line(3));
3370 lines_to_delete.push_back(quad->child(3)->line(2));
3371
3372 for (unsigned int child = 0; child < quad->n_children();
3373 ++child)
3374 quads_to_delete.push_back(quad->child(child));
3375
3376 triangulation
3377 .vertices_used[quad->child(0)->vertex_index(3)] =
3378 false;
3379
3380 quad->clear_children();
3381 quad->clear_refinement_case();
3382 }
3383 }
3384 break;
3385
3386 default:
3387 Assert(false, ExcInternalError());
3388 break;
3389 }
3390 }
3391
3392 // now we repeat a similar procedure
3393 // for the outer lines of this cell.
3394
3395 // if in debug mode: check that each
3396 // of the lines for which we consider
3397 // deleting the children in fact has
3398 // children (the bits/coarsening_3d
3399 // test tripped over this initially)
3400 for (unsigned int line_no = 0;
3401 line_no < GeometryInfo<dim>::lines_per_cell;
3402 ++line_no)
3403 {
3404 typename Triangulation<dim, spacedim>::line_iterator line =
3405 cell->line(line_no);
3406
3407 Assert(
3408 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
3409 line->has_children()) ||
3410 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
3411 RefinementCase<1>::no_refinement,
3412 ExcInternalError());
3413
3414 if (line->has_children())
3415 {
3416 // if one of the cell counters is
3417 // zero, the other has to be as well
3418
3419 Assert((line_cell_count[line->child_index(0)] == 0 &&
3420 line_cell_count[line->child_index(1)] == 0) ||
3421 (line_cell_count[line->child_index(0)] > 0 &&
3422 line_cell_count[line->child_index(1)] > 0),
3423 ExcInternalError());
3424
3425 if (line_cell_count[line->child_index(0)] == 0)
3426 {
3427 for (unsigned int c = 0; c < 2; ++c)
3428 Assert(!line->child(c)->has_children(),
3429 ExcInternalError());
3430
3431 // we may delete the line's
3432 // children and the middle vertex
3433 // as no cell references them
3434 // anymore
3435 triangulation
3436 .vertices_used[line->child(0)->vertex_index(1)] = false;
3437
3438 lines_to_delete.push_back(line->child(0));
3439 lines_to_delete.push_back(line->child(1));
3440
3441 line->clear_children();
3442 }
3443 }
3444 }
3445
3446 // finally, delete unneeded quads and lines
3447
3448 // clear user pointers, to avoid that
3449 // they may appear at unwanted places
3450 // later on...
3451 // same for user flags, then finally
3452 // delete the quads and lines
3453 typename std::vector<
3454 typename Triangulation<dim, spacedim>::line_iterator>::iterator
3455 line = lines_to_delete.begin(),
3456 endline = lines_to_delete.end();
3457 for (; line != endline; ++line)
3458 {
3459 (*line)->clear_user_data();
3460 (*line)->clear_user_flag();
3461 (*line)->clear_used_flag();
3462 }
3463
3464 typename std::vector<
3465 typename Triangulation<dim, spacedim>::quad_iterator>::iterator
3466 quad = quads_to_delete.begin(),
3467 endquad = quads_to_delete.end();
3468 for (; quad != endquad; ++quad)
3469 {
3470 (*quad)->clear_user_data();
3471 (*quad)->clear_children();
3472 (*quad)->clear_refinement_case();
3473 (*quad)->clear_user_flag();
3474 (*quad)->clear_used_flag();
3475 }
3476 }
3477
3478
3479 /**
3480 * Create the children of a 2d
3481 * cell. The arguments indicate
3482 * the next free spots in the
3483 * vertices, lines, and cells
3484 * arrays.
3485 *
3486 * The faces of the cell have to
3487 * be refined already, whereas
3488 * the inner lines in 2D will be
3489 * created in this
3490 * function. Therefore iterator
3491 * pointers into the vectors of
3492 * lines, quads and cells have to
3493 * be passed, which point at (or
3494 * "before") the reserved space.
3495 */
3496 template <int spacedim>
create_childreninternal::TriangulationImplementation::Implementation3497 static void create_children(
3498 Triangulation<2, spacedim> &triangulation,
3499 unsigned int & next_unused_vertex,
3500 typename Triangulation<2, spacedim>::raw_line_iterator
3501 &next_unused_line,
3502 typename Triangulation<2, spacedim>::raw_cell_iterator
3503 &next_unused_cell,
3504 const typename Triangulation<2, spacedim>::cell_iterator &cell)
3505 {
3506 const unsigned int dim = 2;
3507 // clear refinement flag
3508 const RefinementCase<dim> ref_case = cell->refine_flag_set();
3509 cell->clear_refine_flag();
3510
3511 /* For the refinement process: since we go the levels up from the
3512 lowest, there are (unlike above) only two possibilities: a neighbor
3513 cell is on the same level or one level up (in both cases, it may or
3514 may not be refined later on, but we don't care here).
3515
3516 First:
3517 Set up an array of the 3x3 vertices, which are distributed on the
3518 cell (the array consists of indices into the @p{vertices} std::vector
3519
3520 2--7--3
3521 | | |
3522 4--8--5
3523 | | |
3524 0--6--1
3525
3526 note: in case of cut_x or cut_y not all these vertices are needed for
3527 the new cells
3528
3529 Second:
3530 Set up an array of the new lines (the array consists of iterator
3531 pointers into the lines arrays)
3532
3533 .-6-.-7-. The directions are: .->-.->-.
3534 1 9 3 ^ ^ ^
3535 .-10.11-. .->-.->-.
3536 0 8 2 ^ ^ ^
3537 .-4-.-5-. .->-.->-.
3538
3539 cut_x:
3540 .-4-.-5-.
3541 | | |
3542 0 6 1
3543 | | |
3544 .-2-.-3-.
3545
3546 cut_y:
3547 .---5---.
3548 1 3
3549 .---6---.
3550 0 2
3551 .---4---.
3552
3553
3554 Third:
3555 Set up an array of neighbors:
3556
3557 6 7
3558 .--.--.
3559 1| | |3
3560 .--.--.
3561 0| | |2
3562 .--.--.
3563 4 5
3564
3565 We need this array for two reasons: first to get the lines which will
3566 bound the four subcells (if the neighboring cell is refined, these
3567 lines already exist), and second to update neighborship information.
3568 Since if a neighbor is not refined, its neighborship record only
3569 points to the present, unrefined, cell rather than the children we
3570 are presently creating, we only need the neighborship information
3571 if the neighbor cells are refined. In all other cases, we store
3572 the unrefined neighbor address
3573
3574 We also need for every neighbor (if refined) which number among its
3575 neighbors the present (unrefined) cell has, since that number is to
3576 be replaced and because that also is the number of the subline which
3577 will be the interface between that neighbor and the to be created
3578 cell. We will store this number (between 0 and 3) in the field
3579 @p{neighbors_neighbor}.
3580
3581 It would be sufficient to use the children of the common line to the
3582 neighbor, if we only wanted to get the new sublines and the new
3583 vertex, but because we need to update the neighborship information of
3584 the two refined subcells of the neighbor, we need to search these
3585 anyway.
3586
3587 Convention:
3588 The created children are numbered like this:
3589
3590 .--.--.
3591 |2 . 3|
3592 .--.--.
3593 |0 | 1|
3594 .--.--.
3595 */
3596 // collect the
3597 // indices of the
3598 // eight
3599 // surrounding
3600 // vertices
3601 // 2--7--3
3602 // | | |
3603 // 4--9--5
3604 // | | |
3605 // 0--6--1
3606 int new_vertices[9];
3607 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
3608 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
3609 for (unsigned int line_no = 0; line_no < 4; ++line_no)
3610 if (cell->line(line_no)->has_children())
3611 new_vertices[4 + line_no] =
3612 cell->line(line_no)->child(0)->vertex_index(1);
3613
3614 if (ref_case == RefinementCase<dim>::cut_xy)
3615 {
3616 // find the next
3617 // unused vertex and
3618 // allocate it for
3619 // the new vertex we
3620 // need here
3621 while (triangulation.vertices_used[next_unused_vertex] == true)
3622 ++next_unused_vertex;
3623 Assert(
3624 next_unused_vertex < triangulation.vertices.size(),
3625 ExcMessage(
3626 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
3627 triangulation.vertices_used[next_unused_vertex] = true;
3628
3629 new_vertices[8] = next_unused_vertex;
3630
3631 // if this quad lives
3632 // in 2d, then we can
3633 // compute the new
3634 // central vertex
3635 // location just from
3636 // the surrounding
3637 // ones. If this is
3638 // not the case, then
3639 // we need to ask a
3640 // boundary object
3641 if (dim == spacedim)
3642 {
3643 // triangulation.vertices[next_unused_vertex] = new_point;
3644 triangulation.vertices[next_unused_vertex] = cell->center(true);
3645
3646 // if the user_flag is set, i.e. if the cell is at the
3647 // boundary, use a different calculation of the middle vertex
3648 // here. this is of advantage if the boundary is strongly
3649 // curved (whereas the cell is not) and the cell has a high
3650 // aspect ratio.
3651 if (cell->user_flag_set())
3652 {
3653 // first reset the user_flag and then refine
3654 cell->clear_user_flag();
3655 triangulation.vertices[next_unused_vertex] =
3656 cell->center(true, true);
3657 }
3658 }
3659 else
3660 {
3661 // if this quad lives in a higher dimensional space
3662 // then we don't need to worry if it is at the
3663 // boundary of the manifold -- we always have to use
3664 // the boundary object anyway; so ignore whether the
3665 // user flag is set or not
3666 cell->clear_user_flag();
3667
3668 // determine middle vertex by transfinite interpolation to be
3669 // consistent with what happens to quads in a Triangulation<3,
3670 // 3> when they are refined
3671 triangulation.vertices[next_unused_vertex] =
3672 cell->center(true, true);
3673 }
3674 }
3675
3676
3677 // Now the lines:
3678 typename Triangulation<dim, spacedim>::raw_line_iterator new_lines[12];
3679 unsigned int lmin = 8;
3680 unsigned int lmax = 12;
3681 if (ref_case != RefinementCase<dim>::cut_xy)
3682 {
3683 lmin = 6;
3684 lmax = 7;
3685 }
3686
3687 for (unsigned int l = lmin; l < lmax; ++l)
3688 {
3689 while (next_unused_line->used() == true)
3690 ++next_unused_line;
3691 new_lines[l] = next_unused_line;
3692 ++next_unused_line;
3693
3694 Assert(
3695 new_lines[l]->used() == false,
3696 ExcMessage(
3697 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
3698 }
3699
3700 if (ref_case == RefinementCase<dim>::cut_xy)
3701 {
3702 // .-6-.-7-.
3703 // 1 9 3
3704 // .-10.11-.
3705 // 0 8 2
3706 // .-4-.-5-.
3707
3708 // lines 0-7 already exist, create only the four interior
3709 // lines 8-11
3710 unsigned int l = 0;
3711 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
3712 for (unsigned int c = 0; c < 2; ++c, ++l)
3713 new_lines[l] = cell->line(face_no)->child(c);
3714 Assert(l == 8, ExcInternalError());
3715
3716 new_lines[8]->set_bounding_object_indices(
3717 {new_vertices[6], new_vertices[8]});
3718 new_lines[9]->set_bounding_object_indices(
3719 {new_vertices[8], new_vertices[7]});
3720 new_lines[10]->set_bounding_object_indices(
3721 {new_vertices[4], new_vertices[8]});
3722 new_lines[11]->set_bounding_object_indices(
3723 {new_vertices[8], new_vertices[5]});
3724 }
3725 else if (ref_case == RefinementCase<dim>::cut_x)
3726 {
3727 // .-4-.-5-.
3728 // | | |
3729 // 0 6 1
3730 // | | |
3731 // .-2-.-3-.
3732 new_lines[0] = cell->line(0);
3733 new_lines[1] = cell->line(1);
3734 new_lines[2] = cell->line(2)->child(0);
3735 new_lines[3] = cell->line(2)->child(1);
3736 new_lines[4] = cell->line(3)->child(0);
3737 new_lines[5] = cell->line(3)->child(1);
3738 new_lines[6]->set_bounding_object_indices(
3739 {new_vertices[6], new_vertices[7]});
3740 }
3741 else
3742 {
3743 Assert(ref_case == RefinementCase<dim>::cut_y, ExcInternalError());
3744 // .---5---.
3745 // 1 3
3746 // .---6---.
3747 // 0 2
3748 // .---4---.
3749 new_lines[0] = cell->line(0)->child(0);
3750 new_lines[1] = cell->line(0)->child(1);
3751 new_lines[2] = cell->line(1)->child(0);
3752 new_lines[3] = cell->line(1)->child(1);
3753 new_lines[4] = cell->line(2);
3754 new_lines[5] = cell->line(3);
3755 new_lines[6]->set_bounding_object_indices(
3756 {new_vertices[4], new_vertices[5]});
3757 }
3758
3759 for (unsigned int l = lmin; l < lmax; ++l)
3760 {
3761 new_lines[l]->set_used_flag();
3762 new_lines[l]->clear_user_flag();
3763 new_lines[l]->clear_user_data();
3764 new_lines[l]->clear_children();
3765 // interior line
3766 new_lines[l]->set_boundary_id_internal(
3767 numbers::internal_face_boundary_id);
3768 new_lines[l]->set_manifold_id(cell->manifold_id());
3769 }
3770
3771 // Now add the four (two)
3772 // new cells!
3773 typename Triangulation<dim, spacedim>::raw_cell_iterator
3774 subcells[GeometryInfo<dim>::max_children_per_cell];
3775 while (next_unused_cell->used() == true)
3776 ++next_unused_cell;
3777
3778 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
3779 for (unsigned int i = 0; i < n_children; ++i)
3780 {
3781 Assert(
3782 next_unused_cell->used() == false,
3783 ExcMessage(
3784 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
3785 subcells[i] = next_unused_cell;
3786 ++next_unused_cell;
3787 if (i % 2 == 1 && i < n_children - 1)
3788 while (next_unused_cell->used() == true)
3789 ++next_unused_cell;
3790 }
3791
3792 if (ref_case == RefinementCase<dim>::cut_xy)
3793 {
3794 // children:
3795 // .--.--.
3796 // |2 . 3|
3797 // .--.--.
3798 // |0 | 1|
3799 // .--.--.
3800 // lines:
3801 // .-6-.-7-.
3802 // 1 9 3
3803 // .-10.11-.
3804 // 0 8 2
3805 // .-4-.-5-.
3806 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3807 new_lines[8]->index(),
3808 new_lines[4]->index(),
3809 new_lines[10]->index()});
3810 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
3811 new_lines[2]->index(),
3812 new_lines[5]->index(),
3813 new_lines[11]->index()});
3814 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
3815 new_lines[9]->index(),
3816 new_lines[10]->index(),
3817 new_lines[6]->index()});
3818 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
3819 new_lines[3]->index(),
3820 new_lines[11]->index(),
3821 new_lines[7]->index()});
3822 }
3823 else if (ref_case == RefinementCase<dim>::cut_x)
3824 {
3825 // children:
3826 // .--.--.
3827 // | . |
3828 // .0 . 1.
3829 // | | |
3830 // .--.--.
3831 // lines:
3832 // .-4-.-5-.
3833 // | | |
3834 // 0 6 1
3835 // | | |
3836 // .-2-.-3-.
3837 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3838 new_lines[6]->index(),
3839 new_lines[2]->index(),
3840 new_lines[4]->index()});
3841 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
3842 new_lines[1]->index(),
3843 new_lines[3]->index(),
3844 new_lines[5]->index()});
3845 }
3846 else
3847 {
3848 Assert(ref_case == RefinementCase<dim>::cut_y, ExcInternalError());
3849 // children:
3850 // .-----.
3851 // | 1 |
3852 // .-----.
3853 // | 0 |
3854 // .-----.
3855 // lines:
3856 // .---5---.
3857 // 1 3
3858 // .---6---.
3859 // 0 2
3860 // .---4---.
3861 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3862 new_lines[2]->index(),
3863 new_lines[4]->index(),
3864 new_lines[6]->index()});
3865 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
3866 new_lines[3]->index(),
3867 new_lines[6]->index(),
3868 new_lines[5]->index()});
3869 }
3870
3871 types::subdomain_id subdomainid = cell->subdomain_id();
3872
3873 for (unsigned int i = 0; i < n_children; ++i)
3874 {
3875 subcells[i]->set_used_flag();
3876 subcells[i]->clear_refine_flag();
3877 subcells[i]->clear_user_flag();
3878 subcells[i]->clear_user_data();
3879 subcells[i]->clear_children();
3880 // inherit material
3881 // properties
3882 subcells[i]->set_material_id(cell->material_id());
3883 subcells[i]->set_manifold_id(cell->manifold_id());
3884 subcells[i]->set_subdomain_id(subdomainid);
3885
3886 if (i % 2 == 0)
3887 subcells[i]->set_parent(cell->index());
3888 }
3889
3890
3891
3892 // set child index for
3893 // even children children
3894 // i=0,2 (0)
3895 for (unsigned int i = 0; i < n_children / 2; ++i)
3896 cell->set_children(2 * i, subcells[2 * i]->index());
3897 // set the refine case
3898 cell->set_refinement_case(ref_case);
3899
3900 // note that the
3901 // refinement flag was
3902 // already cleared at the
3903 // beginning of this function
3904
3905 if (dim < spacedim)
3906 for (unsigned int c = 0; c < n_children; ++c)
3907 cell->child(c)->set_direction_flag(cell->direction_flag());
3908 }
3909
3910
3911
3912 /**
3913 * A function that performs the
3914 * refinement of a triangulation in 1d.
3915 */
3916 template <int spacedim>
3917 static typename Triangulation<1, spacedim>::DistortedCellList
execute_refinementinternal::TriangulationImplementation::Implementation3918 execute_refinement(Triangulation<1, spacedim> &triangulation,
3919 const bool /*check_for_distorted_cells*/)
3920 {
3921 const unsigned int dim = 1;
3922
3923 // check whether a new level is needed we have to check for
3924 // this on the highest level only (on this, all used cells are
3925 // also active, so we only have to check for this)
3926 {
3927 typename Triangulation<dim, spacedim>::raw_cell_iterator
3928 cell = triangulation.begin_active(triangulation.levels.size() - 1),
3929 endc = triangulation.end();
3930 for (; cell != endc; ++cell)
3931 if (cell->used())
3932 if (cell->refine_flag_set())
3933 {
3934 triangulation.levels.push_back(
3935 std::make_unique<
3936 internal::TriangulationImplementation::TriaLevel>(dim));
3937 break;
3938 }
3939 }
3940
3941
3942 // check how much space is needed on every level we need not
3943 // check the highest level since either - on the highest level
3944 // no cells are flagged for refinement - there are, but
3945 // prepare_refinement added another empty level
3946 unsigned int needed_vertices = 0;
3947 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
3948 {
3949 // count number of flagged
3950 // cells on this level
3951 unsigned int flagged_cells = 0;
3952
3953 for (const auto &acell :
3954 triangulation.active_cell_iterators_on_level(level))
3955 if (acell->refine_flag_set())
3956 ++flagged_cells;
3957
3958 // count number of used cells
3959 // on the next higher level
3960 const unsigned int used_cells =
3961 std::count(triangulation.levels[level + 1]->cells.used.begin(),
3962 triangulation.levels[level + 1]->cells.used.end(),
3963 true);
3964
3965 // reserve space for the used_cells cells already existing
3966 // on the next higher level as well as for the
3967 // 2*flagged_cells that will be created on that level
3968 reserve_space(*triangulation.levels[level + 1],
3969 used_cells + GeometryInfo<1>::max_children_per_cell *
3970 flagged_cells,
3971 1,
3972 spacedim);
3973 // reserve space for 2*flagged_cells new lines on the next
3974 // higher level
3975 reserve_space(triangulation.levels[level + 1]->cells,
3976 GeometryInfo<1>::max_children_per_cell *
3977 flagged_cells,
3978 0);
3979
3980 needed_vertices += flagged_cells;
3981 }
3982
3983 // add to needed vertices how many
3984 // vertices are already in use
3985 needed_vertices += std::count(triangulation.vertices_used.begin(),
3986 triangulation.vertices_used.end(),
3987 true);
3988 // if we need more vertices: create them, if not: leave the
3989 // array as is, since shrinking is not really possible because
3990 // some of the vertices at the end may be in use
3991 if (needed_vertices > triangulation.vertices.size())
3992 {
3993 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
3994 triangulation.vertices_used.resize(needed_vertices, false);
3995 }
3996
3997
3998 // Do REFINEMENT on every level; exclude highest level as
3999 // above
4000
4001 // index of next unused vertex
4002 unsigned int next_unused_vertex = 0;
4003
4004 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4005 {
4006 typename Triangulation<dim, spacedim>::raw_cell_iterator
4007 next_unused_cell = triangulation.begin_raw(level + 1);
4008
4009 for (const auto &cell :
4010 triangulation.active_cell_iterators_on_level(level))
4011 if (cell->refine_flag_set())
4012 {
4013 // clear refinement flag
4014 cell->clear_refine_flag();
4015
4016 // search for next unused
4017 // vertex
4018 while (triangulation.vertices_used[next_unused_vertex] ==
4019 true)
4020 ++next_unused_vertex;
4021 Assert(
4022 next_unused_vertex < triangulation.vertices.size(),
4023 ExcMessage(
4024 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
4025
4026 // Now we always ask the cell itself where to put
4027 // the new point. The cell in turn will query the
4028 // manifold object internally.
4029 triangulation.vertices[next_unused_vertex] =
4030 cell->center(true);
4031
4032 triangulation.vertices_used[next_unused_vertex] = true;
4033
4034 // search for next two unused cell (++ takes care of
4035 // the end of the vector)
4036 typename Triangulation<dim, spacedim>::raw_cell_iterator
4037 first_child,
4038 second_child;
4039 while (next_unused_cell->used() == true)
4040 ++next_unused_cell;
4041 first_child = next_unused_cell;
4042 first_child->set_used_flag();
4043 first_child->clear_user_data();
4044 ++next_unused_cell;
4045 Assert(
4046 next_unused_cell->used() == false,
4047 ExcMessage(
4048 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4049 second_child = next_unused_cell;
4050 second_child->set_used_flag();
4051 second_child->clear_user_data();
4052
4053 types::subdomain_id subdomainid = cell->subdomain_id();
4054
4055 // insert first child
4056 cell->set_children(0, first_child->index());
4057 first_child->clear_children();
4058 first_child->set_bounding_object_indices(
4059 {cell->vertex_index(0), next_unused_vertex});
4060 first_child->set_material_id(cell->material_id());
4061 first_child->set_manifold_id(cell->manifold_id());
4062 first_child->set_subdomain_id(subdomainid);
4063 first_child->set_direction_flag(cell->direction_flag());
4064
4065 first_child->set_parent(cell->index());
4066
4067 // Set manifold id of the right face. Only do this
4068 // on the first child.
4069 first_child->face(1)->set_manifold_id(cell->manifold_id());
4070
4071 // reset neighborship info (refer to
4072 // internal::TriangulationImplementation::TriaLevel<0> for
4073 // details)
4074 first_child->set_neighbor(1, second_child);
4075 if (cell->neighbor(0).state() != IteratorState::valid)
4076 first_child->set_neighbor(0, cell->neighbor(0));
4077 else if (cell->neighbor(0)->is_active())
4078 {
4079 // since the neighbors level is always <=level,
4080 // if the cell is active, then there are no
4081 // cells to the left which may want to know
4082 // about this new child cell.
4083 Assert(cell->neighbor(0)->level() <= cell->level(),
4084 ExcInternalError());
4085 first_child->set_neighbor(0, cell->neighbor(0));
4086 }
4087 else
4088 // left neighbor is refined
4089 {
4090 // set neighbor to cell on same level
4091 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
4092 first_child->set_neighbor(0,
4093 cell->neighbor(0)->child(nbnb));
4094
4095 // reset neighbor info of all right descendant
4096 // of the left neighbor of cell
4097 typename Triangulation<dim, spacedim>::cell_iterator
4098 left_neighbor = cell->neighbor(0);
4099 while (left_neighbor->has_children())
4100 {
4101 left_neighbor = left_neighbor->child(nbnb);
4102 left_neighbor->set_neighbor(nbnb, first_child);
4103 }
4104 }
4105
4106 // insert second child
4107 second_child->clear_children();
4108 second_child->set_bounding_object_indices(
4109 {next_unused_vertex, cell->vertex_index(1)});
4110 second_child->set_neighbor(0, first_child);
4111 second_child->set_material_id(cell->material_id());
4112 second_child->set_manifold_id(cell->manifold_id());
4113 second_child->set_subdomain_id(subdomainid);
4114 second_child->set_direction_flag(cell->direction_flag());
4115
4116 if (cell->neighbor(1).state() != IteratorState::valid)
4117 second_child->set_neighbor(1, cell->neighbor(1));
4118 else if (cell->neighbor(1)->is_active())
4119 {
4120 Assert(cell->neighbor(1)->level() <= cell->level(),
4121 ExcInternalError());
4122 second_child->set_neighbor(1, cell->neighbor(1));
4123 }
4124 else
4125 // right neighbor is refined same as above
4126 {
4127 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
4128 second_child->set_neighbor(
4129 1, cell->neighbor(1)->child(nbnb));
4130
4131 typename Triangulation<dim, spacedim>::cell_iterator
4132 right_neighbor = cell->neighbor(1);
4133 while (right_neighbor->has_children())
4134 {
4135 right_neighbor = right_neighbor->child(nbnb);
4136 right_neighbor->set_neighbor(nbnb, second_child);
4137 }
4138 }
4139 // inform all listeners that cell refinement is done
4140 triangulation.signals.post_refinement_on_cell(cell);
4141 }
4142 }
4143
4144 // in 1d, we can not have distorted children unless the parent
4145 // was already distorted (that is because we don't use
4146 // boundary information for 1d triangulations). so return an
4147 // empty list
4148 return typename Triangulation<1, spacedim>::DistortedCellList();
4149 }
4150
4151
4152 /**
4153 * A function that performs the refinement of a triangulation in
4154 * 2d.
4155 */
4156 template <int spacedim>
4157 static typename Triangulation<2, spacedim>::DistortedCellList
execute_refinementinternal::TriangulationImplementation::Implementation4158 execute_refinement(Triangulation<2, spacedim> &triangulation,
4159 const bool check_for_distorted_cells)
4160 {
4161 const unsigned int dim = 2;
4162
4163 // check whether a new level is needed we have to check for
4164 // this on the highest level only (on this, all used cells are
4165 // also active, so we only have to check for this)
4166 {
4167 typename Triangulation<dim, spacedim>::raw_cell_iterator
4168 cell = triangulation.begin_active(triangulation.levels.size() - 1),
4169 endc = triangulation.end();
4170 for (; cell != endc; ++cell)
4171 if (cell->used())
4172 if (cell->refine_flag_set())
4173 {
4174 triangulation.levels.push_back(
4175 std::make_unique<
4176 internal::TriangulationImplementation::TriaLevel>(dim));
4177 break;
4178 }
4179 }
4180
4181 // TODO[WB]: we clear user flags and pointers of lines; we're going
4182 // to use them to flag which lines need refinement
4183 for (typename Triangulation<dim, spacedim>::line_iterator line =
4184 triangulation.begin_line();
4185 line != triangulation.end_line();
4186 ++line)
4187 {
4188 line->clear_user_flag();
4189 line->clear_user_data();
4190 }
4191 // running over all cells and lines count the number
4192 // n_single_lines of lines which can be stored as single
4193 // lines, e.g. inner lines
4194 unsigned int n_single_lines = 0;
4195
4196 // New lines to be created: number lines which are stored in
4197 // pairs (the children of lines must be stored in pairs)
4198 unsigned int n_lines_in_pairs = 0;
4199
4200 // check how much space is needed on every level we need not
4201 // check the highest level since either - on the highest level
4202 // no cells are flagged for refinement - there are, but
4203 // prepare_refinement added another empty level
4204 unsigned int needed_vertices = 0;
4205 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4206 {
4207 // count number of flagged cells on this level and compute
4208 // how many new vertices and new lines will be needed
4209 unsigned int needed_cells = 0;
4210
4211 for (const auto &cell :
4212 triangulation.active_cell_iterators_on_level(level))
4213 if (cell->refine_flag_set())
4214 {
4215 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
4216 {
4217 needed_cells += 4;
4218
4219 // new vertex at center of cell is needed in any
4220 // case
4221 ++needed_vertices;
4222
4223 // the four inner lines can be stored as singles
4224 n_single_lines += 4;
4225 }
4226 else // cut_x || cut_y
4227 {
4228 // set the flag showing that anisotropic
4229 // refinement is used for at least one cell
4230 triangulation.anisotropic_refinement = true;
4231
4232 needed_cells += 2;
4233 // no vertex at center
4234
4235 // the inner line can be stored as single
4236 n_single_lines += 1;
4237 }
4238
4239 // mark all faces (lines) for refinement; checking
4240 // locally whether the neighbor would also like to
4241 // refine them is rather difficult for lines so we
4242 // only flag them and after visiting all cells, we
4243 // decide which lines need refinement;
4244 for (const unsigned int line_no :
4245 GeometryInfo<dim>::face_indices())
4246 {
4247 if (GeometryInfo<dim>::face_refinement_case(
4248 cell->refine_flag_set(), line_no) ==
4249 RefinementCase<1>::cut_x)
4250 {
4251 typename Triangulation<dim, spacedim>::line_iterator
4252 line = cell->line(line_no);
4253 if (line->has_children() == false)
4254 line->set_user_flag();
4255 }
4256 }
4257 }
4258
4259
4260 // count number of used cells on the next higher level
4261 const unsigned int used_cells =
4262 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4263 triangulation.levels[level + 1]->cells.used.end(),
4264 true);
4265
4266
4267 // reserve space for the used_cells cells already existing
4268 // on the next higher level as well as for the
4269 // needed_cells that will be created on that level
4270 reserve_space(*triangulation.levels[level + 1],
4271 used_cells + needed_cells,
4272 2,
4273 spacedim);
4274
4275 // reserve space for needed_cells new quads on the next
4276 // higher level
4277 reserve_space(triangulation.levels[level + 1]->cells,
4278 needed_cells,
4279 0);
4280 }
4281
4282 // now count the lines which were flagged for refinement
4283 for (typename Triangulation<dim, spacedim>::line_iterator line =
4284 triangulation.begin_line();
4285 line != triangulation.end_line();
4286 ++line)
4287 if (line->user_flag_set())
4288 {
4289 Assert(line->has_children() == false, ExcInternalError());
4290 n_lines_in_pairs += 2;
4291 needed_vertices += 1;
4292 }
4293 // reserve space for n_lines_in_pairs new lines. note, that
4294 // we can't reserve space for the single lines here as well,
4295 // as all the space reserved for lines in pairs would be
4296 // counted as unused and we would end up with too little space
4297 // to store all lines. memory reservation for n_single_lines
4298 // can only be done AFTER we refined the lines of the current
4299 // cells
4300 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4301
4302 // add to needed vertices how many vertices are already in use
4303 needed_vertices += std::count(triangulation.vertices_used.begin(),
4304 triangulation.vertices_used.end(),
4305 true);
4306 // if we need more vertices: create them, if not: leave the
4307 // array as is, since shrinking is not really possible because
4308 // some of the vertices at the end may be in use
4309 if (needed_vertices > triangulation.vertices.size())
4310 {
4311 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4312 triangulation.vertices_used.resize(needed_vertices, false);
4313 }
4314
4315
4316 // Do REFINEMENT on every level; exclude highest level as
4317 // above
4318
4319 // index of next unused vertex
4320 unsigned int next_unused_vertex = 0;
4321
4322 // first the refinement of lines. children are stored
4323 // pairwise
4324 {
4325 // only active objects can be refined further
4326 typename Triangulation<dim, spacedim>::active_line_iterator
4327 line = triangulation.begin_active_line(),
4328 endl = triangulation.end_line();
4329 typename Triangulation<dim, spacedim>::raw_line_iterator
4330 next_unused_line = triangulation.begin_raw_line();
4331
4332 for (; line != endl; ++line)
4333 if (line->user_flag_set())
4334 {
4335 // this line needs to be refined
4336
4337 // find the next unused vertex and set it
4338 // appropriately
4339 while (triangulation.vertices_used[next_unused_vertex] == true)
4340 ++next_unused_vertex;
4341 Assert(
4342 next_unused_vertex < triangulation.vertices.size(),
4343 ExcMessage(
4344 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
4345 triangulation.vertices_used[next_unused_vertex] = true;
4346
4347 triangulation.vertices[next_unused_vertex] = line->center(true);
4348
4349 // now that we created the right point, make up the
4350 // two child lines. To this end, find a pair of
4351 // unused lines
4352 bool pair_found = false;
4353 (void)pair_found;
4354 for (; next_unused_line != endl; ++next_unused_line)
4355 if (!next_unused_line->used() &&
4356 !(++next_unused_line)->used())
4357 {
4358 // go back to the first of the two unused
4359 // lines
4360 --next_unused_line;
4361 pair_found = true;
4362 break;
4363 }
4364 Assert(pair_found, ExcInternalError());
4365
4366 // there are now two consecutive unused lines, such
4367 // that the children of a line will be consecutive.
4368 // then set the child pointer of the present line
4369 line->set_children(0, next_unused_line->index());
4370
4371 // set the two new lines
4372 const typename Triangulation<dim, spacedim>::raw_line_iterator
4373 children[2] = {next_unused_line, ++next_unused_line};
4374 // some tests; if any of the iterators should be
4375 // invalid, then already dereferencing will fail
4376 Assert(
4377 children[0]->used() == false,
4378 ExcMessage(
4379 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4380 Assert(
4381 children[1]->used() == false,
4382 ExcMessage(
4383 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4384
4385 children[0]->set_bounding_object_indices(
4386 {line->vertex_index(0), next_unused_vertex});
4387 children[1]->set_bounding_object_indices(
4388 {next_unused_vertex, line->vertex_index(1)});
4389
4390 children[0]->set_used_flag();
4391 children[1]->set_used_flag();
4392 children[0]->clear_children();
4393 children[1]->clear_children();
4394 children[0]->clear_user_data();
4395 children[1]->clear_user_data();
4396 children[0]->clear_user_flag();
4397 children[1]->clear_user_flag();
4398
4399
4400 children[0]->set_boundary_id_internal(line->boundary_id());
4401 children[1]->set_boundary_id_internal(line->boundary_id());
4402
4403 children[0]->set_manifold_id(line->manifold_id());
4404 children[1]->set_manifold_id(line->manifold_id());
4405
4406 // finally clear flag indicating the need for
4407 // refinement
4408 line->clear_user_flag();
4409 }
4410 }
4411
4412
4413 // Now set up the new cells
4414
4415 // reserve space for inner lines (can be stored as single
4416 // lines)
4417 reserve_space(triangulation.faces->lines, 0, n_single_lines);
4418
4419 typename Triangulation<2, spacedim>::DistortedCellList
4420 cells_with_distorted_children;
4421
4422 // reset next_unused_line, as now also single empty places in
4423 // the vector can be used
4424 typename Triangulation<dim, spacedim>::raw_line_iterator
4425 next_unused_line = triangulation.begin_raw_line();
4426
4427 for (int level = 0;
4428 level < static_cast<int>(triangulation.levels.size()) - 1;
4429 ++level)
4430 {
4431 typename Triangulation<dim, spacedim>::raw_cell_iterator
4432 next_unused_cell = triangulation.begin_raw(level + 1);
4433
4434 for (const auto &cell :
4435 triangulation.active_cell_iterators_on_level(level))
4436 if (cell->refine_flag_set())
4437 {
4438 // set the user flag to indicate, that at least one
4439 // line is at the boundary
4440
4441 // TODO[Tobias Leicht] find a better place to set
4442 // this flag, so that we do not need so much time to
4443 // check each cell here
4444 if (cell->at_boundary())
4445 cell->set_user_flag();
4446
4447 // actually set up the children and update neighbor
4448 // information
4449 create_children(triangulation,
4450 next_unused_vertex,
4451 next_unused_line,
4452 next_unused_cell,
4453 cell);
4454
4455 if (check_for_distorted_cells &&
4456 has_distorted_children(
4457 cell,
4458 std::integral_constant<int, dim>(),
4459 std::integral_constant<int, spacedim>()))
4460 cells_with_distorted_children.distorted_cells.push_back(
4461 cell);
4462 // inform all listeners that cell refinement is done
4463 triangulation.signals.post_refinement_on_cell(cell);
4464 }
4465 }
4466
4467 return cells_with_distorted_children;
4468 }
4469
4470
4471 /**
4472 * A function that performs the refinement of a triangulation in
4473 * 3d.
4474 */
4475 template <int spacedim>
4476 static typename Triangulation<3, spacedim>::DistortedCellList
execute_refinementinternal::TriangulationImplementation::Implementation4477 execute_refinement(Triangulation<3, spacedim> &triangulation,
4478 const bool check_for_distorted_cells)
4479 {
4480 const unsigned int dim = 3;
4481
4482 // this function probably also works for spacedim>3 but it
4483 // isn't tested. it will probably be necessary to pull new
4484 // vertices onto the manifold just as we do for the other
4485 // functions above.
4486 Assert(spacedim == 3, ExcNotImplemented());
4487
4488 // check whether a new level is needed we have to check for
4489 // this on the highest level only (on this, all used cells are
4490 // also active, so we only have to check for this)
4491 {
4492 typename Triangulation<dim, spacedim>::raw_cell_iterator
4493 cell = triangulation.begin_active(triangulation.levels.size() - 1),
4494 endc = triangulation.end();
4495 for (; cell != endc; ++cell)
4496 if (cell->used())
4497 if (cell->refine_flag_set())
4498 {
4499 triangulation.levels.push_back(
4500 std::make_unique<
4501 internal::TriangulationImplementation::TriaLevel>(dim));
4502 break;
4503 }
4504 }
4505
4506
4507 // first clear user flags for quads and lines; we're going to
4508 // use them to flag which lines and quads need refinement
4509 triangulation.faces->quads.clear_user_data();
4510
4511 for (typename Triangulation<dim, spacedim>::line_iterator line =
4512 triangulation.begin_line();
4513 line != triangulation.end_line();
4514 ++line)
4515 line->clear_user_flag();
4516 for (typename Triangulation<dim, spacedim>::quad_iterator quad =
4517 triangulation.begin_quad();
4518 quad != triangulation.end_quad();
4519 ++quad)
4520 quad->clear_user_flag();
4521
4522 // create an array of face refine cases. User indices of faces
4523 // will be set to values corresponding with indices in this
4524 // array.
4525 const RefinementCase<dim - 1> face_refinement_cases[4] = {
4526 RefinementCase<dim - 1>::no_refinement,
4527 RefinementCase<dim - 1>::cut_x,
4528 RefinementCase<dim - 1>::cut_y,
4529 RefinementCase<dim - 1>::cut_xy};
4530
4531 // check how much space is needed on every level we need not
4532 // check the highest level since either
4533 // - on the highest level no cells are flagged for refinement
4534 // - there are, but prepare_refinement added another empty
4535 // level which then is the highest level
4536
4537 // variables to hold the number of newly to be created
4538 // vertices, lines and quads. as these are stored globally,
4539 // declare them outside the loop over al levels. we need lines
4540 // and quads in pairs for refinement of old ones and lines and
4541 // quads, that can be stored as single ones, as they are newly
4542 // created in the inside of an existing cell
4543 unsigned int needed_vertices = 0;
4544 unsigned int needed_lines_single = 0;
4545 unsigned int needed_quads_single = 0;
4546 unsigned int needed_lines_pair = 0;
4547 unsigned int needed_quads_pair = 0;
4548 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4549 {
4550 // count number of flagged cells on this level and compute
4551 // how many new vertices and new lines will be needed
4552 unsigned int new_cells = 0;
4553
4554 for (const auto &acell :
4555 triangulation.active_cell_iterators_on_level(level))
4556 if (acell->refine_flag_set())
4557 {
4558 RefinementCase<dim> ref_case = acell->refine_flag_set();
4559
4560 // now for interior vertices, lines and quads, which
4561 // are needed in any case
4562 if (ref_case == RefinementCase<dim>::cut_x ||
4563 ref_case == RefinementCase<dim>::cut_y ||
4564 ref_case == RefinementCase<dim>::cut_z)
4565 {
4566 ++needed_quads_single;
4567 new_cells += 2;
4568 triangulation.anisotropic_refinement = true;
4569 }
4570 else if (ref_case == RefinementCase<dim>::cut_xy ||
4571 ref_case == RefinementCase<dim>::cut_xz ||
4572 ref_case == RefinementCase<dim>::cut_yz)
4573 {
4574 ++needed_lines_single;
4575 needed_quads_single += 4;
4576 new_cells += 4;
4577 triangulation.anisotropic_refinement = true;
4578 }
4579 else if (ref_case == RefinementCase<dim>::cut_xyz)
4580 {
4581 ++needed_vertices;
4582 needed_lines_single += 6;
4583 needed_quads_single += 12;
4584 new_cells += 8;
4585 }
4586 else
4587 {
4588 // we should never get here
4589 Assert(false, ExcInternalError());
4590 }
4591
4592 // mark all faces for refinement; checking locally
4593 // if and how the neighbor would like to refine
4594 // these is difficult so we only flag them and after
4595 // visiting all cells, we decide which faces need
4596 // which refinement;
4597 for (const unsigned int face :
4598 GeometryInfo<dim>::face_indices())
4599 {
4600 typename Triangulation<dim, spacedim>::face_iterator
4601 aface = acell->face(face);
4602 // get the RefineCase this faces has for the
4603 // given RefineCase of the cell
4604 RefinementCase<dim - 1> face_ref_case =
4605 GeometryInfo<dim>::face_refinement_case(
4606 ref_case,
4607 face,
4608 acell->face_orientation(face),
4609 acell->face_flip(face),
4610 acell->face_rotation(face));
4611 // only do something, if this face has to be
4612 // refined
4613 if (face_ref_case)
4614 {
4615 if (face_ref_case ==
4616 RefinementCase<dim - 1>::isotropic_refinement)
4617 {
4618 if (aface->number_of_children() < 4)
4619 // we use user_flags to denote needed
4620 // isotropic refinement
4621 aface->set_user_flag();
4622 }
4623 else if (aface->refinement_case() != face_ref_case)
4624 // we use user_indices to denote needed
4625 // anisotropic refinement. note, that we
4626 // can have at most one anisotropic
4627 // refinement case for this face, as
4628 // otherwise prepare_refinement() would
4629 // have changed one of the cells to yield
4630 // isotropic refinement at this
4631 // face. therefore we set the user_index
4632 // uniquely
4633 {
4634 Assert(aface->refinement_case() ==
4635 RefinementCase<
4636 dim - 1>::isotropic_refinement ||
4637 aface->refinement_case() ==
4638 RefinementCase<dim - 1>::no_refinement,
4639 ExcInternalError());
4640 aface->set_user_index(face_ref_case);
4641 }
4642 }
4643 } // for all faces
4644
4645 // flag all lines, that have to be refined
4646 for (unsigned int line = 0;
4647 line < GeometryInfo<dim>::lines_per_cell;
4648 ++line)
4649 if (GeometryInfo<dim>::line_refinement_case(ref_case,
4650 line) &&
4651 !acell->line(line)->has_children())
4652 acell->line(line)->set_user_flag();
4653
4654 } // if refine_flag set and for all cells on this level
4655
4656
4657 // count number of used cells on the next higher level
4658 const unsigned int used_cells =
4659 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4660 triangulation.levels[level + 1]->cells.used.end(),
4661 true);
4662
4663
4664 // reserve space for the used_cells cells already existing
4665 // on the next higher level as well as for the
4666 // 8*flagged_cells that will be created on that level
4667 reserve_space(*triangulation.levels[level + 1],
4668 used_cells + new_cells,
4669 3,
4670 spacedim);
4671 // reserve space for 8*flagged_cells new hexes on the next
4672 // higher level
4673 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
4674 } // for all levels
4675 // now count the quads and lines which were flagged for
4676 // refinement
4677 for (typename Triangulation<dim, spacedim>::quad_iterator quad =
4678 triangulation.begin_quad();
4679 quad != triangulation.end_quad();
4680 ++quad)
4681 {
4682 if (quad->user_flag_set())
4683 {
4684 // isotropic refinement: 1 interior vertex, 4 quads
4685 // and 4 interior lines. we store the interior lines
4686 // in pairs in case the face is already or will be
4687 // refined anisotropically
4688 needed_quads_pair += 4;
4689 needed_lines_pair += 4;
4690 needed_vertices += 1;
4691 }
4692 if (quad->user_index())
4693 {
4694 // anisotropic refinement: 1 interior
4695 // line and two quads
4696 needed_quads_pair += 2;
4697 needed_lines_single += 1;
4698 // there is a kind of complicated situation here which
4699 // requires our attention. if the quad is refined
4700 // isotropcally, two of the interior lines will get a
4701 // new mother line - the interior line of our
4702 // anisotropically refined quad. if those two lines
4703 // are not consecutive, we cannot do so and have to
4704 // replace them by two lines that are consecutive. we
4705 // try to avoid that situation, but it may happen
4706 // nevertheless through repeated refinement and
4707 // coarsening. thus we have to check here, as we will
4708 // need some additional space to store those new lines
4709 // in case we need them...
4710 if (quad->has_children())
4711 {
4712 Assert(quad->refinement_case() ==
4713 RefinementCase<dim - 1>::isotropic_refinement,
4714 ExcInternalError());
4715 if ((face_refinement_cases[quad->user_index()] ==
4716 RefinementCase<dim - 1>::cut_x &&
4717 (quad->child(0)->line_index(1) + 1 !=
4718 quad->child(2)->line_index(1))) ||
4719 (face_refinement_cases[quad->user_index()] ==
4720 RefinementCase<dim - 1>::cut_y &&
4721 (quad->child(0)->line_index(3) + 1 !=
4722 quad->child(1)->line_index(3))))
4723 needed_lines_pair += 2;
4724 }
4725 }
4726 }
4727
4728 for (typename Triangulation<dim, spacedim>::line_iterator line =
4729 triangulation.begin_line();
4730 line != triangulation.end_line();
4731 ++line)
4732 if (line->user_flag_set())
4733 {
4734 needed_lines_pair += 2;
4735 needed_vertices += 1;
4736 }
4737
4738 // reserve space for needed_lines new lines stored in pairs
4739 reserve_space(triangulation.faces->lines,
4740 needed_lines_pair,
4741 needed_lines_single);
4742 // reserve space for needed_quads new quads stored in pairs
4743 reserve_space(*triangulation.faces,
4744 needed_quads_pair,
4745 needed_quads_single);
4746 reserve_space(triangulation.faces->quads,
4747 needed_quads_pair,
4748 needed_quads_single);
4749
4750
4751 // add to needed vertices how many vertices are already in use
4752 needed_vertices += std::count(triangulation.vertices_used.begin(),
4753 triangulation.vertices_used.end(),
4754 true);
4755 // if we need more vertices: create them, if not: leave the
4756 // array as is, since shrinking is not really possible because
4757 // some of the vertices at the end may be in use
4758 if (needed_vertices > triangulation.vertices.size())
4759 {
4760 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4761 triangulation.vertices_used.resize(needed_vertices, false);
4762 }
4763
4764
4765 ///////////////////////////////////////////
4766 // Before we start with the actual refinement, we do some
4767 // sanity checks if in debug mode. especially, we try to catch
4768 // the notorious problem with lines being twice refined,
4769 // i.e. there are cells adjacent at one line ("around the
4770 // edge", but not at a face), with two cells differing by more
4771 // than one refinement level
4772 //
4773 // this check is very simple to implement here, since we have
4774 // all lines flagged if they shall be refined
4775 #ifdef DEBUG
4776 for (const auto &cell : triangulation.active_cell_iterators())
4777 if (!cell->refine_flag_set())
4778 for (unsigned int line = 0;
4779 line < GeometryInfo<dim>::lines_per_cell;
4780 ++line)
4781 if (cell->line(line)->has_children())
4782 for (unsigned int c = 0; c < 2; ++c)
4783 Assert(cell->line(line)->child(c)->user_flag_set() == false,
4784 ExcInternalError());
4785 #endif
4786
4787 ///////////////////////////////////////////
4788 // Do refinement on every level
4789 //
4790 // To make life a bit easier, we first refine those lines and
4791 // quads that were flagged for refinement and then compose the
4792 // newly to be created cells.
4793 //
4794 // index of next unused vertex
4795 unsigned int next_unused_vertex = 0;
4796
4797 // first for lines
4798 {
4799 // only active objects can be refined further
4800 typename Triangulation<dim, spacedim>::active_line_iterator
4801 line = triangulation.begin_active_line(),
4802 endl = triangulation.end_line();
4803 typename Triangulation<dim, spacedim>::raw_line_iterator
4804 next_unused_line = triangulation.begin_raw_line();
4805
4806 for (; line != endl; ++line)
4807 if (line->user_flag_set())
4808 {
4809 // this line needs to be refined
4810
4811 // find the next unused vertex and set it
4812 // appropriately
4813 while (triangulation.vertices_used[next_unused_vertex] == true)
4814 ++next_unused_vertex;
4815 Assert(
4816 next_unused_vertex < triangulation.vertices.size(),
4817 ExcMessage(
4818 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
4819 triangulation.vertices_used[next_unused_vertex] = true;
4820
4821 triangulation.vertices[next_unused_vertex] = line->center(true);
4822
4823 // now that we created the right point, make up the
4824 // two child lines (++ takes care of the end of the
4825 // vector)
4826 next_unused_line =
4827 triangulation.faces->lines.template next_free_pair_object<1>(
4828 triangulation);
4829 Assert(next_unused_line.state() == IteratorState::valid,
4830 ExcInternalError());
4831
4832 // now we found two consecutive unused lines, such
4833 // that the children of a line will be consecutive.
4834 // then set the child pointer of the present line
4835 line->set_children(0, next_unused_line->index());
4836
4837 // set the two new lines
4838 const typename Triangulation<dim, spacedim>::raw_line_iterator
4839 children[2] = {next_unused_line, ++next_unused_line};
4840
4841 // some tests; if any of the iterators should be
4842 // invalid, then already dereferencing will fail
4843 Assert(
4844 children[0]->used() == false,
4845 ExcMessage(
4846 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4847 Assert(
4848 children[1]->used() == false,
4849 ExcMessage(
4850 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4851
4852 children[0]->set_bounding_object_indices(
4853 {line->vertex_index(0), next_unused_vertex});
4854 children[1]->set_bounding_object_indices(
4855 {next_unused_vertex, line->vertex_index(1)});
4856
4857 children[0]->set_used_flag();
4858 children[1]->set_used_flag();
4859 children[0]->clear_children();
4860 children[1]->clear_children();
4861 children[0]->clear_user_data();
4862 children[1]->clear_user_data();
4863 children[0]->clear_user_flag();
4864 children[1]->clear_user_flag();
4865
4866 children[0]->set_boundary_id_internal(line->boundary_id());
4867 children[1]->set_boundary_id_internal(line->boundary_id());
4868
4869 children[0]->set_manifold_id(line->manifold_id());
4870 children[1]->set_manifold_id(line->manifold_id());
4871
4872 // finally clear flag
4873 // indicating the need
4874 // for refinement
4875 line->clear_user_flag();
4876 }
4877 }
4878
4879
4880 ///////////////////////////////////////
4881 // now refine marked quads
4882 ///////////////////////////////////////
4883
4884 // here we encounter several cases:
4885
4886 // a) the quad is unrefined and shall be refined isotropically
4887
4888 // b) the quad is unrefined and shall be refined
4889 // anisotropically
4890
4891 // c) the quad is unrefined and shall be refined both
4892 // anisotropically and isotropically (this is reduced to case
4893 // b) and then case b) for the children again)
4894
4895 // d) the quad is refined anisotropically and shall be refined
4896 // isotropically (this is reduced to case b) for the
4897 // anisotropic children)
4898
4899 // e) the quad is refined isotropically and shall be refined
4900 // anisotropically (this is transformed to case c), however we
4901 // might have to renumber/rename children...)
4902
4903 // we need a loop in cases c) and d), as the anisotropic
4904 // children migt have a lower index than the mother quad
4905 for (unsigned int loop = 0; loop < 2; ++loop)
4906 {
4907 // usually, only active objects can be refined
4908 // further. however, in cases d) and e) that is not true,
4909 // so we have to use 'normal' iterators here
4910 typename Triangulation<dim, spacedim>::quad_iterator
4911 quad = triangulation.begin_quad(),
4912 endq = triangulation.end_quad();
4913 typename Triangulation<dim, spacedim>::raw_line_iterator
4914 next_unused_line = triangulation.begin_raw_line();
4915 typename Triangulation<dim, spacedim>::raw_quad_iterator
4916 next_unused_quad = triangulation.begin_raw_quad();
4917
4918 for (; quad != endq; ++quad)
4919 {
4920 if (quad->user_index())
4921 {
4922 RefinementCase<dim - 1> aniso_quad_ref_case =
4923 face_refinement_cases[quad->user_index()];
4924 // there is one unlikely event here, where we
4925 // already have refind the face: if the face was
4926 // refined anisotropically and we want to refine
4927 // it isotropically, both children are flagged for
4928 // anisotropic refinement. however, if those
4929 // children were already flagged for anisotropic
4930 // refinement, they might already be processed and
4931 // refined.
4932 if (aniso_quad_ref_case == quad->refinement_case())
4933 continue;
4934
4935 Assert(quad->refinement_case() ==
4936 RefinementCase<dim - 1>::cut_xy ||
4937 quad->refinement_case() ==
4938 RefinementCase<dim - 1>::no_refinement,
4939 ExcInternalError());
4940
4941 // this quad needs to be refined anisotropically
4942 Assert(quad->user_index() ==
4943 RefinementCase<dim - 1>::cut_x ||
4944 quad->user_index() ==
4945 RefinementCase<dim - 1>::cut_y,
4946 ExcInternalError());
4947
4948 // make the new line interior to the quad
4949 typename Triangulation<dim, spacedim>::raw_line_iterator
4950 new_line;
4951
4952 new_line =
4953 triangulation.faces->lines
4954 .template next_free_single_object<1>(triangulation);
4955 Assert(
4956 new_line->used() == false,
4957 ExcMessage(
4958 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4959
4960 // first collect the
4961 // indices of the vertices:
4962 // *--1--*
4963 // | | |
4964 // | | | cut_x
4965 // | | |
4966 // *--0--*
4967 //
4968 // *-----*
4969 // | |
4970 // 0-----1 cut_y
4971 // | |
4972 // *-----*
4973 unsigned int vertex_indices[2];
4974 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
4975 {
4976 vertex_indices[0] =
4977 quad->line(2)->child(0)->vertex_index(1);
4978 vertex_indices[1] =
4979 quad->line(3)->child(0)->vertex_index(1);
4980 }
4981 else
4982 {
4983 vertex_indices[0] =
4984 quad->line(0)->child(0)->vertex_index(1);
4985 vertex_indices[1] =
4986 quad->line(1)->child(0)->vertex_index(1);
4987 }
4988
4989 new_line->set_bounding_object_indices(
4990 {vertex_indices[0], vertex_indices[1]});
4991 new_line->set_used_flag();
4992 new_line->clear_user_flag();
4993 new_line->clear_user_data();
4994 new_line->clear_children();
4995 new_line->set_boundary_id_internal(quad->boundary_id());
4996 new_line->set_manifold_id(quad->manifold_id());
4997
4998 // child 0 and 1 of a line are switched if the
4999 // line orientation is false. set up a miniature
5000 // table, indicating which child to take for line
5001 // orientations false and true. first index: child
5002 // index in standard orientation, second index:
5003 // line orientation
5004 const unsigned int index[2][2] = {
5005 {1, 0}, // child 0, line_orientation=false and true
5006 {0, 1}}; // child 1, line_orientation=false and true
5007
5008 // find some space (consecutive) for the two newly
5009 // to be created quads.
5010 typename Triangulation<dim, spacedim>::raw_quad_iterator
5011 new_quads[2];
5012
5013 next_unused_quad =
5014 triangulation.faces->quads
5015 .template next_free_pair_object<2>(triangulation);
5016 new_quads[0] = next_unused_quad;
5017 Assert(
5018 new_quads[0]->used() == false,
5019 ExcMessage(
5020 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5021
5022 ++next_unused_quad;
5023 new_quads[1] = next_unused_quad;
5024 Assert(
5025 new_quads[1]->used() == false,
5026 ExcMessage(
5027 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5028
5029
5030 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
5031 {
5032 new_quads[0]->set_bounding_object_indices(
5033 {static_cast<int>(quad->line_index(0)),
5034 new_line->index(),
5035 quad->line(2)
5036 ->child(index[0][quad->line_orientation(2)])
5037 ->index(),
5038 quad->line(3)
5039 ->child(index[0][quad->line_orientation(3)])
5040 ->index()});
5041 new_quads[1]->set_bounding_object_indices(
5042 {new_line->index(),
5043 static_cast<int>(quad->line_index(1)),
5044 quad->line(2)
5045 ->child(index[1][quad->line_orientation(2)])
5046 ->index(),
5047 quad->line(3)
5048 ->child(index[1][quad->line_orientation(3)])
5049 ->index()});
5050 }
5051 else
5052 {
5053 new_quads[0]->set_bounding_object_indices(
5054 {quad->line(0)
5055 ->child(index[0][quad->line_orientation(0)])
5056 ->index(),
5057 quad->line(1)
5058 ->child(index[0][quad->line_orientation(1)])
5059 ->index(),
5060 static_cast<int>(quad->line_index(2)),
5061 new_line->index()});
5062 new_quads[1]->set_bounding_object_indices(
5063 {quad->line(0)
5064 ->child(index[1][quad->line_orientation(0)])
5065 ->index(),
5066 quad->line(1)
5067 ->child(index[1][quad->line_orientation(1)])
5068 ->index(),
5069 new_line->index(),
5070 static_cast<int>(quad->line_index(3))});
5071 }
5072
5073 for (const auto &new_quad : new_quads)
5074 {
5075 new_quad->set_used_flag();
5076 new_quad->clear_user_flag();
5077 new_quad->clear_user_data();
5078 new_quad->clear_children();
5079 new_quad->set_boundary_id_internal(quad->boundary_id());
5080 new_quad->set_manifold_id(quad->manifold_id());
5081 // set all line orientations to true, change
5082 // this after the loop, as we have to consider
5083 // different lines for each child
5084 for (unsigned int j = 0;
5085 j < GeometryInfo<dim>::lines_per_face;
5086 ++j)
5087 new_quad->set_line_orientation(j, true);
5088 }
5089 // now set the line orientation of children of
5090 // outer lines correctly, the lines in the
5091 // interior of the refined quad are automatically
5092 // oriented conforming to the standard
5093 new_quads[0]->set_line_orientation(
5094 0, quad->line_orientation(0));
5095 new_quads[0]->set_line_orientation(
5096 2, quad->line_orientation(2));
5097 new_quads[1]->set_line_orientation(
5098 1, quad->line_orientation(1));
5099 new_quads[1]->set_line_orientation(
5100 3, quad->line_orientation(3));
5101 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
5102 {
5103 new_quads[0]->set_line_orientation(
5104 3, quad->line_orientation(3));
5105 new_quads[1]->set_line_orientation(
5106 2, quad->line_orientation(2));
5107 }
5108 else
5109 {
5110 new_quads[0]->set_line_orientation(
5111 1, quad->line_orientation(1));
5112 new_quads[1]->set_line_orientation(
5113 0, quad->line_orientation(0));
5114 }
5115
5116 // test, whether this face is refined
5117 // isotropically already. if so, set the correct
5118 // children pointers.
5119 if (quad->refinement_case() ==
5120 RefinementCase<dim - 1>::cut_xy)
5121 {
5122 // we will put a new refinemnt level of
5123 // anisotropic refinement between the
5124 // unrefined and isotropically refined quad
5125 // ending up with the same fine quads but
5126 // introducing anisotropically refined ones as
5127 // children of the unrefined quad and mother
5128 // cells of the original fine ones.
5129
5130 // this process includes the creation of a new
5131 // middle line which we will assign as the
5132 // mother line of two of the existing inner
5133 // lines. If those inner lines are not
5134 // consecutive in memory, we won't find them
5135 // later on, so we have to create new ones
5136 // instead and replace all occurrences of the
5137 // old ones with those new ones. As this is
5138 // kind of ugly, we hope we don't have to do
5139 // it often...
5140 typename Triangulation<dim, spacedim>::line_iterator
5141 old_child[2];
5142 if (aniso_quad_ref_case ==
5143 RefinementCase<dim - 1>::cut_x)
5144 {
5145 old_child[0] = quad->child(0)->line(1);
5146 old_child[1] = quad->child(2)->line(1);
5147 }
5148 else
5149 {
5150 Assert(aniso_quad_ref_case ==
5151 RefinementCase<dim - 1>::cut_y,
5152 ExcInternalError());
5153
5154 old_child[0] = quad->child(0)->line(3);
5155 old_child[1] = quad->child(1)->line(3);
5156 }
5157
5158 if (old_child[0]->index() + 1 != old_child[1]->index())
5159 {
5160 // this is exactly the ugly case we taked
5161 // about. so, no coimplaining, lets get
5162 // two new lines and copy all info
5163 typename Triangulation<dim,
5164 spacedim>::raw_line_iterator
5165 new_child[2];
5166
5167 new_child[0] = new_child[1] =
5168 triangulation.faces->lines
5169 .template next_free_pair_object<1>(
5170 triangulation);
5171 ++new_child[1];
5172
5173 new_child[0]->set_used_flag();
5174 new_child[1]->set_used_flag();
5175
5176 const int old_index_0 = old_child[0]->index(),
5177 old_index_1 = old_child[1]->index(),
5178 new_index_0 = new_child[0]->index(),
5179 new_index_1 = new_child[1]->index();
5180
5181 // loop over all quads and replace the old
5182 // lines
5183 for (unsigned int q = 0;
5184 q < triangulation.faces->quads.n_objects();
5185 ++q)
5186 for (unsigned int l = 0;
5187 l < GeometryInfo<dim>::lines_per_face;
5188 ++l)
5189 {
5190 const int this_index =
5191 triangulation.faces->quads
5192 .get_bounding_object_indices(q)[l];
5193 if (this_index == old_index_0)
5194 triangulation.faces->quads
5195 .get_bounding_object_indices(q)[l] =
5196 new_index_0;
5197 else if (this_index == old_index_1)
5198 triangulation.faces->quads
5199 .get_bounding_object_indices(q)[l] =
5200 new_index_1;
5201 }
5202 // now we have to copy all information of
5203 // the two lines
5204 for (unsigned int i = 0; i < 2; ++i)
5205 {
5206 Assert(!old_child[i]->has_children(),
5207 ExcInternalError());
5208
5209 new_child[i]->set_bounding_object_indices(
5210 {old_child[i]->vertex_index(0),
5211 old_child[i]->vertex_index(1)});
5212 new_child[i]->set_boundary_id_internal(
5213 old_child[i]->boundary_id());
5214 new_child[i]->set_manifold_id(
5215 old_child[i]->manifold_id());
5216 new_child[i]->set_user_index(
5217 old_child[i]->user_index());
5218 if (old_child[i]->user_flag_set())
5219 new_child[i]->set_user_flag();
5220 else
5221 new_child[i]->clear_user_flag();
5222
5223 new_child[i]->clear_children();
5224
5225 old_child[i]->clear_user_flag();
5226 old_child[i]->clear_user_index();
5227 old_child[i]->clear_used_flag();
5228 }
5229 }
5230 // now that we cared about the lines, go on
5231 // with the quads themselves, where we might
5232 // encounter similar situations...
5233 if (aniso_quad_ref_case ==
5234 RefinementCase<dim - 1>::cut_x)
5235 {
5236 new_line->set_children(
5237 0, quad->child(0)->line_index(1));
5238 Assert(new_line->child(1) ==
5239 quad->child(2)->line(1),
5240 ExcInternalError());
5241 // now evereything is quite
5242 // complicated. we have the children
5243 // numbered according to
5244 //
5245 // *---*---*
5246 // |n+2|n+3|
5247 // *---*---*
5248 // | n |n+1|
5249 // *---*---*
5250 //
5251 // from the original isotropic
5252 // refinement. we have to reorder them as
5253 //
5254 // *---*---*
5255 // |n+1|n+3|
5256 // *---*---*
5257 // | n |n+2|
5258 // *---*---*
5259 //
5260 // such that n and n+1 are consecutive
5261 // children of m and n+2 and n+3 are
5262 // consecutive children of m+1, where m
5263 // and m+1 are given as in
5264 //
5265 // *---*---*
5266 // | | |
5267 // | m |m+1|
5268 // | | |
5269 // *---*---*
5270 //
5271 // this is a bit ugly, of course: loop
5272 // over all cells on all levels and look
5273 // for faces n+1 (switch_1) and n+2
5274 // (switch_2).
5275 const typename Triangulation<dim, spacedim>::
5276 quad_iterator switch_1 = quad->child(1),
5277 switch_2 = quad->child(2);
5278 const int switch_1_index = switch_1->index();
5279 const int switch_2_index = switch_2->index();
5280 for (unsigned int l = 0;
5281 l < triangulation.levels.size();
5282 ++l)
5283 for (unsigned int h = 0;
5284 h <
5285 triangulation.levels[l]->cells.n_objects();
5286 ++h)
5287 for (const unsigned int q :
5288 GeometryInfo<dim>::face_indices())
5289 {
5290 const int face_index =
5291 triangulation.levels[l]
5292 ->cells.get_bounding_object_indices(
5293 h)[q];
5294 if (face_index == switch_1_index)
5295 triangulation.levels[l]
5296 ->cells.get_bounding_object_indices(
5297 h)[q] = switch_2_index;
5298 else if (face_index == switch_2_index)
5299 triangulation.levels[l]
5300 ->cells.get_bounding_object_indices(
5301 h)[q] = switch_1_index;
5302 }
5303 // now we have to copy all information of
5304 // the two quads
5305 const unsigned int switch_1_lines[4] = {
5306 switch_1->line_index(0),
5307 switch_1->line_index(1),
5308 switch_1->line_index(2),
5309 switch_1->line_index(3)};
5310 const bool switch_1_line_orientations[4] = {
5311 switch_1->line_orientation(0),
5312 switch_1->line_orientation(1),
5313 switch_1->line_orientation(2),
5314 switch_1->line_orientation(3)};
5315 const types::boundary_id switch_1_boundary_id =
5316 switch_1->boundary_id();
5317 const unsigned int switch_1_user_index =
5318 switch_1->user_index();
5319 const bool switch_1_user_flag =
5320 switch_1->user_flag_set();
5321 const RefinementCase<dim - 1>
5322 switch_1_refinement_case =
5323 switch_1->refinement_case();
5324 const int switch_1_first_child_pair =
5325 (switch_1_refinement_case ?
5326 switch_1->child_index(0) :
5327 -1);
5328 const int switch_1_second_child_pair =
5329 (switch_1_refinement_case ==
5330 RefinementCase<dim - 1>::cut_xy ?
5331 switch_1->child_index(2) :
5332 -1);
5333
5334 switch_1->set_bounding_object_indices(
5335 {switch_2->line_index(0),
5336 switch_2->line_index(1),
5337 switch_2->line_index(2),
5338 switch_2->line_index(3)});
5339 switch_1->set_line_orientation(
5340 0, switch_2->line_orientation(0));
5341 switch_1->set_line_orientation(
5342 1, switch_2->line_orientation(1));
5343 switch_1->set_line_orientation(
5344 2, switch_2->line_orientation(2));
5345 switch_1->set_line_orientation(
5346 3, switch_2->line_orientation(3));
5347 switch_1->set_boundary_id_internal(
5348 switch_2->boundary_id());
5349 switch_1->set_manifold_id(switch_2->manifold_id());
5350 switch_1->set_user_index(switch_2->user_index());
5351 if (switch_2->user_flag_set())
5352 switch_1->set_user_flag();
5353 else
5354 switch_1->clear_user_flag();
5355 switch_1->clear_refinement_case();
5356 switch_1->set_refinement_case(
5357 switch_2->refinement_case());
5358 switch_1->clear_children();
5359 if (switch_2->refinement_case())
5360 switch_1->set_children(0,
5361 switch_2->child_index(0));
5362 if (switch_2->refinement_case() ==
5363 RefinementCase<dim - 1>::cut_xy)
5364 switch_1->set_children(2,
5365 switch_2->child_index(2));
5366
5367 switch_2->set_bounding_object_indices(
5368 {switch_1_lines[0],
5369 switch_1_lines[1],
5370 switch_1_lines[2],
5371 switch_1_lines[3]});
5372 switch_2->set_line_orientation(
5373 0, switch_1_line_orientations[0]);
5374 switch_2->set_line_orientation(
5375 1, switch_1_line_orientations[1]);
5376 switch_2->set_line_orientation(
5377 2, switch_1_line_orientations[2]);
5378 switch_2->set_line_orientation(
5379 3, switch_1_line_orientations[3]);
5380 switch_2->set_boundary_id_internal(
5381 switch_1_boundary_id);
5382 switch_2->set_manifold_id(switch_1->manifold_id());
5383 switch_2->set_user_index(switch_1_user_index);
5384 if (switch_1_user_flag)
5385 switch_2->set_user_flag();
5386 else
5387 switch_2->clear_user_flag();
5388 switch_2->clear_refinement_case();
5389 switch_2->set_refinement_case(
5390 switch_1_refinement_case);
5391 switch_2->clear_children();
5392 switch_2->set_children(0,
5393 switch_1_first_child_pair);
5394 switch_2->set_children(2,
5395 switch_1_second_child_pair);
5396
5397 new_quads[0]->set_refinement_case(
5398 RefinementCase<2>::cut_y);
5399 new_quads[0]->set_children(0, quad->child_index(0));
5400 new_quads[1]->set_refinement_case(
5401 RefinementCase<2>::cut_y);
5402 new_quads[1]->set_children(0, quad->child_index(2));
5403 }
5404 else
5405 {
5406 new_quads[0]->set_refinement_case(
5407 RefinementCase<2>::cut_x);
5408 new_quads[0]->set_children(0, quad->child_index(0));
5409 new_quads[1]->set_refinement_case(
5410 RefinementCase<2>::cut_x);
5411 new_quads[1]->set_children(0, quad->child_index(2));
5412 new_line->set_children(
5413 0, quad->child(0)->line_index(3));
5414 Assert(new_line->child(1) ==
5415 quad->child(1)->line(3),
5416 ExcInternalError());
5417 }
5418 quad->clear_children();
5419 }
5420
5421 // note these quads as children to the present one
5422 quad->set_children(0, new_quads[0]->index());
5423
5424 quad->set_refinement_case(aniso_quad_ref_case);
5425
5426 // finally clear flag indicating the need for
5427 // refinement
5428 quad->clear_user_data();
5429 } // if (anisotropic refinement)
5430
5431 if (quad->user_flag_set())
5432 {
5433 // this quad needs to be refined isotropically
5434
5435 // first of all: we only get here in the first run
5436 // of the loop
5437 Assert(loop == 0, ExcInternalError());
5438
5439 // find the next unused vertex. we'll need this in
5440 // any case
5441 while (triangulation.vertices_used[next_unused_vertex] ==
5442 true)
5443 ++next_unused_vertex;
5444 Assert(
5445 next_unused_vertex < triangulation.vertices.size(),
5446 ExcMessage(
5447 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
5448
5449 // now: if the quad is refined anisotropically
5450 // already, set the anisotropic refinement flag
5451 // for both children. Additionally, we have to
5452 // refine the inner line, as it is an outer line
5453 // of the two (anisotropic) children
5454 const RefinementCase<dim - 1> quad_ref_case =
5455 quad->refinement_case();
5456
5457 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
5458 quad_ref_case == RefinementCase<dim - 1>::cut_y)
5459 {
5460 // set the 'opposite' refine case for children
5461 quad->child(0)->set_user_index(
5462 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
5463 quad->child(1)->set_user_index(
5464 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
5465 // refine the inner line
5466 typename Triangulation<dim, spacedim>::line_iterator
5467 middle_line;
5468 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
5469 middle_line = quad->child(0)->line(1);
5470 else
5471 middle_line = quad->child(0)->line(3);
5472
5473 // if the face has been refined
5474 // anisotropically in the last refinement step
5475 // it might be, that it is flagged already and
5476 // that the middle line is thus refined
5477 // already. if not create children.
5478 if (!middle_line->has_children())
5479 {
5480 // set the middle vertex
5481 // appropriately. double refinement of
5482 // quads can only happen in the interior
5483 // of the domain, so we need not care
5484 // about boundary quads here
5485 triangulation.vertices[next_unused_vertex] =
5486 middle_line->center(true);
5487 triangulation.vertices_used[next_unused_vertex] =
5488 true;
5489
5490 // now search a slot for the two
5491 // child lines
5492 next_unused_line =
5493 triangulation.faces->lines
5494 .template next_free_pair_object<1>(
5495 triangulation);
5496
5497 // set the child pointer of the present
5498 // line
5499 middle_line->set_children(
5500 0, next_unused_line->index());
5501
5502 // set the two new lines
5503 const typename Triangulation<dim, spacedim>::
5504 raw_line_iterator children[2] = {
5505 next_unused_line, ++next_unused_line};
5506
5507 // some tests; if any of the iterators
5508 // should be invalid, then already
5509 // dereferencing will fail
5510 Assert(
5511 children[0]->used() == false,
5512 ExcMessage(
5513 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5514 Assert(
5515 children[1]->used() == false,
5516 ExcMessage(
5517 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5518
5519 children[0]->set_bounding_object_indices(
5520 {middle_line->vertex_index(0),
5521 next_unused_vertex});
5522 children[1]->set_bounding_object_indices(
5523 {next_unused_vertex,
5524 middle_line->vertex_index(1)});
5525
5526 children[0]->set_used_flag();
5527 children[1]->set_used_flag();
5528 children[0]->clear_children();
5529 children[1]->clear_children();
5530 children[0]->clear_user_data();
5531 children[1]->clear_user_data();
5532 children[0]->clear_user_flag();
5533 children[1]->clear_user_flag();
5534
5535 children[0]->set_boundary_id_internal(
5536 middle_line->boundary_id());
5537 children[1]->set_boundary_id_internal(
5538 middle_line->boundary_id());
5539
5540 children[0]->set_manifold_id(
5541 middle_line->manifold_id());
5542 children[1]->set_manifold_id(
5543 middle_line->manifold_id());
5544 }
5545 // now remove the flag from the quad and go to
5546 // the next quad, the actual refinement of the
5547 // quad takes place later on in this pass of
5548 // the loop or in the next one
5549 quad->clear_user_flag();
5550 continue;
5551 } // if (several refinement cases)
5552
5553 // if we got here, we have an unrefined quad and
5554 // have to do the usual work like in an purely
5555 // isotropic refinement
5556 Assert(quad_ref_case ==
5557 RefinementCase<dim - 1>::no_refinement,
5558 ExcInternalError());
5559
5560 // set the middle vertex appropriately: it might be that
5561 // the quad itself is not at the boundary, but that one of
5562 // its lines actually is. in this case, the newly created
5563 // vertices at the centers of the lines are not
5564 // necessarily the mean values of the adjacent vertices,
5565 // so do not compute the new vertex as the mean value of
5566 // the 4 vertices of the face, but rather as a weighted
5567 // mean value of the 8 vertices which we already have (the
5568 // four old ones, and the four ones inserted as middle
5569 // points for the four lines). summing up some more points
5570 // is generally cheaper than first asking whether one of
5571 // the lines is at the boundary
5572 //
5573 // note that the exact weights are chosen such as to
5574 // minimize the distortion of the four new quads from the
5575 // optimal shape. their description uses the formulas
5576 // underlying the TransfiniteInterpolationManifold
5577 // implementation
5578 triangulation.vertices[next_unused_vertex] =
5579 quad->center(true, true);
5580 triangulation.vertices_used[next_unused_vertex] = true;
5581
5582 // now that we created the right point, make up
5583 // the four lines interior to the quad (++ takes
5584 // care of the end of the vector)
5585 typename Triangulation<dim, spacedim>::raw_line_iterator
5586 new_lines[4];
5587
5588 for (unsigned int i = 0; i < 4; ++i)
5589 {
5590 if (i % 2 == 0)
5591 // search a free pair of lines for 0. and
5592 // 2. line, so that two of them end up
5593 // together, which is necessary if later on
5594 // we want to refine the quad
5595 // anisotropically and the two lines end up
5596 // as children of new line
5597 next_unused_line =
5598 triangulation.faces->lines
5599 .template next_free_pair_object<1>(triangulation);
5600
5601 new_lines[i] = next_unused_line;
5602 ++next_unused_line;
5603
5604 Assert(
5605 new_lines[i]->used() == false,
5606 ExcMessage(
5607 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5608 }
5609
5610 // set the data of the four lines. first collect
5611 // the indices of the five vertices:
5612 //
5613 // *--3--*
5614 // | | |
5615 // 0--4--1
5616 // | | |
5617 // *--2--*
5618 //
5619 // the lines are numbered as follows:
5620 //
5621 // *--*--*
5622 // | 1 |
5623 // *2-*-3*
5624 // | 0 |
5625 // *--*--*
5626
5627 const unsigned int vertex_indices[5] = {
5628 quad->line(0)->child(0)->vertex_index(1),
5629 quad->line(1)->child(0)->vertex_index(1),
5630 quad->line(2)->child(0)->vertex_index(1),
5631 quad->line(3)->child(0)->vertex_index(1),
5632 next_unused_vertex};
5633
5634 new_lines[0]->set_bounding_object_indices(
5635 {vertex_indices[2], vertex_indices[4]});
5636 new_lines[1]->set_bounding_object_indices(
5637 {vertex_indices[4], vertex_indices[3]});
5638 new_lines[2]->set_bounding_object_indices(
5639 {vertex_indices[0], vertex_indices[4]});
5640 new_lines[3]->set_bounding_object_indices(
5641 {vertex_indices[4], vertex_indices[1]});
5642
5643 for (const auto &new_line : new_lines)
5644 {
5645 new_line->set_used_flag();
5646 new_line->clear_user_flag();
5647 new_line->clear_user_data();
5648 new_line->clear_children();
5649 new_line->set_boundary_id_internal(quad->boundary_id());
5650 new_line->set_manifold_id(quad->manifold_id());
5651 }
5652
5653 // now for the quads. again, first collect some
5654 // data about the indices of the lines, with the
5655 // following numbering:
5656 //
5657 // .-6-.-7-.
5658 // 1 9 3
5659 // .-10.11-.
5660 // 0 8 2
5661 // .-4-.-5-.
5662
5663 // child 0 and 1 of a line are switched if the
5664 // line orientation is false. set up a miniature
5665 // table, indicating which child to take for line
5666 // orientations false and true. first index: child
5667 // index in standard orientation, second index:
5668 // line orientation
5669 const unsigned int index[2][2] = {
5670 {1, 0}, // child 0, line_orientation=false and true
5671 {0, 1}}; // child 1, line_orientation=false and true
5672
5673 const int line_indices[12] = {
5674 quad->line(0)
5675 ->child(index[0][quad->line_orientation(0)])
5676 ->index(),
5677 quad->line(0)
5678 ->child(index[1][quad->line_orientation(0)])
5679 ->index(),
5680 quad->line(1)
5681 ->child(index[0][quad->line_orientation(1)])
5682 ->index(),
5683 quad->line(1)
5684 ->child(index[1][quad->line_orientation(1)])
5685 ->index(),
5686 quad->line(2)
5687 ->child(index[0][quad->line_orientation(2)])
5688 ->index(),
5689 quad->line(2)
5690 ->child(index[1][quad->line_orientation(2)])
5691 ->index(),
5692 quad->line(3)
5693 ->child(index[0][quad->line_orientation(3)])
5694 ->index(),
5695 quad->line(3)
5696 ->child(index[1][quad->line_orientation(3)])
5697 ->index(),
5698 new_lines[0]->index(),
5699 new_lines[1]->index(),
5700 new_lines[2]->index(),
5701 new_lines[3]->index()};
5702
5703 // find some space (consecutive)
5704 // for the first two newly to be
5705 // created quads.
5706 typename Triangulation<dim, spacedim>::raw_quad_iterator
5707 new_quads[4];
5708
5709 next_unused_quad =
5710 triangulation.faces->quads
5711 .template next_free_pair_object<2>(triangulation);
5712
5713 new_quads[0] = next_unused_quad;
5714 Assert(
5715 new_quads[0]->used() == false,
5716 ExcMessage(
5717 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5718
5719 ++next_unused_quad;
5720 new_quads[1] = next_unused_quad;
5721 Assert(
5722 new_quads[1]->used() == false,
5723 ExcMessage(
5724 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5725
5726 next_unused_quad =
5727 triangulation.faces->quads
5728 .template next_free_pair_object<2>(triangulation);
5729 new_quads[2] = next_unused_quad;
5730 Assert(
5731 new_quads[2]->used() == false,
5732 ExcMessage(
5733 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5734
5735 ++next_unused_quad;
5736 new_quads[3] = next_unused_quad;
5737 Assert(
5738 new_quads[3]->used() == false,
5739 ExcMessage(
5740 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5741
5742 // note these quads as children to the present one
5743 quad->set_children(0, new_quads[0]->index());
5744 quad->set_children(2, new_quads[2]->index());
5745 quad->set_refinement_case(RefinementCase<2>::cut_xy);
5746
5747 new_quads[0]->set_bounding_object_indices(
5748 {line_indices[0],
5749 line_indices[8],
5750 line_indices[4],
5751 line_indices[10]});
5752 new_quads[1]->set_bounding_object_indices(
5753 {line_indices[8],
5754 line_indices[2],
5755 line_indices[5],
5756 line_indices[11]});
5757 new_quads[2]->set_bounding_object_indices(
5758 {line_indices[1],
5759 line_indices[9],
5760 line_indices[10],
5761 line_indices[6]});
5762 new_quads[3]->set_bounding_object_indices(
5763 {line_indices[9],
5764 line_indices[3],
5765 line_indices[11],
5766 line_indices[7]});
5767 for (const auto &new_quad : new_quads)
5768 {
5769 new_quad->set_used_flag();
5770 new_quad->clear_user_flag();
5771 new_quad->clear_user_data();
5772 new_quad->clear_children();
5773 new_quad->set_boundary_id_internal(quad->boundary_id());
5774 new_quad->set_manifold_id(quad->manifold_id());
5775 // set all line orientations to true, change
5776 // this after the loop, as we have to consider
5777 // different lines for each child
5778 for (unsigned int j = 0;
5779 j < GeometryInfo<dim>::lines_per_face;
5780 ++j)
5781 new_quad->set_line_orientation(j, true);
5782 }
5783 // now set the line orientation of children of
5784 // outer lines correctly, the lines in the
5785 // interior of the refined quad are automatically
5786 // oriented conforming to the standard
5787 new_quads[0]->set_line_orientation(
5788 0, quad->line_orientation(0));
5789 new_quads[0]->set_line_orientation(
5790 2, quad->line_orientation(2));
5791 new_quads[1]->set_line_orientation(
5792 1, quad->line_orientation(1));
5793 new_quads[1]->set_line_orientation(
5794 2, quad->line_orientation(2));
5795 new_quads[2]->set_line_orientation(
5796 0, quad->line_orientation(0));
5797 new_quads[2]->set_line_orientation(
5798 3, quad->line_orientation(3));
5799 new_quads[3]->set_line_orientation(
5800 1, quad->line_orientation(1));
5801 new_quads[3]->set_line_orientation(
5802 3, quad->line_orientation(3));
5803
5804 // finally clear flag indicating the need for
5805 // refinement
5806 quad->clear_user_flag();
5807 } // if (isotropic refinement)
5808 } // for all quads
5809 } // looped two times over all quads, all quads refined now
5810
5811 ///////////////////////////////////
5812 // Now, finally, set up the new
5813 // cells
5814 ///////////////////////////////////
5815
5816 typename Triangulation<3, spacedim>::DistortedCellList
5817 cells_with_distorted_children;
5818
5819 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
5820 ++level)
5821 {
5822 // only active objects can be refined further; remember
5823 // that we won't operate on the finest level, so
5824 // triangulation.begin_*(level+1) is allowed
5825 typename Triangulation<dim, spacedim>::active_hex_iterator
5826 hex = triangulation.begin_active_hex(level),
5827 endh = triangulation.begin_active_hex(level + 1);
5828 typename Triangulation<dim, spacedim>::raw_hex_iterator
5829 next_unused_hex = triangulation.begin_raw_hex(level + 1);
5830
5831 for (; hex != endh; ++hex)
5832 if (hex->refine_flag_set())
5833 {
5834 // this hex needs to be refined
5835
5836 // clear flag indicating the need for refinement. do
5837 // it here already, since we can't do it anymore
5838 // once the cell has children
5839 const RefinementCase<dim> ref_case = hex->refine_flag_set();
5840 hex->clear_refine_flag();
5841 hex->set_refinement_case(ref_case);
5842
5843 // depending on the refine case we might have to
5844 // create additional vertices, lines and quads
5845 // interior of the hex before the actual children
5846 // can be set up.
5847
5848 // in a first step: reserve the needed space for
5849 // lines, quads and hexes and initialize them
5850 // correctly
5851
5852 unsigned int n_new_lines = 0;
5853 unsigned int n_new_quads = 0;
5854 unsigned int n_new_hexes = 0;
5855 switch (ref_case)
5856 {
5857 case RefinementCase<dim>::cut_x:
5858 case RefinementCase<dim>::cut_y:
5859 case RefinementCase<dim>::cut_z:
5860 n_new_lines = 0;
5861 n_new_quads = 1;
5862 n_new_hexes = 2;
5863 break;
5864 case RefinementCase<dim>::cut_xy:
5865 case RefinementCase<dim>::cut_xz:
5866 case RefinementCase<dim>::cut_yz:
5867 n_new_lines = 1;
5868 n_new_quads = 4;
5869 n_new_hexes = 4;
5870 break;
5871 case RefinementCase<dim>::cut_xyz:
5872 n_new_lines = 6;
5873 n_new_quads = 12;
5874 n_new_hexes = 8;
5875 break;
5876 default:
5877 Assert(false, ExcInternalError());
5878 break;
5879 }
5880
5881 // find some space for the newly to be created
5882 // interior lines and initialize them.
5883 std::vector<
5884 typename Triangulation<dim, spacedim>::raw_line_iterator>
5885 new_lines(n_new_lines);
5886 for (unsigned int i = 0; i < n_new_lines; ++i)
5887 {
5888 new_lines[i] =
5889 triangulation.faces->lines
5890 .template next_free_single_object<1>(triangulation);
5891
5892 Assert(
5893 new_lines[i]->used() == false,
5894 ExcMessage(
5895 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5896 new_lines[i]->set_used_flag();
5897 new_lines[i]->clear_user_flag();
5898 new_lines[i]->clear_user_data();
5899 new_lines[i]->clear_children();
5900 // interior line
5901 new_lines[i]->set_boundary_id_internal(
5902 numbers::internal_face_boundary_id);
5903 // they inherit geometry description of the hex they
5904 // belong to
5905 new_lines[i]->set_manifold_id(hex->manifold_id());
5906 }
5907
5908 // find some space for the newly to be created
5909 // interior quads and initialize them.
5910 std::vector<
5911 typename Triangulation<dim, spacedim>::raw_quad_iterator>
5912 new_quads(n_new_quads);
5913 for (unsigned int i = 0; i < n_new_quads; ++i)
5914 {
5915 new_quads[i] =
5916 triangulation.faces->quads
5917 .template next_free_single_object<2>(triangulation);
5918
5919 Assert(
5920 new_quads[i]->used() == false,
5921 ExcMessage(
5922 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5923 new_quads[i]->set_used_flag();
5924 new_quads[i]->clear_user_flag();
5925 new_quads[i]->clear_user_data();
5926 new_quads[i]->clear_children();
5927 // interior quad
5928 new_quads[i]->set_boundary_id_internal(
5929 numbers::internal_face_boundary_id);
5930 // they inherit geometry description of the hex they
5931 // belong to
5932 new_quads[i]->set_manifold_id(hex->manifold_id());
5933 // set all line orientation flags to true by
5934 // default, change this afterwards, if necessary
5935 for (unsigned int j = 0;
5936 j < GeometryInfo<dim>::lines_per_face;
5937 ++j)
5938 new_quads[i]->set_line_orientation(j, true);
5939 }
5940
5941 types::subdomain_id subdomainid = hex->subdomain_id();
5942
5943 // find some space for the newly to be created hexes
5944 // and initialize them.
5945 std::vector<
5946 typename Triangulation<dim, spacedim>::raw_hex_iterator>
5947 new_hexes(n_new_hexes);
5948 for (unsigned int i = 0; i < n_new_hexes; ++i)
5949 {
5950 if (i % 2 == 0)
5951 next_unused_hex =
5952 triangulation.levels[level + 1]->cells.next_free_hex(
5953 triangulation, level + 1);
5954 else
5955 ++next_unused_hex;
5956
5957 new_hexes[i] = next_unused_hex;
5958
5959 Assert(
5960 new_hexes[i]->used() == false,
5961 ExcMessage(
5962 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5963 new_hexes[i]->set_used_flag();
5964 new_hexes[i]->clear_user_flag();
5965 new_hexes[i]->clear_user_data();
5966 new_hexes[i]->clear_children();
5967 // inherit material
5968 // properties
5969 new_hexes[i]->set_material_id(hex->material_id());
5970 new_hexes[i]->set_manifold_id(hex->manifold_id());
5971 new_hexes[i]->set_subdomain_id(subdomainid);
5972
5973 if (i % 2)
5974 new_hexes[i]->set_parent(hex->index());
5975 // set the face_orientation flag to true for all
5976 // faces initially, as this is the default value
5977 // which is true for all faces interior to the
5978 // hex. later on go the other way round and
5979 // reset faces that are at the boundary of the
5980 // mother cube
5981 //
5982 // the same is true for the face_flip and
5983 // face_rotation flags. however, the latter two
5984 // are set to false by default as this is the
5985 // standard value
5986 for (const unsigned int f :
5987 GeometryInfo<dim>::face_indices())
5988 {
5989 new_hexes[i]->set_face_orientation(f, true);
5990 new_hexes[i]->set_face_flip(f, false);
5991 new_hexes[i]->set_face_rotation(f, false);
5992 }
5993 }
5994 // note these hexes as children to the present cell
5995 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
5996 hex->set_children(2 * i, new_hexes[2 * i]->index());
5997
5998 // we have to take into account whether the
5999 // different faces are oriented correctly or in the
6000 // opposite direction, so store that up front
6001
6002 // face_orientation
6003 const bool f_or[6] = {hex->face_orientation(0),
6004 hex->face_orientation(1),
6005 hex->face_orientation(2),
6006 hex->face_orientation(3),
6007 hex->face_orientation(4),
6008 hex->face_orientation(5)};
6009
6010 // face_flip
6011 const bool f_fl[6] = {hex->face_flip(0),
6012 hex->face_flip(1),
6013 hex->face_flip(2),
6014 hex->face_flip(3),
6015 hex->face_flip(4),
6016 hex->face_flip(5)};
6017
6018 // face_rotation
6019 const bool f_ro[6] = {hex->face_rotation(0),
6020 hex->face_rotation(1),
6021 hex->face_rotation(2),
6022 hex->face_rotation(3),
6023 hex->face_rotation(4),
6024 hex->face_rotation(5)};
6025
6026 // little helper table, indicating, whether the
6027 // child with index 0 or with index 1 can be found
6028 // at the standard origin of an anisotropically
6029 // refined quads in real orientation index 1:
6030 // (RefineCase - 1) index 2: face_flip
6031
6032 // index 3: face rotation
6033 // note: face orientation has no influence
6034 const unsigned int child_at_origin[2][2][2] = {
6035 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
6036 // face_rotation=false and true
6037 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
6038 // face_rotation=false and true
6039 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
6040 // face_rotation=false and true
6041 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
6042 // face_rotation=false and true
6043
6044 ///////////////////////////////////////
6045 //
6046 // in the following we will do the same thing for
6047 // each refinement case: create a new vertex (if
6048 // needed), create new interior lines (if needed),
6049 // create new interior quads and afterwards build
6050 // the children hexes out of these and the existing
6051 // subfaces of the outer quads (which have been
6052 // created above). However, even if the steps are
6053 // quite similar, the actual work strongly depends
6054 // on the actual refinement case. therefore, we use
6055 // separate blocks of code for each of these cases,
6056 // which hopefully increases the readability to some
6057 // extend.
6058
6059 switch (ref_case)
6060 {
6061 case RefinementCase<dim>::cut_x:
6062 {
6063 //////////////////////////////
6064 //
6065 // RefinementCase<dim>::cut_x
6066 //
6067 // the refined cube will look
6068 // like this:
6069 //
6070 // *----*----*
6071 // / / /|
6072 // / / / |
6073 // / / / |
6074 // *----*----* |
6075 // | | | |
6076 // | | | *
6077 // | | | /
6078 // | | | /
6079 // | | |/
6080 // *----*----*
6081 //
6082 // again, first collect some data about the
6083 // indices of the lines, with the following
6084 // numbering:
6085
6086 // face 2: front plane
6087 // (note: x,y exchanged)
6088 // *---*---*
6089 // | | |
6090 // | 0 |
6091 // | | |
6092 // *---*---*
6093 // m0
6094 // face 3: back plane
6095 // (note: x,y exchanged)
6096 // m1
6097 // *---*---*
6098 // | | |
6099 // | 1 |
6100 // | | |
6101 // *---*---*
6102 // face 4: bottom plane
6103 // *---*---*
6104 // / / /
6105 // / 2 /
6106 // / / /
6107 // *---*---*
6108 // m0
6109 // face 5: top plane
6110 // m1
6111 // *---*---*
6112 // / / /
6113 // / 3 /
6114 // / / /
6115 // *---*---*
6116
6117 // set up a list of line iterators first. from
6118 // this, construct lists of line_indices and
6119 // line orientations later on
6120 const typename Triangulation<dim, spacedim>::
6121 raw_line_iterator lines[4] = {
6122 hex->face(2)->child(0)->line(
6123 (hex->face(2)->refinement_case() ==
6124 RefinementCase<2>::cut_x) ?
6125 1 :
6126 3), // 0
6127 hex->face(3)->child(0)->line(
6128 (hex->face(3)->refinement_case() ==
6129 RefinementCase<2>::cut_x) ?
6130 1 :
6131 3), // 1
6132 hex->face(4)->child(0)->line(
6133 (hex->face(4)->refinement_case() ==
6134 RefinementCase<2>::cut_x) ?
6135 1 :
6136 3), // 2
6137 hex->face(5)->child(0)->line(
6138 (hex->face(5)->refinement_case() ==
6139 RefinementCase<2>::cut_x) ?
6140 1 :
6141 3) // 3
6142 };
6143
6144 unsigned int line_indices[4];
6145 for (unsigned int i = 0; i < 4; ++i)
6146 line_indices[i] = lines[i]->index();
6147
6148 // the orientation of lines for the inner quads
6149 // is quite tricky. as these lines are newly
6150 // created ones and thus have no parents, they
6151 // cannot inherit this property. set up an array
6152 // and fill it with the respective values
6153 bool line_orientation[4];
6154
6155 // the middle vertex marked as m0 above is the
6156 // start vertex for lines 0 and 2 in standard
6157 // orientation, whereas m1 is the end vertex of
6158 // lines 1 and 3 in standard orientation
6159 const unsigned int middle_vertices[2] = {
6160 hex->line(2)->child(0)->vertex_index(1),
6161 hex->line(7)->child(0)->vertex_index(1)};
6162
6163 for (unsigned int i = 0; i < 4; ++i)
6164 if (lines[i]->vertex_index(i % 2) ==
6165 middle_vertices[i % 2])
6166 line_orientation[i] = true;
6167 else
6168 {
6169 // it must be the other
6170 // way round then
6171 Assert(lines[i]->vertex_index((i + 1) % 2) ==
6172 middle_vertices[i % 2],
6173 ExcInternalError());
6174 line_orientation[i] = false;
6175 }
6176
6177 // set up the new quad, line numbering is as
6178 // indicated above
6179 new_quads[0]->set_bounding_object_indices(
6180 {line_indices[0],
6181 line_indices[1],
6182 line_indices[2],
6183 line_indices[3]});
6184
6185 new_quads[0]->set_line_orientation(
6186 0, line_orientation[0]);
6187 new_quads[0]->set_line_orientation(
6188 1, line_orientation[1]);
6189 new_quads[0]->set_line_orientation(
6190 2, line_orientation[2]);
6191 new_quads[0]->set_line_orientation(
6192 3, line_orientation[3]);
6193
6194 // the quads are numbered as follows:
6195 //
6196 // planes in the interior of the old hex:
6197 //
6198 // *
6199 // /|
6200 // / | x
6201 // / | *-------* *---------*
6202 // * | | | / /
6203 // | 0 | | | / /
6204 // | * | | / /
6205 // | / *-------*y *---------*x
6206 // | /
6207 // |/
6208 // *
6209 //
6210 // children of the faces of the old hex
6211 //
6212 // *---*---* *---*---*
6213 // /| | | / / /|
6214 // / | | | / 9 / 10/ |
6215 // / | 5 | 6 | / / / |
6216 // * | | | *---*---* |
6217 // | 1 *---*---* | | | 2 *
6218 // | / / / | | | /
6219 // | / 7 / 8 / | 3 | 4 | /
6220 // |/ / / | | |/
6221 // *---*---* *---*---*
6222 //
6223 // note that we have to take care of the
6224 // orientation of faces.
6225 const int quad_indices[11] = {
6226 new_quads[0]->index(), // 0
6227
6228 hex->face(0)->index(), // 1
6229
6230 hex->face(1)->index(), // 2
6231
6232 hex->face(2)->child_index(
6233 child_at_origin[hex->face(2)->refinement_case() -
6234 1][f_fl[2]][f_ro[2]]), // 3
6235 hex->face(2)->child_index(
6236 1 -
6237 child_at_origin[hex->face(2)->refinement_case() -
6238 1][f_fl[2]][f_ro[2]]),
6239
6240 hex->face(3)->child_index(
6241 child_at_origin[hex->face(3)->refinement_case() -
6242 1][f_fl[3]][f_ro[3]]), // 5
6243 hex->face(3)->child_index(
6244 1 -
6245 child_at_origin[hex->face(3)->refinement_case() -
6246 1][f_fl[3]][f_ro[3]]),
6247
6248 hex->face(4)->child_index(
6249 child_at_origin[hex->face(4)->refinement_case() -
6250 1][f_fl[4]][f_ro[4]]), // 7
6251 hex->face(4)->child_index(
6252 1 -
6253 child_at_origin[hex->face(4)->refinement_case() -
6254 1][f_fl[4]][f_ro[4]]),
6255
6256 hex->face(5)->child_index(
6257 child_at_origin[hex->face(5)->refinement_case() -
6258 1][f_fl[5]][f_ro[5]]), // 9
6259 hex->face(5)->child_index(
6260 1 -
6261 child_at_origin[hex->face(5)->refinement_case() -
6262 1][f_fl[5]][f_ro[5]])
6263
6264 };
6265
6266 new_hexes[0]->set_bounding_object_indices(
6267 {quad_indices[1],
6268 quad_indices[0],
6269 quad_indices[3],
6270 quad_indices[5],
6271 quad_indices[7],
6272 quad_indices[9]});
6273 new_hexes[1]->set_bounding_object_indices(
6274 {quad_indices[0],
6275 quad_indices[2],
6276 quad_indices[4],
6277 quad_indices[6],
6278 quad_indices[8],
6279 quad_indices[10]});
6280 break;
6281 }
6282
6283 case RefinementCase<dim>::cut_y:
6284 {
6285 //////////////////////////////
6286 //
6287 // RefinementCase<dim>::cut_y
6288 //
6289 // the refined cube will look like this:
6290 //
6291 // *---------*
6292 // / /|
6293 // *---------* |
6294 // / /| |
6295 // *---------* | |
6296 // | | | |
6297 // | | | *
6298 // | | |/
6299 // | | *
6300 // | |/
6301 // *---------*
6302 //
6303 // again, first collect some data about the
6304 // indices of the lines, with the following
6305 // numbering:
6306
6307 // face 0: left plane
6308 // *
6309 // /|
6310 // * |
6311 // /| |
6312 // * | |
6313 // | 0 |
6314 // | | *
6315 // | |/
6316 // | *m0
6317 // |/
6318 // *
6319 // face 1: right plane
6320 // *
6321 // /|
6322 // m1* |
6323 // /| |
6324 // * | |
6325 // | 1 |
6326 // | | *
6327 // | |/
6328 // | *
6329 // |/
6330 // *
6331 // face 4: bottom plane
6332 // *-------*
6333 // / /
6334 // m0*---2---*
6335 // / /
6336 // *-------*
6337 // face 5: top plane
6338 // *-------*
6339 // / /
6340 // *---3---*m1
6341 // / /
6342 // *-------*
6343
6344 // set up a list of line iterators first. from
6345 // this, construct lists of line_indices and
6346 // line orientations later on
6347 const typename Triangulation<dim, spacedim>::
6348 raw_line_iterator lines[4] = {
6349 hex->face(0)->child(0)->line(
6350 (hex->face(0)->refinement_case() ==
6351 RefinementCase<2>::cut_x) ?
6352 1 :
6353 3), // 0
6354 hex->face(1)->child(0)->line(
6355 (hex->face(1)->refinement_case() ==
6356 RefinementCase<2>::cut_x) ?
6357 1 :
6358 3), // 1
6359 hex->face(4)->child(0)->line(
6360 (hex->face(4)->refinement_case() ==
6361 RefinementCase<2>::cut_x) ?
6362 1 :
6363 3), // 2
6364 hex->face(5)->child(0)->line(
6365 (hex->face(5)->refinement_case() ==
6366 RefinementCase<2>::cut_x) ?
6367 1 :
6368 3) // 3
6369 };
6370
6371 unsigned int line_indices[4];
6372 for (unsigned int i = 0; i < 4; ++i)
6373 line_indices[i] = lines[i]->index();
6374
6375 // the orientation of lines for the inner quads
6376 // is quite tricky. as these lines are newly
6377 // created ones and thus have no parents, they
6378 // cannot inherit this property. set up an array
6379 // and fill it with the respective values
6380 bool line_orientation[4];
6381
6382 // the middle vertex marked as m0 above is the
6383 // start vertex for lines 0 and 2 in standard
6384 // orientation, whereas m1 is the end vertex of
6385 // lines 1 and 3 in standard orientation
6386 const unsigned int middle_vertices[2] = {
6387 hex->line(0)->child(0)->vertex_index(1),
6388 hex->line(5)->child(0)->vertex_index(1)};
6389
6390 for (unsigned int i = 0; i < 4; ++i)
6391 if (lines[i]->vertex_index(i % 2) ==
6392 middle_vertices[i % 2])
6393 line_orientation[i] = true;
6394 else
6395 {
6396 // it must be the other way round then
6397 Assert(lines[i]->vertex_index((i + 1) % 2) ==
6398 middle_vertices[i % 2],
6399 ExcInternalError());
6400 line_orientation[i] = false;
6401 }
6402
6403 // set up the new quad, line numbering is as
6404 // indicated above
6405 new_quads[0]->set_bounding_object_indices(
6406 {line_indices[2],
6407 line_indices[3],
6408 line_indices[0],
6409 line_indices[1]});
6410
6411 new_quads[0]->set_line_orientation(
6412 0, line_orientation[2]);
6413 new_quads[0]->set_line_orientation(
6414 1, line_orientation[3]);
6415 new_quads[0]->set_line_orientation(
6416 2, line_orientation[0]);
6417 new_quads[0]->set_line_orientation(
6418 3, line_orientation[1]);
6419
6420 // the quads are numbered as follows:
6421 //
6422 // planes in the interior of the old hex:
6423 //
6424 // *
6425 // /|
6426 // / | x
6427 // / | *-------* *---------*
6428 // * | | | / /
6429 // | | | 0 | / /
6430 // | * | | / /
6431 // | / *-------*y *---------*x
6432 // | /
6433 // |/
6434 // *
6435 //
6436 // children of the faces of the old hex
6437 //
6438 // *-------* *-------*
6439 // /| | / 10 /|
6440 // * | | *-------* |
6441 // /| | 6 | / 9 /| |
6442 // * |2| | *-------* |4|
6443 // | | *-------* | | | *
6444 // |1|/ 8 / | |3|/
6445 // | *-------* | 5 | *
6446 // |/ 7 / | |/
6447 // *-------* *-------*
6448 //
6449 // note that we have to take care of the
6450 // orientation of faces.
6451 const int quad_indices[11] = {
6452 new_quads[0]->index(), // 0
6453
6454 hex->face(0)->child_index(
6455 child_at_origin[hex->face(0)->refinement_case() -
6456 1][f_fl[0]][f_ro[0]]), // 1
6457 hex->face(0)->child_index(
6458 1 -
6459 child_at_origin[hex->face(0)->refinement_case() -
6460 1][f_fl[0]][f_ro[0]]),
6461
6462 hex->face(1)->child_index(
6463 child_at_origin[hex->face(1)->refinement_case() -
6464 1][f_fl[1]][f_ro[1]]), // 3
6465 hex->face(1)->child_index(
6466 1 -
6467 child_at_origin[hex->face(1)->refinement_case() -
6468 1][f_fl[1]][f_ro[1]]),
6469
6470 hex->face(2)->index(), // 5
6471
6472 hex->face(3)->index(), // 6
6473
6474 hex->face(4)->child_index(
6475 child_at_origin[hex->face(4)->refinement_case() -
6476 1][f_fl[4]][f_ro[4]]), // 7
6477 hex->face(4)->child_index(
6478 1 -
6479 child_at_origin[hex->face(4)->refinement_case() -
6480 1][f_fl[4]][f_ro[4]]),
6481
6482 hex->face(5)->child_index(
6483 child_at_origin[hex->face(5)->refinement_case() -
6484 1][f_fl[5]][f_ro[5]]), // 9
6485 hex->face(5)->child_index(
6486 1 -
6487 child_at_origin[hex->face(5)->refinement_case() -
6488 1][f_fl[5]][f_ro[5]])
6489
6490 };
6491
6492 new_hexes[0]->set_bounding_object_indices(
6493 {quad_indices[1],
6494 quad_indices[3],
6495 quad_indices[5],
6496 quad_indices[0],
6497 quad_indices[7],
6498 quad_indices[9]});
6499 new_hexes[1]->set_bounding_object_indices(
6500 {quad_indices[2],
6501 quad_indices[4],
6502 quad_indices[0],
6503 quad_indices[6],
6504 quad_indices[8],
6505 quad_indices[10]});
6506 break;
6507 }
6508
6509 case RefinementCase<dim>::cut_z:
6510 {
6511 //////////////////////////////
6512 //
6513 // RefinementCase<dim>::cut_z
6514 //
6515 // the refined cube will look like this:
6516 //
6517 // *---------*
6518 // / /|
6519 // / / |
6520 // / / *
6521 // *---------* /|
6522 // | | / |
6523 // | |/ *
6524 // *---------* /
6525 // | | /
6526 // | |/
6527 // *---------*
6528 //
6529 // again, first collect some data about the
6530 // indices of the lines, with the following
6531 // numbering:
6532
6533 // face 0: left plane
6534 // *
6535 // /|
6536 // / |
6537 // / *
6538 // * /|
6539 // | 0 |
6540 // |/ *
6541 // m0* /
6542 // | /
6543 // |/
6544 // *
6545 // face 1: right plane
6546 // *
6547 // /|
6548 // / |
6549 // / *m1
6550 // * /|
6551 // | 1 |
6552 // |/ *
6553 // * /
6554 // | /
6555 // |/
6556 // *
6557 // face 2: front plane
6558 // (note: x,y exchanged)
6559 // *-------*
6560 // | |
6561 // m0*---2---*
6562 // | |
6563 // *-------*
6564 // face 3: back plane
6565 // (note: x,y exchanged)
6566 // *-------*
6567 // | |
6568 // *---3---*m1
6569 // | |
6570 // *-------*
6571
6572 // set up a list of line iterators first. from
6573 // this, construct lists of line_indices and
6574 // line orientations later on
6575 const typename Triangulation<dim, spacedim>::
6576 raw_line_iterator lines[4] = {
6577 hex->face(0)->child(0)->line(
6578 (hex->face(0)->refinement_case() ==
6579 RefinementCase<2>::cut_x) ?
6580 1 :
6581 3), // 0
6582 hex->face(1)->child(0)->line(
6583 (hex->face(1)->refinement_case() ==
6584 RefinementCase<2>::cut_x) ?
6585 1 :
6586 3), // 1
6587 hex->face(2)->child(0)->line(
6588 (hex->face(2)->refinement_case() ==
6589 RefinementCase<2>::cut_x) ?
6590 1 :
6591 3), // 2
6592 hex->face(3)->child(0)->line(
6593 (hex->face(3)->refinement_case() ==
6594 RefinementCase<2>::cut_x) ?
6595 1 :
6596 3) // 3
6597 };
6598
6599 unsigned int line_indices[4];
6600 for (unsigned int i = 0; i < 4; ++i)
6601 line_indices[i] = lines[i]->index();
6602
6603 // the orientation of lines for the inner quads
6604 // is quite tricky. as these lines are newly
6605 // created ones and thus have no parents, they
6606 // cannot inherit this property. set up an array
6607 // and fill it with the respective values
6608 bool line_orientation[4];
6609
6610 // the middle vertex marked as m0 above is the
6611 // start vertex for lines 0 and 2 in standard
6612 // orientation, whereas m1 is the end vertex of
6613 // lines 1 and 3 in standard orientation
6614 const unsigned int middle_vertices[2] = {
6615 middle_vertex_index<dim, spacedim>(hex->line(8)),
6616 middle_vertex_index<dim, spacedim>(hex->line(11))};
6617
6618 for (unsigned int i = 0; i < 4; ++i)
6619 if (lines[i]->vertex_index(i % 2) ==
6620 middle_vertices[i % 2])
6621 line_orientation[i] = true;
6622 else
6623 {
6624 // it must be the other way round then
6625 Assert(lines[i]->vertex_index((i + 1) % 2) ==
6626 middle_vertices[i % 2],
6627 ExcInternalError());
6628 line_orientation[i] = false;
6629 }
6630
6631 // set up the new quad, line numbering is as
6632 // indicated above
6633 new_quads[0]->set_bounding_object_indices(
6634 {line_indices[0],
6635 line_indices[1],
6636 line_indices[2],
6637 line_indices[3]});
6638
6639 new_quads[0]->set_line_orientation(
6640 0, line_orientation[0]);
6641 new_quads[0]->set_line_orientation(
6642 1, line_orientation[1]);
6643 new_quads[0]->set_line_orientation(
6644 2, line_orientation[2]);
6645 new_quads[0]->set_line_orientation(
6646 3, line_orientation[3]);
6647
6648 // the quads are numbered as follows:
6649 //
6650 // planes in the interior of the old hex:
6651 //
6652 // *
6653 // /|
6654 // / | x
6655 // / | *-------* *---------*
6656 // * | | | / /
6657 // | | | | / 0 /
6658 // | * | | / /
6659 // | / *-------*y *---------*x
6660 // | /
6661 // |/
6662 // *
6663 //
6664 // children of the faces of the old hex
6665 //
6666 // *---*---* *-------*
6667 // /| 8 | / /|
6668 // / | | / 10 / |
6669 // / *-------* / / *
6670 // * 2/| | *-------* 4/|
6671 // | / | 7 | | 6 | / |
6672 // |/1 *-------* | |/3 *
6673 // * / / *-------* /
6674 // | / 9 / | | /
6675 // |/ / | 5 |/
6676 // *-------* *---*---*
6677 //
6678 // note that we have to take care of the
6679 // orientation of faces.
6680 const int quad_indices[11] = {
6681 new_quads[0]->index(), // 0
6682
6683 hex->face(0)->child_index(
6684 child_at_origin[hex->face(0)->refinement_case() -
6685 1][f_fl[0]][f_ro[0]]), // 1
6686 hex->face(0)->child_index(
6687 1 -
6688 child_at_origin[hex->face(0)->refinement_case() -
6689 1][f_fl[0]][f_ro[0]]),
6690
6691 hex->face(1)->child_index(
6692 child_at_origin[hex->face(1)->refinement_case() -
6693 1][f_fl[1]][f_ro[1]]), // 3
6694 hex->face(1)->child_index(
6695 1 -
6696 child_at_origin[hex->face(1)->refinement_case() -
6697 1][f_fl[1]][f_ro[1]]),
6698
6699 hex->face(2)->child_index(
6700 child_at_origin[hex->face(2)->refinement_case() -
6701 1][f_fl[2]][f_ro[2]]), // 5
6702 hex->face(2)->child_index(
6703 1 -
6704 child_at_origin[hex->face(2)->refinement_case() -
6705 1][f_fl[2]][f_ro[2]]),
6706
6707 hex->face(3)->child_index(
6708 child_at_origin[hex->face(3)->refinement_case() -
6709 1][f_fl[3]][f_ro[3]]), // 7
6710 hex->face(3)->child_index(
6711 1 -
6712 child_at_origin[hex->face(3)->refinement_case() -
6713 1][f_fl[3]][f_ro[3]]),
6714
6715 hex->face(4)->index(), // 9
6716
6717 hex->face(5)->index() // 10
6718 };
6719
6720 new_hexes[0]->set_bounding_object_indices(
6721 {quad_indices[1],
6722 quad_indices[3],
6723 quad_indices[5],
6724 quad_indices[7],
6725 quad_indices[9],
6726 quad_indices[0]});
6727 new_hexes[1]->set_bounding_object_indices(
6728 {quad_indices[2],
6729 quad_indices[4],
6730 quad_indices[6],
6731 quad_indices[8],
6732 quad_indices[0],
6733 quad_indices[10]});
6734 break;
6735 }
6736
6737 case RefinementCase<dim>::cut_xy:
6738 {
6739 //////////////////////////////
6740 //
6741 // RefinementCase<dim>::cut_xy
6742 //
6743 // the refined cube will look like this:
6744 //
6745 // *----*----*
6746 // / / /|
6747 // *----*----* |
6748 // / / /| |
6749 // *----*----* | |
6750 // | | | | |
6751 // | | | | *
6752 // | | | |/
6753 // | | | *
6754 // | | |/
6755 // *----*----*
6756 //
6757
6758 // first, create the new internal line
6759 new_lines[0]->set_bounding_object_indices(
6760 {middle_vertex_index<dim, spacedim>(hex->face(4)),
6761 middle_vertex_index<dim, spacedim>(hex->face(5))});
6762
6763 // again, first collect some data about the
6764 // indices of the lines, with the following
6765 // numbering:
6766
6767 // face 0: left plane
6768 // *
6769 // /|
6770 // * |
6771 // /| |
6772 // * | |
6773 // | 0 |
6774 // | | *
6775 // | |/
6776 // | *
6777 // |/
6778 // *
6779 // face 1: right plane
6780 // *
6781 // /|
6782 // * |
6783 // /| |
6784 // * | |
6785 // | 1 |
6786 // | | *
6787 // | |/
6788 // | *
6789 // |/
6790 // *
6791 // face 2: front plane
6792 // (note: x,y exchanged)
6793 // *---*---*
6794 // | | |
6795 // | 2 |
6796 // | | |
6797 // *-------*
6798 // face 3: back plane
6799 // (note: x,y exchanged)
6800 // *---*---*
6801 // | | |
6802 // | 3 |
6803 // | | |
6804 // *---*---*
6805 // face 4: bottom plane
6806 // *---*---*
6807 // / 5 /
6808 // *-6-*-7-*
6809 // / 4 /
6810 // *---*---*
6811 // face 5: top plane
6812 // *---*---*
6813 // / 9 /
6814 // *10-*-11*
6815 // / 8 /
6816 // *---*---*
6817 // middle planes
6818 // *-------* *---*---*
6819 // / / | | |
6820 // / / | 12 |
6821 // / / | | |
6822 // *-------* *---*---*
6823
6824 // set up a list of line iterators first. from
6825 // this, construct lists of line_indices and
6826 // line orientations later on
6827 const typename Triangulation<
6828 dim,
6829 spacedim>::raw_line_iterator lines[13] = {
6830 hex->face(0)->child(0)->line(
6831 (hex->face(0)->refinement_case() ==
6832 RefinementCase<2>::cut_x) ?
6833 1 :
6834 3), // 0
6835 hex->face(1)->child(0)->line(
6836 (hex->face(1)->refinement_case() ==
6837 RefinementCase<2>::cut_x) ?
6838 1 :
6839 3), // 1
6840 hex->face(2)->child(0)->line(
6841 (hex->face(2)->refinement_case() ==
6842 RefinementCase<2>::cut_x) ?
6843 1 :
6844 3), // 2
6845 hex->face(3)->child(0)->line(
6846 (hex->face(3)->refinement_case() ==
6847 RefinementCase<2>::cut_x) ?
6848 1 :
6849 3), // 3
6850
6851 hex->face(4)
6852 ->isotropic_child(
6853 GeometryInfo<dim>::standard_to_real_face_vertex(
6854 0, f_or[4], f_fl[4], f_ro[4]))
6855 ->line(
6856 GeometryInfo<dim>::standard_to_real_face_line(
6857 1, f_or[4], f_fl[4], f_ro[4])), // 4
6858 hex->face(4)
6859 ->isotropic_child(
6860 GeometryInfo<dim>::standard_to_real_face_vertex(
6861 3, f_or[4], f_fl[4], f_ro[4]))
6862 ->line(
6863 GeometryInfo<dim>::standard_to_real_face_line(
6864 0, f_or[4], f_fl[4], f_ro[4])), // 5
6865 hex->face(4)
6866 ->isotropic_child(
6867 GeometryInfo<dim>::standard_to_real_face_vertex(
6868 0, f_or[4], f_fl[4], f_ro[4]))
6869 ->line(
6870 GeometryInfo<dim>::standard_to_real_face_line(
6871 3, f_or[4], f_fl[4], f_ro[4])), // 6
6872 hex->face(4)
6873 ->isotropic_child(
6874 GeometryInfo<dim>::standard_to_real_face_vertex(
6875 3, f_or[4], f_fl[4], f_ro[4]))
6876 ->line(
6877 GeometryInfo<dim>::standard_to_real_face_line(
6878 2, f_or[4], f_fl[4], f_ro[4])), // 7
6879
6880 hex->face(5)
6881 ->isotropic_child(
6882 GeometryInfo<dim>::standard_to_real_face_vertex(
6883 0, f_or[5], f_fl[5], f_ro[5]))
6884 ->line(
6885 GeometryInfo<dim>::standard_to_real_face_line(
6886 1, f_or[5], f_fl[5], f_ro[5])), // 8
6887 hex->face(5)
6888 ->isotropic_child(
6889 GeometryInfo<dim>::standard_to_real_face_vertex(
6890 3, f_or[5], f_fl[5], f_ro[5]))
6891 ->line(
6892 GeometryInfo<dim>::standard_to_real_face_line(
6893 0, f_or[5], f_fl[5], f_ro[5])), // 9
6894 hex->face(5)
6895 ->isotropic_child(
6896 GeometryInfo<dim>::standard_to_real_face_vertex(
6897 0, f_or[5], f_fl[5], f_ro[5]))
6898 ->line(
6899 GeometryInfo<dim>::standard_to_real_face_line(
6900 3, f_or[5], f_fl[5], f_ro[5])), // 10
6901 hex->face(5)
6902 ->isotropic_child(
6903 GeometryInfo<dim>::standard_to_real_face_vertex(
6904 3, f_or[5], f_fl[5], f_ro[5]))
6905 ->line(
6906 GeometryInfo<dim>::standard_to_real_face_line(
6907 2, f_or[5], f_fl[5], f_ro[5])), // 11
6908
6909 new_lines[0] // 12
6910 };
6911
6912 unsigned int line_indices[13];
6913 for (unsigned int i = 0; i < 13; ++i)
6914 line_indices[i] = lines[i]->index();
6915
6916 // the orientation of lines for the inner quads
6917 // is quite tricky. as these lines are newly
6918 // created ones and thus have no parents, they
6919 // cannot inherit this property. set up an array
6920 // and fill it with the respective values
6921 bool line_orientation[13];
6922
6923 // the middle vertices of the lines of our
6924 // bottom face
6925 const unsigned int middle_vertices[4] = {
6926 hex->line(0)->child(0)->vertex_index(1),
6927 hex->line(1)->child(0)->vertex_index(1),
6928 hex->line(2)->child(0)->vertex_index(1),
6929 hex->line(3)->child(0)->vertex_index(1),
6930 };
6931
6932 // note: for lines 0 to 3 the orientation of the
6933 // line is 'true', if vertex 0 is on the bottom
6934 // face
6935 for (unsigned int i = 0; i < 4; ++i)
6936 if (lines[i]->vertex_index(0) == middle_vertices[i])
6937 line_orientation[i] = true;
6938 else
6939 {
6940 // it must be the other way round then
6941 Assert(lines[i]->vertex_index(1) ==
6942 middle_vertices[i],
6943 ExcInternalError());
6944 line_orientation[i] = false;
6945 }
6946
6947 // note: for lines 4 to 11 (inner lines of the
6948 // outer quads) the following holds: the second
6949 // vertex of the even lines in standard
6950 // orientation is the vertex in the middle of
6951 // the quad, whereas for odd lines the first
6952 // vertex is the same middle vertex.
6953 for (unsigned int i = 4; i < 12; ++i)
6954 if (lines[i]->vertex_index((i + 1) % 2) ==
6955 middle_vertex_index<dim, spacedim>(
6956 hex->face(3 + i / 4)))
6957 line_orientation[i] = true;
6958 else
6959 {
6960 // it must be the other way
6961 // round then
6962 Assert(lines[i]->vertex_index(i % 2) ==
6963 (middle_vertex_index<dim, spacedim>(
6964 hex->face(3 + i / 4))),
6965 ExcInternalError());
6966 line_orientation[i] = false;
6967 }
6968 // for the last line the line orientation is
6969 // always true, since it was just constructed
6970 // that way
6971 line_orientation[12] = true;
6972
6973 // set up the 4 quads, numbered as follows (left
6974 // quad numbering, right line numbering
6975 // extracted from above)
6976 //
6977 // * *
6978 // /| 9|
6979 // * | * |
6980 // y/| | 8| 3
6981 // * |1| * | |
6982 // | | |x | 12|
6983 // |0| * | | *
6984 // | |/ 2 |5
6985 // | * | *
6986 // |/ |4
6987 // * *
6988 //
6989 // x
6990 // *---*---* *10-*-11*
6991 // | | | | | |
6992 // | 2 | 3 | 0 12 1
6993 // | | | | | |
6994 // *---*---*y *-6-*-7-*
6995
6996 new_quads[0]->set_bounding_object_indices(
6997 {line_indices[2],
6998 line_indices[12],
6999 line_indices[4],
7000 line_indices[8]});
7001 new_quads[1]->set_bounding_object_indices(
7002 {line_indices[12],
7003 line_indices[3],
7004 line_indices[5],
7005 line_indices[9]});
7006 new_quads[2]->set_bounding_object_indices(
7007 {line_indices[6],
7008 line_indices[10],
7009 line_indices[0],
7010 line_indices[12]});
7011 new_quads[3]->set_bounding_object_indices(
7012 {line_indices[7],
7013 line_indices[11],
7014 line_indices[12],
7015 line_indices[1]});
7016
7017 new_quads[0]->set_line_orientation(
7018 0, line_orientation[2]);
7019 new_quads[0]->set_line_orientation(
7020 2, line_orientation[4]);
7021 new_quads[0]->set_line_orientation(
7022 3, line_orientation[8]);
7023
7024 new_quads[1]->set_line_orientation(
7025 1, line_orientation[3]);
7026 new_quads[1]->set_line_orientation(
7027 2, line_orientation[5]);
7028 new_quads[1]->set_line_orientation(
7029 3, line_orientation[9]);
7030
7031 new_quads[2]->set_line_orientation(
7032 0, line_orientation[6]);
7033 new_quads[2]->set_line_orientation(
7034 1, line_orientation[10]);
7035 new_quads[2]->set_line_orientation(
7036 2, line_orientation[0]);
7037
7038 new_quads[3]->set_line_orientation(
7039 0, line_orientation[7]);
7040 new_quads[3]->set_line_orientation(
7041 1, line_orientation[11]);
7042 new_quads[3]->set_line_orientation(
7043 3, line_orientation[1]);
7044
7045 // the quads are numbered as follows:
7046 //
7047 // planes in the interior of the old hex:
7048 //
7049 // *
7050 // /|
7051 // * | x
7052 // /| | *---*---* *---------*
7053 // * |1| | | | / /
7054 // | | | | 2 | 3 | / /
7055 // |0| * | | | / /
7056 // | |/ *---*---*y *---------*x
7057 // | *
7058 // |/
7059 // *
7060 //
7061 // children of the faces of the old hex
7062 //
7063 // *---*---* *---*---*
7064 // /| | | /18 / 19/|
7065 // * |10 | 11| /---/---* |
7066 // /| | | | /16 / 17/| |
7067 // * |5| | | *---*---* |7|
7068 // | | *---*---* | | | | *
7069 // |4|/14 / 15/ | | |6|/
7070 // | *---/---/ | 8 | 9 | *
7071 // |/12 / 13/ | | |/
7072 // *---*---* *---*---*
7073 //
7074 // note that we have to take care of the
7075 // orientation of faces.
7076 const int quad_indices[20] = {
7077 new_quads[0]->index(), // 0
7078 new_quads[1]->index(),
7079 new_quads[2]->index(),
7080 new_quads[3]->index(),
7081
7082 hex->face(0)->child_index(
7083 child_at_origin[hex->face(0)->refinement_case() -
7084 1][f_fl[0]][f_ro[0]]), // 4
7085 hex->face(0)->child_index(
7086 1 -
7087 child_at_origin[hex->face(0)->refinement_case() -
7088 1][f_fl[0]][f_ro[0]]),
7089
7090 hex->face(1)->child_index(
7091 child_at_origin[hex->face(1)->refinement_case() -
7092 1][f_fl[1]][f_ro[1]]), // 6
7093 hex->face(1)->child_index(
7094 1 -
7095 child_at_origin[hex->face(1)->refinement_case() -
7096 1][f_fl[1]][f_ro[1]]),
7097
7098 hex->face(2)->child_index(
7099 child_at_origin[hex->face(2)->refinement_case() -
7100 1][f_fl[2]][f_ro[2]]), // 8
7101 hex->face(2)->child_index(
7102 1 -
7103 child_at_origin[hex->face(2)->refinement_case() -
7104 1][f_fl[2]][f_ro[2]]),
7105
7106 hex->face(3)->child_index(
7107 child_at_origin[hex->face(3)->refinement_case() -
7108 1][f_fl[3]][f_ro[3]]), // 10
7109 hex->face(3)->child_index(
7110 1 -
7111 child_at_origin[hex->face(3)->refinement_case() -
7112 1][f_fl[3]][f_ro[3]]),
7113
7114 hex->face(4)->isotropic_child_index(
7115 GeometryInfo<dim>::standard_to_real_face_vertex(
7116 0, f_or[4], f_fl[4], f_ro[4])), // 12
7117 hex->face(4)->isotropic_child_index(
7118 GeometryInfo<dim>::standard_to_real_face_vertex(
7119 1, f_or[4], f_fl[4], f_ro[4])),
7120 hex->face(4)->isotropic_child_index(
7121 GeometryInfo<dim>::standard_to_real_face_vertex(
7122 2, f_or[4], f_fl[4], f_ro[4])),
7123 hex->face(4)->isotropic_child_index(
7124 GeometryInfo<dim>::standard_to_real_face_vertex(
7125 3, f_or[4], f_fl[4], f_ro[4])),
7126
7127 hex->face(5)->isotropic_child_index(
7128 GeometryInfo<dim>::standard_to_real_face_vertex(
7129 0, f_or[5], f_fl[5], f_ro[5])), // 16
7130 hex->face(5)->isotropic_child_index(
7131 GeometryInfo<dim>::standard_to_real_face_vertex(
7132 1, f_or[5], f_fl[5], f_ro[5])),
7133 hex->face(5)->isotropic_child_index(
7134 GeometryInfo<dim>::standard_to_real_face_vertex(
7135 2, f_or[5], f_fl[5], f_ro[5])),
7136 hex->face(5)->isotropic_child_index(
7137 GeometryInfo<dim>::standard_to_real_face_vertex(
7138 3, f_or[5], f_fl[5], f_ro[5]))};
7139
7140 new_hexes[0]->set_bounding_object_indices(
7141 {quad_indices[4],
7142 quad_indices[0],
7143 quad_indices[8],
7144 quad_indices[2],
7145 quad_indices[12],
7146 quad_indices[16]});
7147 new_hexes[1]->set_bounding_object_indices(
7148 {quad_indices[0],
7149 quad_indices[6],
7150 quad_indices[9],
7151 quad_indices[3],
7152 quad_indices[13],
7153 quad_indices[17]});
7154 new_hexes[2]->set_bounding_object_indices(
7155 {quad_indices[5],
7156 quad_indices[1],
7157 quad_indices[2],
7158 quad_indices[10],
7159 quad_indices[14],
7160 quad_indices[18]});
7161 new_hexes[3]->set_bounding_object_indices(
7162 {quad_indices[1],
7163 quad_indices[7],
7164 quad_indices[3],
7165 quad_indices[11],
7166 quad_indices[15],
7167 quad_indices[19]});
7168 break;
7169 }
7170
7171 case RefinementCase<dim>::cut_xz:
7172 {
7173 //////////////////////////////
7174 //
7175 // RefinementCase<dim>::cut_xz
7176 //
7177 // the refined cube will look like this:
7178 //
7179 // *----*----*
7180 // / / /|
7181 // / / / |
7182 // / / / *
7183 // *----*----* /|
7184 // | | | / |
7185 // | | |/ *
7186 // *----*----* /
7187 // | | | /
7188 // | | |/
7189 // *----*----*
7190 //
7191
7192 // first, create the new internal line
7193 new_lines[0]->set_bounding_object_indices(
7194 {middle_vertex_index<dim, spacedim>(hex->face(2)),
7195 middle_vertex_index<dim, spacedim>(hex->face(3))});
7196
7197 // again, first collect some data about the
7198 // indices of the lines, with the following
7199 // numbering:
7200
7201 // face 0: left plane
7202 // *
7203 // /|
7204 // / |
7205 // / *
7206 // * /|
7207 // | 0 |
7208 // |/ *
7209 // * /
7210 // | /
7211 // |/
7212 // *
7213 // face 1: right plane
7214 // *
7215 // /|
7216 // / |
7217 // / *
7218 // * /|
7219 // | 1 |
7220 // |/ *
7221 // * /
7222 // | /
7223 // |/
7224 // *
7225 // face 2: front plane
7226 // (note: x,y exchanged)
7227 // *---*---*
7228 // | 5 |
7229 // *-6-*-7-*
7230 // | 4 |
7231 // *---*---*
7232 // face 3: back plane
7233 // (note: x,y exchanged)
7234 // *---*---*
7235 // | 9 |
7236 // *10-*-11*
7237 // | 8 |
7238 // *---*---*
7239 // face 4: bottom plane
7240 // *---*---*
7241 // / / /
7242 // / 2 /
7243 // / / /
7244 // *---*---*
7245 // face 5: top plane
7246 // *---*---*
7247 // / / /
7248 // / 3 /
7249 // / / /
7250 // *---*---*
7251 // middle planes
7252 // *---*---* *-------*
7253 // / / / | |
7254 // / 12 / | |
7255 // / / / | |
7256 // *---*---* *-------*
7257
7258 // set up a list of line iterators first. from
7259 // this, construct lists of line_indices and
7260 // line orientations later on
7261 const typename Triangulation<
7262 dim,
7263 spacedim>::raw_line_iterator lines[13] = {
7264 hex->face(0)->child(0)->line(
7265 (hex->face(0)->refinement_case() ==
7266 RefinementCase<2>::cut_x) ?
7267 1 :
7268 3), // 0
7269 hex->face(1)->child(0)->line(
7270 (hex->face(1)->refinement_case() ==
7271 RefinementCase<2>::cut_x) ?
7272 1 :
7273 3), // 1
7274 hex->face(4)->child(0)->line(
7275 (hex->face(4)->refinement_case() ==
7276 RefinementCase<2>::cut_x) ?
7277 1 :
7278 3), // 2
7279 hex->face(5)->child(0)->line(
7280 (hex->face(5)->refinement_case() ==
7281 RefinementCase<2>::cut_x) ?
7282 1 :
7283 3), // 3
7284
7285 hex->face(2)
7286 ->isotropic_child(
7287 GeometryInfo<dim>::standard_to_real_face_vertex(
7288 0, f_or[2], f_fl[2], f_ro[2]))
7289 ->line(
7290 GeometryInfo<dim>::standard_to_real_face_line(
7291 3, f_or[2], f_fl[2], f_ro[2])), // 4
7292 hex->face(2)
7293 ->isotropic_child(
7294 GeometryInfo<dim>::standard_to_real_face_vertex(
7295 3, f_or[2], f_fl[2], f_ro[2]))
7296 ->line(
7297 GeometryInfo<dim>::standard_to_real_face_line(
7298 2, f_or[2], f_fl[2], f_ro[2])), // 5
7299 hex->face(2)
7300 ->isotropic_child(
7301 GeometryInfo<dim>::standard_to_real_face_vertex(
7302 0, f_or[2], f_fl[2], f_ro[2]))
7303 ->line(
7304 GeometryInfo<dim>::standard_to_real_face_line(
7305 1, f_or[2], f_fl[2], f_ro[2])), // 6
7306 hex->face(2)
7307 ->isotropic_child(
7308 GeometryInfo<dim>::standard_to_real_face_vertex(
7309 3, f_or[2], f_fl[2], f_ro[2]))
7310 ->line(
7311 GeometryInfo<dim>::standard_to_real_face_line(
7312 0, f_or[2], f_fl[2], f_ro[2])), // 7
7313
7314 hex->face(3)
7315 ->isotropic_child(
7316 GeometryInfo<dim>::standard_to_real_face_vertex(
7317 0, f_or[3], f_fl[3], f_ro[3]))
7318 ->line(
7319 GeometryInfo<dim>::standard_to_real_face_line(
7320 3, f_or[3], f_fl[3], f_ro[3])), // 8
7321 hex->face(3)
7322 ->isotropic_child(
7323 GeometryInfo<dim>::standard_to_real_face_vertex(
7324 3, f_or[3], f_fl[3], f_ro[3]))
7325 ->line(
7326 GeometryInfo<dim>::standard_to_real_face_line(
7327 2, f_or[3], f_fl[3], f_ro[3])), // 9
7328 hex->face(3)
7329 ->isotropic_child(
7330 GeometryInfo<dim>::standard_to_real_face_vertex(
7331 0, f_or[3], f_fl[3], f_ro[3]))
7332 ->line(
7333 GeometryInfo<dim>::standard_to_real_face_line(
7334 1, f_or[3], f_fl[3], f_ro[3])), // 10
7335 hex->face(3)
7336 ->isotropic_child(
7337 GeometryInfo<dim>::standard_to_real_face_vertex(
7338 3, f_or[3], f_fl[3], f_ro[3]))
7339 ->line(
7340 GeometryInfo<dim>::standard_to_real_face_line(
7341 0, f_or[3], f_fl[3], f_ro[3])), // 11
7342
7343 new_lines[0] // 12
7344 };
7345
7346 unsigned int line_indices[13];
7347 for (unsigned int i = 0; i < 13; ++i)
7348 line_indices[i] = lines[i]->index();
7349
7350 // the orientation of lines for the inner quads
7351 // is quite tricky. as these lines are newly
7352 // created ones and thus have no parents, they
7353 // cannot inherit this property. set up an array
7354 // and fill it with the respective values
7355 bool line_orientation[13];
7356
7357 // the middle vertices of the
7358 // lines of our front face
7359 const unsigned int middle_vertices[4] = {
7360 hex->line(8)->child(0)->vertex_index(1),
7361 hex->line(9)->child(0)->vertex_index(1),
7362 hex->line(2)->child(0)->vertex_index(1),
7363 hex->line(6)->child(0)->vertex_index(1),
7364 };
7365
7366 // note: for lines 0 to 3 the orientation of the
7367 // line is 'true', if vertex 0 is on the front
7368 for (unsigned int i = 0; i < 4; ++i)
7369 if (lines[i]->vertex_index(0) == middle_vertices[i])
7370 line_orientation[i] = true;
7371 else
7372 {
7373 // it must be the other way round then
7374 Assert(lines[i]->vertex_index(1) ==
7375 middle_vertices[i],
7376 ExcInternalError());
7377 line_orientation[i] = false;
7378 }
7379
7380 // note: for lines 4 to 11 (inner lines of the
7381 // outer quads) the following holds: the second
7382 // vertex of the even lines in standard
7383 // orientation is the vertex in the middle of
7384 // the quad, whereas for odd lines the first
7385 // vertex is the same middle vertex.
7386 for (unsigned int i = 4; i < 12; ++i)
7387 if (lines[i]->vertex_index((i + 1) % 2) ==
7388 middle_vertex_index<dim, spacedim>(
7389 hex->face(1 + i / 4)))
7390 line_orientation[i] = true;
7391 else
7392 {
7393 // it must be the other way
7394 // round then
7395 Assert(lines[i]->vertex_index(i % 2) ==
7396 (middle_vertex_index<dim, spacedim>(
7397 hex->face(1 + i / 4))),
7398 ExcInternalError());
7399 line_orientation[i] = false;
7400 }
7401 // for the last line the line orientation is
7402 // always true, since it was just constructed
7403 // that way
7404 line_orientation[12] = true;
7405
7406 // set up the 4 quads, numbered as follows (left
7407 // quad numbering, right line numbering
7408 // extracted from above), the drawings denote
7409 // middle planes
7410 //
7411 // * *
7412 // /| /|
7413 // / | 3 9
7414 // y/ * / *
7415 // * 3/| * /|
7416 // | / |x 5 12|8
7417 // |/ * |/ *
7418 // * 2/ * /
7419 // | / 4 2
7420 // |/ |/
7421 // * *
7422 //
7423 // y
7424 // *----*----* *-10-*-11-*
7425 // / / / / / /
7426 // / 0 / 1 / 0 12 1
7427 // / / / / / /
7428 // *----*----*x *--6-*--7-*
7429
7430 new_quads[0]->set_bounding_object_indices(
7431 {line_indices[0],
7432 line_indices[12],
7433 line_indices[6],
7434 line_indices[10]});
7435 new_quads[1]->set_bounding_object_indices(
7436 {line_indices[12],
7437 line_indices[1],
7438 line_indices[7],
7439 line_indices[11]});
7440 new_quads[2]->set_bounding_object_indices(
7441 {line_indices[4],
7442 line_indices[8],
7443 line_indices[2],
7444 line_indices[12]});
7445 new_quads[3]->set_bounding_object_indices(
7446 {line_indices[5],
7447 line_indices[9],
7448 line_indices[12],
7449 line_indices[3]});
7450
7451 new_quads[0]->set_line_orientation(
7452 0, line_orientation[0]);
7453 new_quads[0]->set_line_orientation(
7454 2, line_orientation[6]);
7455 new_quads[0]->set_line_orientation(
7456 3, line_orientation[10]);
7457
7458 new_quads[1]->set_line_orientation(
7459 1, line_orientation[1]);
7460 new_quads[1]->set_line_orientation(
7461 2, line_orientation[7]);
7462 new_quads[1]->set_line_orientation(
7463 3, line_orientation[11]);
7464
7465 new_quads[2]->set_line_orientation(
7466 0, line_orientation[4]);
7467 new_quads[2]->set_line_orientation(
7468 1, line_orientation[8]);
7469 new_quads[2]->set_line_orientation(
7470 2, line_orientation[2]);
7471
7472 new_quads[3]->set_line_orientation(
7473 0, line_orientation[5]);
7474 new_quads[3]->set_line_orientation(
7475 1, line_orientation[9]);
7476 new_quads[3]->set_line_orientation(
7477 3, line_orientation[3]);
7478
7479 // the quads are numbered as follows:
7480 //
7481 // planes in the interior of the old hex:
7482 //
7483 // *
7484 // /|
7485 // / | x
7486 // /3 * *-------* *----*----*
7487 // * /| | | / / /
7488 // | / | | | / 0 / 1 /
7489 // |/ * | | / / /
7490 // * 2/ *-------*y *----*----*x
7491 // | /
7492 // |/
7493 // *
7494 //
7495 // children of the faces
7496 // of the old hex
7497 // *---*---* *---*---*
7498 // /|13 | 15| / / /|
7499 // / | | | /18 / 19/ |
7500 // / *---*---* / / / *
7501 // * 5/| | | *---*---* 7/|
7502 // | / |12 | 14| | 9 | 11| / |
7503 // |/4 *---*---* | | |/6 *
7504 // * / / / *---*---* /
7505 // | /16 / 17/ | | | /
7506 // |/ / / | 8 | 10|/
7507 // *---*---* *---*---*
7508 //
7509 // note that we have to take care of the
7510 // orientation of faces.
7511 const int quad_indices[20] = {
7512 new_quads[0]->index(), // 0
7513 new_quads[1]->index(),
7514 new_quads[2]->index(),
7515 new_quads[3]->index(),
7516
7517 hex->face(0)->child_index(
7518 child_at_origin[hex->face(0)->refinement_case() -
7519 1][f_fl[0]][f_ro[0]]), // 4
7520 hex->face(0)->child_index(
7521 1 -
7522 child_at_origin[hex->face(0)->refinement_case() -
7523 1][f_fl[0]][f_ro[0]]),
7524
7525 hex->face(1)->child_index(
7526 child_at_origin[hex->face(1)->refinement_case() -
7527 1][f_fl[1]][f_ro[1]]), // 6
7528 hex->face(1)->child_index(
7529 1 -
7530 child_at_origin[hex->face(1)->refinement_case() -
7531 1][f_fl[1]][f_ro[1]]),
7532
7533 hex->face(2)->isotropic_child_index(
7534 GeometryInfo<dim>::standard_to_real_face_vertex(
7535 0, f_or[2], f_fl[2], f_ro[2])), // 8
7536 hex->face(2)->isotropic_child_index(
7537 GeometryInfo<dim>::standard_to_real_face_vertex(
7538 1, f_or[2], f_fl[2], f_ro[2])),
7539 hex->face(2)->isotropic_child_index(
7540 GeometryInfo<dim>::standard_to_real_face_vertex(
7541 2, f_or[2], f_fl[2], f_ro[2])),
7542 hex->face(2)->isotropic_child_index(
7543 GeometryInfo<dim>::standard_to_real_face_vertex(
7544 3, f_or[2], f_fl[2], f_ro[2])),
7545
7546 hex->face(3)->isotropic_child_index(
7547 GeometryInfo<dim>::standard_to_real_face_vertex(
7548 0, f_or[3], f_fl[3], f_ro[3])), // 12
7549 hex->face(3)->isotropic_child_index(
7550 GeometryInfo<dim>::standard_to_real_face_vertex(
7551 1, f_or[3], f_fl[3], f_ro[3])),
7552 hex->face(3)->isotropic_child_index(
7553 GeometryInfo<dim>::standard_to_real_face_vertex(
7554 2, f_or[3], f_fl[3], f_ro[3])),
7555 hex->face(3)->isotropic_child_index(
7556 GeometryInfo<dim>::standard_to_real_face_vertex(
7557 3, f_or[3], f_fl[3], f_ro[3])),
7558
7559 hex->face(4)->child_index(
7560 child_at_origin[hex->face(4)->refinement_case() -
7561 1][f_fl[4]][f_ro[4]]), // 16
7562 hex->face(4)->child_index(
7563 1 -
7564 child_at_origin[hex->face(4)->refinement_case() -
7565 1][f_fl[4]][f_ro[4]]),
7566
7567 hex->face(5)->child_index(
7568 child_at_origin[hex->face(5)->refinement_case() -
7569 1][f_fl[5]][f_ro[5]]), // 18
7570 hex->face(5)->child_index(
7571 1 -
7572 child_at_origin[hex->face(5)->refinement_case() -
7573 1][f_fl[5]][f_ro[5]])};
7574
7575 // due to the exchange of x and y for the front
7576 // and back face, we order the children
7577 // according to
7578 //
7579 // *---*---*
7580 // | 1 | 3 |
7581 // *---*---*
7582 // | 0 | 2 |
7583 // *---*---*
7584 new_hexes[0]->set_bounding_object_indices(
7585 {quad_indices[4],
7586 quad_indices[2],
7587 quad_indices[8],
7588 quad_indices[12],
7589 quad_indices[16],
7590 quad_indices[0]});
7591 new_hexes[1]->set_bounding_object_indices(
7592 {quad_indices[5],
7593 quad_indices[3],
7594 quad_indices[9],
7595 quad_indices[13],
7596 quad_indices[0],
7597 quad_indices[18]});
7598 new_hexes[2]->set_bounding_object_indices(
7599 {quad_indices[2],
7600 quad_indices[6],
7601 quad_indices[10],
7602 quad_indices[14],
7603 quad_indices[17],
7604 quad_indices[1]});
7605 new_hexes[3]->set_bounding_object_indices(
7606 {quad_indices[3],
7607 quad_indices[7],
7608 quad_indices[11],
7609 quad_indices[15],
7610 quad_indices[1],
7611 quad_indices[19]});
7612 break;
7613 }
7614
7615 case RefinementCase<dim>::cut_yz:
7616 {
7617 //////////////////////////////
7618 //
7619 // RefinementCase<dim>::cut_yz
7620 //
7621 // the refined cube will look like this:
7622 //
7623 // *---------*
7624 // / /|
7625 // *---------* |
7626 // / /| |
7627 // *---------* |/|
7628 // | | * |
7629 // | |/| *
7630 // *---------* |/
7631 // | | *
7632 // | |/
7633 // *---------*
7634 //
7635
7636 // first, create the new
7637 // internal line
7638 new_lines[0]->set_bounding_object_indices(
7639
7640 {middle_vertex_index<dim, spacedim>(hex->face(0)),
7641 middle_vertex_index<dim, spacedim>(hex->face(1))});
7642
7643 // again, first collect some data about the
7644 // indices of the lines, with the following
7645 // numbering: (note that face 0 and 1 each are
7646 // shown twice for better readability)
7647
7648 // face 0: left plane
7649 // * *
7650 // /| /|
7651 // * | * |
7652 // /| * /| *
7653 // * 5/| * |7|
7654 // | * | | * |
7655 // |/| * |6| *
7656 // * 4/ * |/
7657 // | * | *
7658 // |/ |/
7659 // * *
7660 // face 1: right plane
7661 // * *
7662 // /| /|
7663 // * | * |
7664 // /| * /| *
7665 // * 9/| * |11
7666 // | * | | * |
7667 // |/| * |10 *
7668 // * 8/ * |/
7669 // | * | *
7670 // |/ |/
7671 // * *
7672 // face 2: front plane
7673 // (note: x,y exchanged)
7674 // *-------*
7675 // | |
7676 // *---0---*
7677 // | |
7678 // *-------*
7679 // face 3: back plane
7680 // (note: x,y exchanged)
7681 // *-------*
7682 // | |
7683 // *---1---*
7684 // | |
7685 // *-------*
7686 // face 4: bottom plane
7687 // *-------*
7688 // / /
7689 // *---2---*
7690 // / /
7691 // *-------*
7692 // face 5: top plane
7693 // *-------*
7694 // / /
7695 // *---3---*
7696 // / /
7697 // *-------*
7698 // middle planes
7699 // *-------* *-------*
7700 // / / | |
7701 // *---12--* | |
7702 // / / | |
7703 // *-------* *-------*
7704
7705 // set up a list of line iterators first. from
7706 // this, construct lists of line_indices and
7707 // line orientations later on
7708 const typename Triangulation<
7709 dim,
7710 spacedim>::raw_line_iterator lines[13] = {
7711 hex->face(2)->child(0)->line(
7712 (hex->face(2)->refinement_case() ==
7713 RefinementCase<2>::cut_x) ?
7714 1 :
7715 3), // 0
7716 hex->face(3)->child(0)->line(
7717 (hex->face(3)->refinement_case() ==
7718 RefinementCase<2>::cut_x) ?
7719 1 :
7720 3), // 1
7721 hex->face(4)->child(0)->line(
7722 (hex->face(4)->refinement_case() ==
7723 RefinementCase<2>::cut_x) ?
7724 1 :
7725 3), // 2
7726 hex->face(5)->child(0)->line(
7727 (hex->face(5)->refinement_case() ==
7728 RefinementCase<2>::cut_x) ?
7729 1 :
7730 3), // 3
7731
7732 hex->face(0)
7733 ->isotropic_child(
7734 GeometryInfo<dim>::standard_to_real_face_vertex(
7735 0, f_or[0], f_fl[0], f_ro[0]))
7736 ->line(
7737 GeometryInfo<dim>::standard_to_real_face_line(
7738 1, f_or[0], f_fl[0], f_ro[0])), // 4
7739 hex->face(0)
7740 ->isotropic_child(
7741 GeometryInfo<dim>::standard_to_real_face_vertex(
7742 3, f_or[0], f_fl[0], f_ro[0]))
7743 ->line(
7744 GeometryInfo<dim>::standard_to_real_face_line(
7745 0, f_or[0], f_fl[0], f_ro[0])), // 5
7746 hex->face(0)
7747 ->isotropic_child(
7748 GeometryInfo<dim>::standard_to_real_face_vertex(
7749 0, f_or[0], f_fl[0], f_ro[0]))
7750 ->line(
7751 GeometryInfo<dim>::standard_to_real_face_line(
7752 3, f_or[0], f_fl[0], f_ro[0])), // 6
7753 hex->face(0)
7754 ->isotropic_child(
7755 GeometryInfo<dim>::standard_to_real_face_vertex(
7756 3, f_or[0], f_fl[0], f_ro[0]))
7757 ->line(
7758 GeometryInfo<dim>::standard_to_real_face_line(
7759 2, f_or[0], f_fl[0], f_ro[0])), // 7
7760
7761 hex->face(1)
7762 ->isotropic_child(
7763 GeometryInfo<dim>::standard_to_real_face_vertex(
7764 0, f_or[1], f_fl[1], f_ro[1]))
7765 ->line(
7766 GeometryInfo<dim>::standard_to_real_face_line(
7767 1, f_or[1], f_fl[1], f_ro[1])), // 8
7768 hex->face(1)
7769 ->isotropic_child(
7770 GeometryInfo<dim>::standard_to_real_face_vertex(
7771 3, f_or[1], f_fl[1], f_ro[1]))
7772 ->line(
7773 GeometryInfo<dim>::standard_to_real_face_line(
7774 0, f_or[1], f_fl[1], f_ro[1])), // 9
7775 hex->face(1)
7776 ->isotropic_child(
7777 GeometryInfo<dim>::standard_to_real_face_vertex(
7778 0, f_or[1], f_fl[1], f_ro[1]))
7779 ->line(
7780 GeometryInfo<dim>::standard_to_real_face_line(
7781 3, f_or[1], f_fl[1], f_ro[1])), // 10
7782 hex->face(1)
7783 ->isotropic_child(
7784 GeometryInfo<dim>::standard_to_real_face_vertex(
7785 3, f_or[1], f_fl[1], f_ro[1]))
7786 ->line(
7787 GeometryInfo<dim>::standard_to_real_face_line(
7788 2, f_or[1], f_fl[1], f_ro[1])), // 11
7789
7790 new_lines[0] // 12
7791 };
7792
7793 unsigned int line_indices[13];
7794
7795 for (unsigned int i = 0; i < 13; ++i)
7796 line_indices[i] = lines[i]->index();
7797
7798 // the orientation of lines for the inner quads
7799 // is quite tricky. as these lines are newly
7800 // created ones and thus have no parents, they
7801 // cannot inherit this property. set up an array
7802 // and fill it with the respective values
7803 bool line_orientation[13];
7804
7805 // the middle vertices of the lines of our front
7806 // face
7807 const unsigned int middle_vertices[4] = {
7808 hex->line(8)->child(0)->vertex_index(1),
7809 hex->line(10)->child(0)->vertex_index(1),
7810 hex->line(0)->child(0)->vertex_index(1),
7811 hex->line(4)->child(0)->vertex_index(1),
7812 };
7813
7814 // note: for lines 0 to 3 the orientation of the
7815 // line is 'true', if vertex 0 is on the front
7816 for (unsigned int i = 0; i < 4; ++i)
7817 if (lines[i]->vertex_index(0) == middle_vertices[i])
7818 line_orientation[i] = true;
7819 else
7820 {
7821 // it must be the other way round then
7822 Assert(lines[i]->vertex_index(1) ==
7823 middle_vertices[i],
7824 ExcInternalError());
7825 line_orientation[i] = false;
7826 }
7827
7828 // note: for lines 4 to 11 (inner lines of the
7829 // outer quads) the following holds: the second
7830 // vertex of the even lines in standard
7831 // orientation is the vertex in the middle of
7832 // the quad, whereas for odd lines the first
7833 // vertex is the same middle vertex.
7834 for (unsigned int i = 4; i < 12; ++i)
7835 if (lines[i]->vertex_index((i + 1) % 2) ==
7836 middle_vertex_index<dim, spacedim>(
7837 hex->face(i / 4 - 1)))
7838 line_orientation[i] = true;
7839 else
7840 {
7841 // it must be the other way
7842 // round then
7843 Assert(lines[i]->vertex_index(i % 2) ==
7844 (middle_vertex_index<dim, spacedim>(
7845 hex->face(i / 4 - 1))),
7846 ExcInternalError());
7847 line_orientation[i] = false;
7848 }
7849 // for the last line the line orientation is
7850 // always true, since it was just constructed
7851 // that way
7852 line_orientation[12] = true;
7853
7854 // set up the 4 quads, numbered as follows (left
7855 // quad numbering, right line numbering
7856 // extracted from above)
7857 //
7858 // x
7859 // *-------* *---3---*
7860 // | 3 | 5 9
7861 // *-------* *---12--*
7862 // | 2 | 4 8
7863 // *-------*y *---2---*
7864 //
7865 // y
7866 // *---------* *----1----*
7867 // / 1 / 7 11
7868 // *---------* *----12---*
7869 // / 0 / 6 10
7870 // *---------*x *----0----*
7871
7872 new_quads[0]->set_bounding_object_indices(
7873 {line_indices[6],
7874 line_indices[10],
7875 line_indices[0],
7876 line_indices[12]});
7877 new_quads[1]->set_bounding_object_indices(
7878 {line_indices[7],
7879 line_indices[11],
7880 line_indices[12],
7881 line_indices[1]});
7882 new_quads[2]->set_bounding_object_indices(
7883 {line_indices[2],
7884 line_indices[12],
7885 line_indices[4],
7886 line_indices[8]});
7887 new_quads[3]->set_bounding_object_indices(
7888 {line_indices[12],
7889 line_indices[3],
7890 line_indices[5],
7891 line_indices[9]});
7892
7893 new_quads[0]->set_line_orientation(
7894 0, line_orientation[6]);
7895 new_quads[0]->set_line_orientation(
7896 1, line_orientation[10]);
7897 new_quads[0]->set_line_orientation(
7898 2, line_orientation[0]);
7899
7900 new_quads[1]->set_line_orientation(
7901 0, line_orientation[7]);
7902 new_quads[1]->set_line_orientation(
7903 1, line_orientation[11]);
7904 new_quads[1]->set_line_orientation(
7905 3, line_orientation[1]);
7906
7907 new_quads[2]->set_line_orientation(
7908 0, line_orientation[2]);
7909 new_quads[2]->set_line_orientation(
7910 2, line_orientation[4]);
7911 new_quads[2]->set_line_orientation(
7912 3, line_orientation[8]);
7913
7914 new_quads[3]->set_line_orientation(
7915 1, line_orientation[3]);
7916 new_quads[3]->set_line_orientation(
7917 2, line_orientation[5]);
7918 new_quads[3]->set_line_orientation(
7919 3, line_orientation[9]);
7920
7921 // the quads are numbered as follows:
7922 //
7923 // planes in the interior of the old hex:
7924 //
7925 // *
7926 // /|
7927 // / | x
7928 // / | *-------* *---------*
7929 // * | | 3 | / 1 /
7930 // | | *-------* *---------*
7931 // | * | 2 | / 0 /
7932 // | / *-------*y *---------*x
7933 // | /
7934 // |/
7935 // *
7936 //
7937 // children of the faces
7938 // of the old hex
7939 // *-------* *-------*
7940 // /| | / 19 /|
7941 // * | 15 | *-------* |
7942 // /|7*-------* / 18 /|11
7943 // * |/| | *-------* |/|
7944 // |6* | 14 | | 10* |
7945 // |/|5*-------* | 13 |/|9*
7946 // * |/ 17 / *-------* |/
7947 // |4*-------* | |8*
7948 // |/ 16 / | 12 |/
7949 // *-------* *-------*
7950 //
7951 // note that we have to take care of the
7952 // orientation of faces.
7953 const int quad_indices[20] = {
7954 new_quads[0]->index(), // 0
7955 new_quads[1]->index(),
7956 new_quads[2]->index(),
7957 new_quads[3]->index(),
7958
7959 hex->face(0)->isotropic_child_index(
7960 GeometryInfo<dim>::standard_to_real_face_vertex(
7961 0, f_or[0], f_fl[0], f_ro[0])), // 4
7962 hex->face(0)->isotropic_child_index(
7963 GeometryInfo<dim>::standard_to_real_face_vertex(
7964 1, f_or[0], f_fl[0], f_ro[0])),
7965 hex->face(0)->isotropic_child_index(
7966 GeometryInfo<dim>::standard_to_real_face_vertex(
7967 2, f_or[0], f_fl[0], f_ro[0])),
7968 hex->face(0)->isotropic_child_index(
7969 GeometryInfo<dim>::standard_to_real_face_vertex(
7970 3, f_or[0], f_fl[0], f_ro[0])),
7971
7972 hex->face(1)->isotropic_child_index(
7973 GeometryInfo<dim>::standard_to_real_face_vertex(
7974 0, f_or[1], f_fl[1], f_ro[1])), // 8
7975 hex->face(1)->isotropic_child_index(
7976 GeometryInfo<dim>::standard_to_real_face_vertex(
7977 1, f_or[1], f_fl[1], f_ro[1])),
7978 hex->face(1)->isotropic_child_index(
7979 GeometryInfo<dim>::standard_to_real_face_vertex(
7980 2, f_or[1], f_fl[1], f_ro[1])),
7981 hex->face(1)->isotropic_child_index(
7982 GeometryInfo<dim>::standard_to_real_face_vertex(
7983 3, f_or[1], f_fl[1], f_ro[1])),
7984
7985 hex->face(2)->child_index(
7986 child_at_origin[hex->face(2)->refinement_case() -
7987 1][f_fl[2]][f_ro[2]]), // 12
7988 hex->face(2)->child_index(
7989 1 -
7990 child_at_origin[hex->face(2)->refinement_case() -
7991 1][f_fl[2]][f_ro[2]]),
7992
7993 hex->face(3)->child_index(
7994 child_at_origin[hex->face(3)->refinement_case() -
7995 1][f_fl[3]][f_ro[3]]), // 14
7996 hex->face(3)->child_index(
7997 1 -
7998 child_at_origin[hex->face(3)->refinement_case() -
7999 1][f_fl[3]][f_ro[3]]),
8000
8001 hex->face(4)->child_index(
8002 child_at_origin[hex->face(4)->refinement_case() -
8003 1][f_fl[4]][f_ro[4]]), // 16
8004 hex->face(4)->child_index(
8005 1 -
8006 child_at_origin[hex->face(4)->refinement_case() -
8007 1][f_fl[4]][f_ro[4]]),
8008
8009 hex->face(5)->child_index(
8010 child_at_origin[hex->face(5)->refinement_case() -
8011 1][f_fl[5]][f_ro[5]]), // 18
8012 hex->face(5)->child_index(
8013 1 -
8014 child_at_origin[hex->face(5)->refinement_case() -
8015 1][f_fl[5]][f_ro[5]])};
8016
8017 new_hexes[0]->set_bounding_object_indices(
8018 {quad_indices[4],
8019 quad_indices[8],
8020 quad_indices[12],
8021 quad_indices[2],
8022 quad_indices[16],
8023 quad_indices[0]});
8024 new_hexes[1]->set_bounding_object_indices(
8025 {quad_indices[5],
8026 quad_indices[9],
8027 quad_indices[2],
8028 quad_indices[14],
8029 quad_indices[17],
8030 quad_indices[1]});
8031 new_hexes[2]->set_bounding_object_indices(
8032 {quad_indices[6],
8033 quad_indices[10],
8034 quad_indices[13],
8035 quad_indices[3],
8036 quad_indices[0],
8037 quad_indices[18]});
8038 new_hexes[3]->set_bounding_object_indices(
8039 {quad_indices[7],
8040 quad_indices[11],
8041 quad_indices[3],
8042 quad_indices[15],
8043 quad_indices[1],
8044 quad_indices[19]});
8045 break;
8046 }
8047
8048 case RefinementCase<dim>::cut_xyz:
8049 {
8050 //////////////////////////////
8051 //
8052 // RefinementCase<dim>::cut_xyz
8053 // isotropic refinement
8054 //
8055 // the refined cube will look
8056 // like this:
8057 //
8058 // *----*----*
8059 // / / /|
8060 // *----*----* |
8061 // / / /| *
8062 // *----*----* |/|
8063 // | | | * |
8064 // | | |/| *
8065 // *----*----* |/
8066 // | | | *
8067 // | | |/
8068 // *----*----*
8069 //
8070
8071 // find the next unused vertex and set it
8072 // appropriately
8073 while (
8074 triangulation.vertices_used[next_unused_vertex] ==
8075 true)
8076 ++next_unused_vertex;
8077 Assert(
8078 next_unused_vertex < triangulation.vertices.size(),
8079 ExcMessage(
8080 "Internal error: During refinement, the triangulation wants to access an element of the 'vertices' array but it turns out that the array is not large enough."));
8081 triangulation.vertices_used[next_unused_vertex] =
8082 true;
8083
8084 // the new vertex is definitely in the interior,
8085 // so we need not worry about the
8086 // boundary. However we need to worry about
8087 // Manifolds. Let the cell compute its own
8088 // center, by querying the underlying manifold
8089 // object.
8090 triangulation.vertices[next_unused_vertex] =
8091 hex->center(true, true);
8092
8093 // set the data of the six lines. first collect
8094 // the indices of the seven vertices (consider
8095 // the two planes to be crossed to form the
8096 // planes cutting the hex in two vertically and
8097 // horizontally)
8098 //
8099 // *--3--* *--5--*
8100 // / / / | | |
8101 // 0--6--1 0--6--1
8102 // / / / | | |
8103 // *--2--* *--4--*
8104 // the lines are numbered
8105 // as follows:
8106 // *--*--* *--*--*
8107 // / 1 / | 5 |
8108 // *2-*-3* *2-*-3*
8109 // / 0 / | 4 |
8110 // *--*--* *--*--*
8111 //
8112 const unsigned int vertex_indices[7] = {
8113 middle_vertex_index<dim, spacedim>(hex->face(0)),
8114 middle_vertex_index<dim, spacedim>(hex->face(1)),
8115 middle_vertex_index<dim, spacedim>(hex->face(2)),
8116 middle_vertex_index<dim, spacedim>(hex->face(3)),
8117 middle_vertex_index<dim, spacedim>(hex->face(4)),
8118 middle_vertex_index<dim, spacedim>(hex->face(5)),
8119 next_unused_vertex};
8120
8121 new_lines[0]->set_bounding_object_indices(
8122 {vertex_indices[2], vertex_indices[6]});
8123 new_lines[1]->set_bounding_object_indices(
8124 {vertex_indices[6], vertex_indices[3]});
8125 new_lines[2]->set_bounding_object_indices(
8126 {vertex_indices[0], vertex_indices[6]});
8127 new_lines[3]->set_bounding_object_indices(
8128 {vertex_indices[6], vertex_indices[1]});
8129 new_lines[4]->set_bounding_object_indices(
8130 {vertex_indices[4], vertex_indices[6]});
8131 new_lines[5]->set_bounding_object_indices(
8132 {vertex_indices[6], vertex_indices[5]});
8133
8134 // again, first collect some data about the
8135 // indices of the lines, with the following
8136 // numbering: (note that face 0 and 1 each are
8137 // shown twice for better readability)
8138
8139 // face 0: left plane
8140 // * *
8141 // /| /|
8142 // * | * |
8143 // /| * /| *
8144 // * 1/| * |3|
8145 // | * | | * |
8146 // |/| * |2| *
8147 // * 0/ * |/
8148 // | * | *
8149 // |/ |/
8150 // * *
8151 // face 1: right plane
8152 // * *
8153 // /| /|
8154 // * | * |
8155 // /| * /| *
8156 // * 5/| * |7|
8157 // | * | | * |
8158 // |/| * |6| *
8159 // * 4/ * |/
8160 // | * | *
8161 // |/ |/
8162 // * *
8163 // face 2: front plane
8164 // (note: x,y exchanged)
8165 // *---*---*
8166 // | 11 |
8167 // *-8-*-9-*
8168 // | 10 |
8169 // *---*---*
8170 // face 3: back plane
8171 // (note: x,y exchanged)
8172 // *---*---*
8173 // | 15 |
8174 // *12-*-13*
8175 // | 14 |
8176 // *---*---*
8177 // face 4: bottom plane
8178 // *---*---*
8179 // / 17 /
8180 // *18-*-19*
8181 // / 16 /
8182 // *---*---*
8183 // face 5: top plane
8184 // *---*---*
8185 // / 21 /
8186 // *22-*-23*
8187 // / 20 /
8188 // *---*---*
8189 // middle planes
8190 // *---*---* *---*---*
8191 // / 25 / | 29 |
8192 // *26-*-27* *26-*-27*
8193 // / 24 / | 28 |
8194 // *---*---* *---*---*
8195
8196 // set up a list of line iterators first. from
8197 // this, construct lists of line_indices and
8198 // line orientations later on
8199 const typename Triangulation<
8200 dim,
8201 spacedim>::raw_line_iterator lines[30] = {
8202 hex->face(0)
8203 ->isotropic_child(
8204 GeometryInfo<dim>::standard_to_real_face_vertex(
8205 0, f_or[0], f_fl[0], f_ro[0]))
8206 ->line(
8207 GeometryInfo<dim>::standard_to_real_face_line(
8208 1, f_or[0], f_fl[0], f_ro[0])), // 0
8209 hex->face(0)
8210 ->isotropic_child(
8211 GeometryInfo<dim>::standard_to_real_face_vertex(
8212 3, f_or[0], f_fl[0], f_ro[0]))
8213 ->line(
8214 GeometryInfo<dim>::standard_to_real_face_line(
8215 0, f_or[0], f_fl[0], f_ro[0])), // 1
8216 hex->face(0)
8217 ->isotropic_child(
8218 GeometryInfo<dim>::standard_to_real_face_vertex(
8219 0, f_or[0], f_fl[0], f_ro[0]))
8220 ->line(
8221 GeometryInfo<dim>::standard_to_real_face_line(
8222 3, f_or[0], f_fl[0], f_ro[0])), // 2
8223 hex->face(0)
8224 ->isotropic_child(
8225 GeometryInfo<dim>::standard_to_real_face_vertex(
8226 3, f_or[0], f_fl[0], f_ro[0]))
8227 ->line(
8228 GeometryInfo<dim>::standard_to_real_face_line(
8229 2, f_or[0], f_fl[0], f_ro[0])), // 3
8230
8231 hex->face(1)
8232 ->isotropic_child(
8233 GeometryInfo<dim>::standard_to_real_face_vertex(
8234 0, f_or[1], f_fl[1], f_ro[1]))
8235 ->line(
8236 GeometryInfo<dim>::standard_to_real_face_line(
8237 1, f_or[1], f_fl[1], f_ro[1])), // 4
8238 hex->face(1)
8239 ->isotropic_child(
8240 GeometryInfo<dim>::standard_to_real_face_vertex(
8241 3, f_or[1], f_fl[1], f_ro[1]))
8242 ->line(
8243 GeometryInfo<dim>::standard_to_real_face_line(
8244 0, f_or[1], f_fl[1], f_ro[1])), // 5
8245 hex->face(1)
8246 ->isotropic_child(
8247 GeometryInfo<dim>::standard_to_real_face_vertex(
8248 0, f_or[1], f_fl[1], f_ro[1]))
8249 ->line(
8250 GeometryInfo<dim>::standard_to_real_face_line(
8251 3, f_or[1], f_fl[1], f_ro[1])), // 6
8252 hex->face(1)
8253 ->isotropic_child(
8254 GeometryInfo<dim>::standard_to_real_face_vertex(
8255 3, f_or[1], f_fl[1], f_ro[1]))
8256 ->line(
8257 GeometryInfo<dim>::standard_to_real_face_line(
8258 2, f_or[1], f_fl[1], f_ro[1])), // 7
8259
8260 hex->face(2)
8261 ->isotropic_child(
8262 GeometryInfo<dim>::standard_to_real_face_vertex(
8263 0, f_or[2], f_fl[2], f_ro[2]))
8264 ->line(
8265 GeometryInfo<dim>::standard_to_real_face_line(
8266 1, f_or[2], f_fl[2], f_ro[2])), // 8
8267 hex->face(2)
8268 ->isotropic_child(
8269 GeometryInfo<dim>::standard_to_real_face_vertex(
8270 3, f_or[2], f_fl[2], f_ro[2]))
8271 ->line(
8272 GeometryInfo<dim>::standard_to_real_face_line(
8273 0, f_or[2], f_fl[2], f_ro[2])), // 9
8274 hex->face(2)
8275 ->isotropic_child(
8276 GeometryInfo<dim>::standard_to_real_face_vertex(
8277 0, f_or[2], f_fl[2], f_ro[2]))
8278 ->line(
8279 GeometryInfo<dim>::standard_to_real_face_line(
8280 3, f_or[2], f_fl[2], f_ro[2])), // 10
8281 hex->face(2)
8282 ->isotropic_child(
8283 GeometryInfo<dim>::standard_to_real_face_vertex(
8284 3, f_or[2], f_fl[2], f_ro[2]))
8285 ->line(
8286 GeometryInfo<dim>::standard_to_real_face_line(
8287 2, f_or[2], f_fl[2], f_ro[2])), // 11
8288
8289 hex->face(3)
8290 ->isotropic_child(
8291 GeometryInfo<dim>::standard_to_real_face_vertex(
8292 0, f_or[3], f_fl[3], f_ro[3]))
8293 ->line(
8294 GeometryInfo<dim>::standard_to_real_face_line(
8295 1, f_or[3], f_fl[3], f_ro[3])), // 12
8296 hex->face(3)
8297 ->isotropic_child(
8298 GeometryInfo<dim>::standard_to_real_face_vertex(
8299 3, f_or[3], f_fl[3], f_ro[3]))
8300 ->line(
8301 GeometryInfo<dim>::standard_to_real_face_line(
8302 0, f_or[3], f_fl[3], f_ro[3])), // 13
8303 hex->face(3)
8304 ->isotropic_child(
8305 GeometryInfo<dim>::standard_to_real_face_vertex(
8306 0, f_or[3], f_fl[3], f_ro[3]))
8307 ->line(
8308 GeometryInfo<dim>::standard_to_real_face_line(
8309 3, f_or[3], f_fl[3], f_ro[3])), // 14
8310 hex->face(3)
8311 ->isotropic_child(
8312 GeometryInfo<dim>::standard_to_real_face_vertex(
8313 3, f_or[3], f_fl[3], f_ro[3]))
8314 ->line(
8315 GeometryInfo<dim>::standard_to_real_face_line(
8316 2, f_or[3], f_fl[3], f_ro[3])), // 15
8317
8318 hex->face(4)
8319 ->isotropic_child(
8320 GeometryInfo<dim>::standard_to_real_face_vertex(
8321 0, f_or[4], f_fl[4], f_ro[4]))
8322 ->line(
8323 GeometryInfo<dim>::standard_to_real_face_line(
8324 1, f_or[4], f_fl[4], f_ro[4])), // 16
8325 hex->face(4)
8326 ->isotropic_child(
8327 GeometryInfo<dim>::standard_to_real_face_vertex(
8328 3, f_or[4], f_fl[4], f_ro[4]))
8329 ->line(
8330 GeometryInfo<dim>::standard_to_real_face_line(
8331 0, f_or[4], f_fl[4], f_ro[4])), // 17
8332 hex->face(4)
8333 ->isotropic_child(
8334 GeometryInfo<dim>::standard_to_real_face_vertex(
8335 0, f_or[4], f_fl[4], f_ro[4]))
8336 ->line(
8337 GeometryInfo<dim>::standard_to_real_face_line(
8338 3, f_or[4], f_fl[4], f_ro[4])), // 18
8339 hex->face(4)
8340 ->isotropic_child(
8341 GeometryInfo<dim>::standard_to_real_face_vertex(
8342 3, f_or[4], f_fl[4], f_ro[4]))
8343 ->line(
8344 GeometryInfo<dim>::standard_to_real_face_line(
8345 2, f_or[4], f_fl[4], f_ro[4])), // 19
8346
8347 hex->face(5)
8348 ->isotropic_child(
8349 GeometryInfo<dim>::standard_to_real_face_vertex(
8350 0, f_or[5], f_fl[5], f_ro[5]))
8351 ->line(
8352 GeometryInfo<dim>::standard_to_real_face_line(
8353 1, f_or[5], f_fl[5], f_ro[5])), // 20
8354 hex->face(5)
8355 ->isotropic_child(
8356 GeometryInfo<dim>::standard_to_real_face_vertex(
8357 3, f_or[5], f_fl[5], f_ro[5]))
8358 ->line(
8359 GeometryInfo<dim>::standard_to_real_face_line(
8360 0, f_or[5], f_fl[5], f_ro[5])), // 21
8361 hex->face(5)
8362 ->isotropic_child(
8363 GeometryInfo<dim>::standard_to_real_face_vertex(
8364 0, f_or[5], f_fl[5], f_ro[5]))
8365 ->line(
8366 GeometryInfo<dim>::standard_to_real_face_line(
8367 3, f_or[5], f_fl[5], f_ro[5])), // 22
8368 hex->face(5)
8369 ->isotropic_child(
8370 GeometryInfo<dim>::standard_to_real_face_vertex(
8371 3, f_or[5], f_fl[5], f_ro[5]))
8372 ->line(
8373 GeometryInfo<dim>::standard_to_real_face_line(
8374 2, f_or[5], f_fl[5], f_ro[5])), // 23
8375
8376 new_lines[0], // 24
8377 new_lines[1], // 25
8378 new_lines[2], // 26
8379 new_lines[3], // 27
8380 new_lines[4], // 28
8381 new_lines[5] // 29
8382 };
8383
8384 unsigned int line_indices[30];
8385 for (unsigned int i = 0; i < 30; ++i)
8386 line_indices[i] = lines[i]->index();
8387
8388 // the orientation of lines for the inner quads
8389 // is quite tricky. as these lines are newly
8390 // created ones and thus have no parents, they
8391 // cannot inherit this property. set up an array
8392 // and fill it with the respective values
8393 bool line_orientation[30];
8394
8395 // note: for the first 24 lines (inner lines of
8396 // the outer quads) the following holds: the
8397 // second vertex of the even lines in standard
8398 // orientation is the vertex in the middle of
8399 // the quad, whereas for odd lines the first
8400 // vertex is the same middle vertex.
8401 for (unsigned int i = 0; i < 24; ++i)
8402 if (lines[i]->vertex_index((i + 1) % 2) ==
8403 vertex_indices[i / 4])
8404 line_orientation[i] = true;
8405 else
8406 {
8407 // it must be the other way
8408 // round then
8409 Assert(lines[i]->vertex_index(i % 2) ==
8410 vertex_indices[i / 4],
8411 ExcInternalError());
8412 line_orientation[i] = false;
8413 }
8414 // for the last 6 lines the line orientation is
8415 // always true, since they were just constructed
8416 // that way
8417 for (unsigned int i = 24; i < 30; ++i)
8418 line_orientation[i] = true;
8419
8420 // set up the 12 quads, numbered as follows
8421 // (left quad numbering, right line numbering
8422 // extracted from above)
8423 //
8424 // * *
8425 // /| 21|
8426 // * | * 15
8427 // y/|3* 20| *
8428 // * |/| * |/|
8429 // |2* |x 11 * 14
8430 // |/|1* |/| *
8431 // * |/ * |17
8432 // |0* 10 *
8433 // |/ |16
8434 // * *
8435 //
8436 // x
8437 // *---*---* *22-*-23*
8438 // | 5 | 7 | 1 29 5
8439 // *---*---* *26-*-27*
8440 // | 4 | 6 | 0 28 4
8441 // *---*---*y *18-*-19*
8442 //
8443 // y
8444 // *----*----* *-12-*-13-*
8445 // / 10 / 11 / 3 25 7
8446 // *----*----* *-26-*-27-*
8447 // / 8 / 9 / 2 24 6
8448 // *----*----*x *--8-*--9-*
8449
8450 new_quads[0]->set_bounding_object_indices(
8451 {line_indices[10],
8452 line_indices[28],
8453 line_indices[16],
8454 line_indices[24]});
8455 new_quads[1]->set_bounding_object_indices(
8456 {line_indices[28],
8457 line_indices[14],
8458 line_indices[17],
8459 line_indices[25]});
8460 new_quads[2]->set_bounding_object_indices(
8461 {line_indices[11],
8462 line_indices[29],
8463 line_indices[24],
8464 line_indices[20]});
8465 new_quads[3]->set_bounding_object_indices(
8466 {line_indices[29],
8467 line_indices[15],
8468 line_indices[25],
8469 line_indices[21]});
8470 new_quads[4]->set_bounding_object_indices(
8471 {line_indices[18],
8472 line_indices[26],
8473 line_indices[0],
8474 line_indices[28]});
8475 new_quads[5]->set_bounding_object_indices(
8476 {line_indices[26],
8477 line_indices[22],
8478 line_indices[1],
8479 line_indices[29]});
8480 new_quads[6]->set_bounding_object_indices(
8481 {line_indices[19],
8482 line_indices[27],
8483 line_indices[28],
8484 line_indices[4]});
8485 new_quads[7]->set_bounding_object_indices(
8486 {line_indices[27],
8487 line_indices[23],
8488 line_indices[29],
8489 line_indices[5]});
8490 new_quads[8]->set_bounding_object_indices(
8491 {line_indices[2],
8492 line_indices[24],
8493 line_indices[8],
8494 line_indices[26]});
8495 new_quads[9]->set_bounding_object_indices(
8496 {line_indices[24],
8497 line_indices[6],
8498 line_indices[9],
8499 line_indices[27]});
8500 new_quads[10]->set_bounding_object_indices(
8501 {line_indices[3],
8502 line_indices[25],
8503 line_indices[26],
8504 line_indices[12]});
8505 new_quads[11]->set_bounding_object_indices(
8506 {line_indices[25],
8507 line_indices[7],
8508 line_indices[27],
8509 line_indices[13]});
8510
8511 // now reset the line_orientation flags of outer
8512 // lines as they cannot be set in a loop (at
8513 // least not easily)
8514 new_quads[0]->set_line_orientation(
8515 0, line_orientation[10]);
8516 new_quads[0]->set_line_orientation(
8517 2, line_orientation[16]);
8518
8519 new_quads[1]->set_line_orientation(
8520 1, line_orientation[14]);
8521 new_quads[1]->set_line_orientation(
8522 2, line_orientation[17]);
8523
8524 new_quads[2]->set_line_orientation(
8525 0, line_orientation[11]);
8526 new_quads[2]->set_line_orientation(
8527 3, line_orientation[20]);
8528
8529 new_quads[3]->set_line_orientation(
8530 1, line_orientation[15]);
8531 new_quads[3]->set_line_orientation(
8532 3, line_orientation[21]);
8533
8534 new_quads[4]->set_line_orientation(
8535 0, line_orientation[18]);
8536 new_quads[4]->set_line_orientation(
8537 2, line_orientation[0]);
8538
8539 new_quads[5]->set_line_orientation(
8540 1, line_orientation[22]);
8541 new_quads[5]->set_line_orientation(
8542 2, line_orientation[1]);
8543
8544 new_quads[6]->set_line_orientation(
8545 0, line_orientation[19]);
8546 new_quads[6]->set_line_orientation(
8547 3, line_orientation[4]);
8548
8549 new_quads[7]->set_line_orientation(
8550 1, line_orientation[23]);
8551 new_quads[7]->set_line_orientation(
8552 3, line_orientation[5]);
8553
8554 new_quads[8]->set_line_orientation(
8555 0, line_orientation[2]);
8556 new_quads[8]->set_line_orientation(
8557 2, line_orientation[8]);
8558
8559 new_quads[9]->set_line_orientation(
8560 1, line_orientation[6]);
8561 new_quads[9]->set_line_orientation(
8562 2, line_orientation[9]);
8563
8564 new_quads[10]->set_line_orientation(
8565 0, line_orientation[3]);
8566 new_quads[10]->set_line_orientation(
8567 3, line_orientation[12]);
8568
8569 new_quads[11]->set_line_orientation(
8570 1, line_orientation[7]);
8571 new_quads[11]->set_line_orientation(
8572 3, line_orientation[13]);
8573
8574 /////////////////////////////////
8575 // create the eight new hexes
8576 //
8577 // again first collect some data. here, we need
8578 // the indices of a whole lotta quads.
8579
8580 // the quads are numbered as follows:
8581 //
8582 // planes in the interior of the old hex:
8583 //
8584 // *
8585 // /|
8586 // * |
8587 // /|3* *---*---* *----*----*
8588 // * |/| | 5 | 7 | / 10 / 11 /
8589 // |2* | *---*---* *----*----*
8590 // |/|1* | 4 | 6 | / 8 / 9 /
8591 // * |/ *---*---*y *----*----*x
8592 // |0*
8593 // |/
8594 // *
8595 //
8596 // children of the faces
8597 // of the old hex
8598 // *-------* *-------*
8599 // /|25 27| /34 35/|
8600 // 15| | / /19
8601 // / | | /32 33/ |
8602 // * |24 26| *-------*18 |
8603 // 1413*-------* |21 23| 17*
8604 // | /30 31/ | | /
8605 // 12/ / | |16
8606 // |/28 29/ |20 22|/
8607 // *-------* *-------*
8608 //
8609 // note that we have to
8610 // take care of the
8611 // orientation of
8612 // faces.
8613 const int quad_indices[36] = {
8614 new_quads[0]->index(), // 0
8615 new_quads[1]->index(),
8616 new_quads[2]->index(),
8617 new_quads[3]->index(),
8618 new_quads[4]->index(),
8619 new_quads[5]->index(),
8620 new_quads[6]->index(),
8621 new_quads[7]->index(),
8622 new_quads[8]->index(),
8623 new_quads[9]->index(),
8624 new_quads[10]->index(),
8625 new_quads[11]->index(), // 11
8626
8627 hex->face(0)->isotropic_child_index(
8628 GeometryInfo<dim>::standard_to_real_face_vertex(
8629 0, f_or[0], f_fl[0], f_ro[0])), // 12
8630 hex->face(0)->isotropic_child_index(
8631 GeometryInfo<dim>::standard_to_real_face_vertex(
8632 1, f_or[0], f_fl[0], f_ro[0])),
8633 hex->face(0)->isotropic_child_index(
8634 GeometryInfo<dim>::standard_to_real_face_vertex(
8635 2, f_or[0], f_fl[0], f_ro[0])),
8636 hex->face(0)->isotropic_child_index(
8637 GeometryInfo<dim>::standard_to_real_face_vertex(
8638 3, f_or[0], f_fl[0], f_ro[0])),
8639
8640 hex->face(1)->isotropic_child_index(
8641 GeometryInfo<dim>::standard_to_real_face_vertex(
8642 0, f_or[1], f_fl[1], f_ro[1])), // 16
8643 hex->face(1)->isotropic_child_index(
8644 GeometryInfo<dim>::standard_to_real_face_vertex(
8645 1, f_or[1], f_fl[1], f_ro[1])),
8646 hex->face(1)->isotropic_child_index(
8647 GeometryInfo<dim>::standard_to_real_face_vertex(
8648 2, f_or[1], f_fl[1], f_ro[1])),
8649 hex->face(1)->isotropic_child_index(
8650 GeometryInfo<dim>::standard_to_real_face_vertex(
8651 3, f_or[1], f_fl[1], f_ro[1])),
8652
8653 hex->face(2)->isotropic_child_index(
8654 GeometryInfo<dim>::standard_to_real_face_vertex(
8655 0, f_or[2], f_fl[2], f_ro[2])), // 20
8656 hex->face(2)->isotropic_child_index(
8657 GeometryInfo<dim>::standard_to_real_face_vertex(
8658 1, f_or[2], f_fl[2], f_ro[2])),
8659 hex->face(2)->isotropic_child_index(
8660 GeometryInfo<dim>::standard_to_real_face_vertex(
8661 2, f_or[2], f_fl[2], f_ro[2])),
8662 hex->face(2)->isotropic_child_index(
8663 GeometryInfo<dim>::standard_to_real_face_vertex(
8664 3, f_or[2], f_fl[2], f_ro[2])),
8665
8666 hex->face(3)->isotropic_child_index(
8667 GeometryInfo<dim>::standard_to_real_face_vertex(
8668 0, f_or[3], f_fl[3], f_ro[3])), // 24
8669 hex->face(3)->isotropic_child_index(
8670 GeometryInfo<dim>::standard_to_real_face_vertex(
8671 1, f_or[3], f_fl[3], f_ro[3])),
8672 hex->face(3)->isotropic_child_index(
8673 GeometryInfo<dim>::standard_to_real_face_vertex(
8674 2, f_or[3], f_fl[3], f_ro[3])),
8675 hex->face(3)->isotropic_child_index(
8676 GeometryInfo<dim>::standard_to_real_face_vertex(
8677 3, f_or[3], f_fl[3], f_ro[3])),
8678
8679 hex->face(4)->isotropic_child_index(
8680 GeometryInfo<dim>::standard_to_real_face_vertex(
8681 0, f_or[4], f_fl[4], f_ro[4])), // 28
8682 hex->face(4)->isotropic_child_index(
8683 GeometryInfo<dim>::standard_to_real_face_vertex(
8684 1, f_or[4], f_fl[4], f_ro[4])),
8685 hex->face(4)->isotropic_child_index(
8686 GeometryInfo<dim>::standard_to_real_face_vertex(
8687 2, f_or[4], f_fl[4], f_ro[4])),
8688 hex->face(4)->isotropic_child_index(
8689 GeometryInfo<dim>::standard_to_real_face_vertex(
8690 3, f_or[4], f_fl[4], f_ro[4])),
8691
8692 hex->face(5)->isotropic_child_index(
8693 GeometryInfo<dim>::standard_to_real_face_vertex(
8694 0, f_or[5], f_fl[5], f_ro[5])), // 32
8695 hex->face(5)->isotropic_child_index(
8696 GeometryInfo<dim>::standard_to_real_face_vertex(
8697 1, f_or[5], f_fl[5], f_ro[5])),
8698 hex->face(5)->isotropic_child_index(
8699 GeometryInfo<dim>::standard_to_real_face_vertex(
8700 2, f_or[5], f_fl[5], f_ro[5])),
8701 hex->face(5)->isotropic_child_index(
8702 GeometryInfo<dim>::standard_to_real_face_vertex(
8703 3, f_or[5], f_fl[5], f_ro[5]))};
8704
8705 // bottom children
8706 new_hexes[0]->set_bounding_object_indices(
8707 {quad_indices[12],
8708 quad_indices[0],
8709 quad_indices[20],
8710 quad_indices[4],
8711 quad_indices[28],
8712 quad_indices[8]});
8713 new_hexes[1]->set_bounding_object_indices(
8714 {quad_indices[0],
8715 quad_indices[16],
8716 quad_indices[22],
8717 quad_indices[6],
8718 quad_indices[29],
8719 quad_indices[9]});
8720 new_hexes[2]->set_bounding_object_indices(
8721 {quad_indices[13],
8722 quad_indices[1],
8723 quad_indices[4],
8724 quad_indices[24],
8725 quad_indices[30],
8726 quad_indices[10]});
8727 new_hexes[3]->set_bounding_object_indices(
8728 {quad_indices[1],
8729 quad_indices[17],
8730 quad_indices[6],
8731 quad_indices[26],
8732 quad_indices[31],
8733 quad_indices[11]});
8734
8735 // top children
8736 new_hexes[4]->set_bounding_object_indices(
8737 {quad_indices[14],
8738 quad_indices[2],
8739 quad_indices[21],
8740 quad_indices[5],
8741 quad_indices[8],
8742 quad_indices[32]});
8743 new_hexes[5]->set_bounding_object_indices(
8744 {quad_indices[2],
8745 quad_indices[18],
8746 quad_indices[23],
8747 quad_indices[7],
8748 quad_indices[9],
8749 quad_indices[33]});
8750 new_hexes[6]->set_bounding_object_indices(
8751 {quad_indices[15],
8752 quad_indices[3],
8753 quad_indices[5],
8754 quad_indices[25],
8755 quad_indices[10],
8756 quad_indices[34]});
8757 new_hexes[7]->set_bounding_object_indices(
8758 {quad_indices[3],
8759 quad_indices[19],
8760 quad_indices[7],
8761 quad_indices[27],
8762 quad_indices[11],
8763 quad_indices[35]});
8764 break;
8765 }
8766 default:
8767 // all refinement cases have been treated, there
8768 // only remains
8769 // RefinementCase<dim>::no_refinement as
8770 // untreated enumeration value. However, in that
8771 // case we should have aborted much
8772 // earlier. thus we should never get here
8773 Assert(false, ExcInternalError());
8774 break;
8775 } // switch (ref_case)
8776
8777 // and set face orientation flags. note that new
8778 // faces in the interior of the mother cell always
8779 // have a correctly oriented face, but the ones on
8780 // the outer faces will inherit this flag
8781 //
8782 // the flag have been set to true for all faces
8783 // initially, now go the other way round and reset
8784 // faces that are at the boundary of the mother cube
8785 //
8786 // the same is true for the face_flip and
8787 // face_rotation flags. however, the latter two are
8788 // set to false by default as this is the standard
8789 // value
8790
8791 // loop over all faces and all (relevant) subfaces
8792 // of that in order to set the correct values for
8793 // face_orientation, face_flip and face_rotation,
8794 // which are inherited from the corresponding face
8795 // of the mother cube
8796 for (const unsigned int f : GeometryInfo<dim>::face_indices())
8797 for (unsigned int s = 0;
8798 s < std::max(GeometryInfo<dim - 1>::n_children(
8799 GeometryInfo<dim>::face_refinement_case(
8800 ref_case, f)),
8801 1U);
8802 ++s)
8803 {
8804 const unsigned int current_child =
8805 GeometryInfo<dim>::child_cell_on_face(
8806 ref_case,
8807 f,
8808 s,
8809 f_or[f],
8810 f_fl[f],
8811 f_ro[f],
8812 GeometryInfo<dim>::face_refinement_case(
8813 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
8814 new_hexes[current_child]->set_face_orientation(f,
8815 f_or[f]);
8816 new_hexes[current_child]->set_face_flip(f, f_fl[f]);
8817 new_hexes[current_child]->set_face_rotation(f, f_ro[f]);
8818 }
8819
8820 // now see if we have created cells that are
8821 // distorted and if so add them to our list
8822 if (check_for_distorted_cells &&
8823 has_distorted_children(
8824 hex,
8825 std::integral_constant<int, dim>(),
8826 std::integral_constant<int, spacedim>()))
8827 cells_with_distorted_children.distorted_cells.push_back(
8828 hex);
8829
8830 // note that the refinement flag was already cleared
8831 // at the beginning of this loop
8832
8833 // inform all listeners that cell refinement is done
8834 triangulation.signals.post_refinement_on_cell(hex);
8835 }
8836 }
8837
8838 // clear user data on quads. we used some of this data to
8839 // indicate anisotropic refinemnt cases on faces. all data
8840 // should be cleared by now, but the information whether we
8841 // used indices or pointers is still present. reset it now to
8842 // enable the user to use whichever they like later on.
8843 triangulation.faces->quads.clear_user_data();
8844
8845 // return the list with distorted children
8846 return cells_with_distorted_children;
8847 }
8848
8849
8850 /**
8851 * At the boundary of the domain, the new point on the face may
8852 * be far inside the current cell, if the boundary has a strong
8853 * curvature. If we allow anisotropic refinement here, the
8854 * resulting cell may be strongly distorted. To prevent this,
8855 * this function flags such cells for isotropic refinement. It
8856 * is called automatically from
8857 * prepare_coarsening_and_refinement().
8858 *
8859 * This function does nothing in 1d (therefore the
8860 * specialization).
8861 */
8862 template <int spacedim>
8863 static void
8864 prevent_distorted_boundary_cells(const Triangulation<1, spacedim> &);
8865
8866
8867 template <int dim, int spacedim>
8868 static void
prevent_distorted_boundary_cellsinternal::TriangulationImplementation::Implementation8869 prevent_distorted_boundary_cells(
8870 Triangulation<dim, spacedim> &triangulation)
8871 {
8872 // If the codimension is one, we cannot perform this check
8873 // yet.
8874 if (spacedim > dim)
8875 return;
8876
8877 for (const auto &cell : triangulation.cell_iterators())
8878 if (cell->at_boundary() && cell->refine_flag_set() &&
8879 cell->refine_flag_set() !=
8880 RefinementCase<dim>::isotropic_refinement)
8881 {
8882 // The cell is at the boundary and it is flagged for
8883 // anisotropic refinement. Therefore, we have a closer
8884 // look
8885 const RefinementCase<dim> ref_case = cell->refine_flag_set();
8886 for (const unsigned int face_no :
8887 GeometryInfo<dim>::face_indices())
8888 if (cell->face(face_no)->at_boundary())
8889 {
8890 // this is the critical face at the boundary.
8891 if (GeometryInfo<dim>::face_refinement_case(ref_case,
8892 face_no) !=
8893 RefinementCase<dim - 1>::isotropic_refinement)
8894 {
8895 // up to now, we do not want to refine this
8896 // cell along the face under consideration
8897 // here.
8898 const typename Triangulation<dim,
8899 spacedim>::face_iterator
8900 face = cell->face(face_no);
8901 // the new point on the boundary would be this
8902 // one.
8903 const Point<spacedim> new_bound = face->center(true);
8904 // to check it, transform to the unit cell
8905 // with Q1Mapping
8906 const Point<dim> new_unit =
8907 StaticMappingQ1<dim, spacedim>::mapping
8908 .transform_real_to_unit_cell(cell, new_bound);
8909
8910 // Now, we have to calculate the distance from
8911 // the face in the unit cell.
8912
8913 // take the correct coordinate direction (0
8914 // for faces 0 and 1, 1 for faces 2 and 3, 2
8915 // for faces 4 and 5) and subtract the correct
8916 // boundary value of the face (0 for faces 0,
8917 // 2, and 4; 1 for faces 1, 3 and 5)
8918 const double dist =
8919 std::fabs(new_unit[face_no / 2] - face_no % 2);
8920
8921 // compare this with the empirical value
8922 // allowed. if it is too big, flag the face
8923 // for isotropic refinement
8924 const double allowed = 0.25;
8925
8926 if (dist > allowed)
8927 cell->flag_for_face_refinement(face_no);
8928 } // if flagged for anistropic refinement
8929 } // if (cell->face(face)->at_boundary())
8930 } // for all cells
8931 }
8932
8933
8934 /**
8935 * Some dimension dependent stuff for mesh smoothing.
8936 *
8937 * At present, this function does nothing in 1d and 2D, but
8938 * makes sure no two cells with a level difference greater than
8939 * one share one line in 3D. This is a requirement needed for
8940 * the interpolation of hanging nodes, since otherwise to steps
8941 * of interpolation would be necessary. This would make the
8942 * processes implemented in the @p AffineConstraints class much
8943 * more complex, since these two steps of interpolation do not
8944 * commute.
8945 */
8946 template <int dim, int spacedim>
8947 static void
prepare_refinement_dim_dependentinternal::TriangulationImplementation::Implementation8948 prepare_refinement_dim_dependent(const Triangulation<dim, spacedim> &)
8949 {
8950 Assert(dim < 3,
8951 ExcMessage("Wrong function called -- there should "
8952 "be a specialization."));
8953 }
8954
8955
8956 template <int spacedim>
prepare_refinement_dim_dependentinternal::TriangulationImplementation::Implementation8957 static void prepare_refinement_dim_dependent(
8958 Triangulation<3, spacedim> &triangulation)
8959 {
8960 const unsigned int dim = 3;
8961
8962 // first clear flags on lines, since we need them to determine
8963 // which lines will be refined
8964 triangulation.clear_user_flags_line();
8965
8966 // also clear flags on hexes, since we need them to mark those
8967 // cells which are to be coarsened
8968 triangulation.clear_user_flags_hex();
8969
8970 // variable to store whether the mesh was changed in the
8971 // present loop and in the whole process
8972 bool mesh_changed = false;
8973
8974 do
8975 {
8976 mesh_changed = false;
8977
8978 // for this following, we need to know which cells are
8979 // going to be coarsened, if we had to make a
8980 // decision. the following function sets these flags:
8981 triangulation.fix_coarsen_flags();
8982
8983
8984 // flag those lines that are refined and will not be
8985 // coarsened and those that will be refined
8986 for (const auto &cell : triangulation.cell_iterators())
8987 if (cell->refine_flag_set())
8988 {
8989 for (unsigned int line = 0;
8990 line < GeometryInfo<dim>::lines_per_cell;
8991 ++line)
8992 if (GeometryInfo<dim>::line_refinement_case(
8993 cell->refine_flag_set(), line) ==
8994 RefinementCase<1>::cut_x)
8995 // flag a line, that will be
8996 // refined
8997 cell->line(line)->set_user_flag();
8998 }
8999 else if (cell->has_children() &&
9000 !cell->child(0)->coarsen_flag_set())
9001 {
9002 for (unsigned int line = 0;
9003 line < GeometryInfo<dim>::lines_per_cell;
9004 ++line)
9005 if (GeometryInfo<dim>::line_refinement_case(
9006 cell->refinement_case(), line) ==
9007 RefinementCase<1>::cut_x)
9008 // flag a line, that is refined
9009 // and will stay so
9010 cell->line(line)->set_user_flag();
9011 }
9012 else if (cell->has_children() &&
9013 cell->child(0)->coarsen_flag_set())
9014 cell->set_user_flag();
9015
9016
9017 // now check whether there are cells with lines that are
9018 // more than once refined or that will be more than once
9019 // refined. The first thing should never be the case, in
9020 // the second case we flag the cell for refinement
9021 for (typename Triangulation<dim, spacedim>::active_cell_iterator
9022 cell = triangulation.last_active();
9023 cell != triangulation.end();
9024 --cell)
9025 for (unsigned int line = 0;
9026 line < GeometryInfo<dim>::lines_per_cell;
9027 ++line)
9028 {
9029 if (cell->line(line)->has_children())
9030 {
9031 // if this line is refined, its children should
9032 // not have further children
9033 //
9034 // however, if any of the children is flagged
9035 // for further refinement, we need to refine
9036 // this cell also (at least, if the cell is not
9037 // already flagged)
9038 bool offending_line_found = false;
9039
9040 for (unsigned int c = 0; c < 2; ++c)
9041 {
9042 Assert(cell->line(line)->child(c)->has_children() ==
9043 false,
9044 ExcInternalError());
9045
9046 if (cell->line(line)->child(c)->user_flag_set() &&
9047 (GeometryInfo<dim>::line_refinement_case(
9048 cell->refine_flag_set(), line) ==
9049 RefinementCase<1>::no_refinement))
9050 {
9051 // tag this cell for refinement
9052 cell->clear_coarsen_flag();
9053 // if anisotropic coarsening is allowed:
9054 // extend the refine_flag in the needed
9055 // direction, else set refine_flag
9056 // (isotropic)
9057 if (triangulation.smooth_grid &
9058 Triangulation<dim, spacedim>::
9059 allow_anisotropic_smoothing)
9060 cell->flag_for_line_refinement(line);
9061 else
9062 cell->set_refine_flag();
9063
9064 for (unsigned int l = 0;
9065 l < GeometryInfo<dim>::lines_per_cell;
9066 ++l)
9067 if (GeometryInfo<dim>::line_refinement_case(
9068 cell->refine_flag_set(), line) ==
9069 RefinementCase<1>::cut_x)
9070 // flag a line, that will be refined
9071 cell->line(l)->set_user_flag();
9072
9073 // note that we have changed the grid
9074 offending_line_found = true;
9075
9076 // it may save us several loop
9077 // iterations if we flag all lines of
9078 // this cell now (and not at the outset
9079 // of the next iteration) for refinement
9080 for (unsigned int l = 0;
9081 l < GeometryInfo<dim>::lines_per_cell;
9082 ++l)
9083 if (!cell->line(l)->has_children() &&
9084 (GeometryInfo<dim>::line_refinement_case(
9085 cell->refine_flag_set(), l) !=
9086 RefinementCase<1>::no_refinement))
9087 cell->line(l)->set_user_flag();
9088
9089 break;
9090 }
9091 }
9092
9093 if (offending_line_found)
9094 {
9095 mesh_changed = true;
9096 break;
9097 }
9098 }
9099 }
9100
9101
9102 // there is another thing here: if any of the lines will
9103 // be refined, then we may not coarsen the present cell
9104 // similarly, if any of the lines *is* already refined, we
9105 // may not coarsen the current cell. however, there's a
9106 // catch: if the line is refined, but the cell behind it
9107 // is going to be coarsened, then the situation
9108 // changes. if we forget this second condition, the
9109 // refine_and_coarsen_3d test will start to fail. note
9110 // that to know which cells are going to be coarsened, the
9111 // call for fix_coarsen_flags above is necessary
9112 for (typename Triangulation<dim, spacedim>::cell_iterator cell =
9113 triangulation.last();
9114 cell != triangulation.end();
9115 --cell)
9116 {
9117 if (cell->user_flag_set())
9118 for (unsigned int line = 0;
9119 line < GeometryInfo<dim>::lines_per_cell;
9120 ++line)
9121 if (cell->line(line)->has_children() &&
9122 (cell->line(line)->child(0)->user_flag_set() ||
9123 cell->line(line)->child(1)->user_flag_set()))
9124 {
9125 for (unsigned int c = 0; c < cell->n_children(); ++c)
9126 cell->child(c)->clear_coarsen_flag();
9127 cell->clear_user_flag();
9128 for (unsigned int l = 0;
9129 l < GeometryInfo<dim>::lines_per_cell;
9130 ++l)
9131 if (GeometryInfo<dim>::line_refinement_case(
9132 cell->refinement_case(), l) ==
9133 RefinementCase<1>::cut_x)
9134 // flag a line, that is refined
9135 // and will stay so
9136 cell->line(l)->set_user_flag();
9137 mesh_changed = true;
9138 break;
9139 }
9140 }
9141 }
9142 while (mesh_changed == true);
9143 }
9144
9145
9146
9147 /**
9148 * Helper function for @p fix_coarsen_flags. Return whether
9149 * coarsening of this cell is allowed. Coarsening can be
9150 * forbidden if the neighboring cells are or will be refined
9151 * twice along the common face.
9152 */
9153 template <int dim, int spacedim>
9154 static bool
coarsening_allowedinternal::TriangulationImplementation::Implementation9155 coarsening_allowed(
9156 const typename Triangulation<dim, spacedim>::cell_iterator &cell)
9157 {
9158 // in 1d, coarsening is always allowed since we don't enforce
9159 // the 2:1 constraint there
9160 if (dim == 1)
9161 return true;
9162
9163 const RefinementCase<dim> ref_case = cell->refinement_case();
9164 for (unsigned int n : GeometryInfo<dim>::face_indices())
9165 {
9166 // if the cell is not refined along that face, coarsening
9167 // will not change anything, so do nothing. the same
9168 // applies, if the face is at the boandary
9169 const RefinementCase<dim - 1> face_ref_case =
9170 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
9171 n);
9172
9173 const unsigned int n_subfaces =
9174 GeometryInfo<dim - 1>::n_children(face_ref_case);
9175
9176 if (n_subfaces == 0 || cell->at_boundary(n))
9177 continue;
9178 for (unsigned int c = 0; c < n_subfaces; ++c)
9179 {
9180 const typename Triangulation<dim, spacedim>::cell_iterator
9181 child = cell->child(
9182 GeometryInfo<dim>::child_cell_on_face(ref_case, n, c));
9183
9184 const typename Triangulation<dim, spacedim>::cell_iterator
9185 child_neighbor = child->neighbor(n);
9186 if (!child->neighbor_is_coarser(n))
9187 // in 2d, if the child's neighbor is coarser, then
9188 // it has no children. however, in 3d it might be
9189 // otherwise. consider for example, that our face
9190 // might be refined with cut_x, but the neighbor is
9191 // refined with cut_xy at that face. then the
9192 // neighbor pointers of the children of our cell
9193 // will point to the common neighbor cell, not to
9194 // its children. what we really want to know in the
9195 // following is, whether the neighbor cell is
9196 // refined twice with reference to our cell. that
9197 // only has to be asked, if the child's neighbor is
9198 // not a coarser one.
9199 if ((child_neighbor->has_children() &&
9200 !child_neighbor->user_flag_set()) ||
9201 // neighbor has children, which are further
9202 // refined along the face, otherwise something
9203 // went wrong in the construction of neighbor
9204 // pointers. then only allow coarsening if this
9205 // neighbor will be coarsened as well
9206 // (user_pointer is set). the same applies, if
9207 // the neighbors children are not refined but
9208 // will be after refinement
9209 child_neighbor->refine_flag_set())
9210 return false;
9211 }
9212 }
9213 return true;
9214 }
9215 };
9216
9217
9218
9219 template <int dim, int spacedim>
9220 const Manifold<dim, spacedim> &
get_default_flat_manifold()9221 get_default_flat_manifold()
9222 {
9223 static const FlatManifold<dim, spacedim> flat_manifold;
9224 return flat_manifold;
9225 }
9226 } // namespace TriangulationImplementation
9227 } // namespace internal
9228
9229
9230
9231 template <int dim, int spacedim>
9232 const unsigned int Triangulation<dim, spacedim>::dimension;
9233
9234
9235
9236 template <int dim, int spacedim>
Triangulation(const MeshSmoothing smooth_grid,const bool check_for_distorted_cells)9237 Triangulation<dim, spacedim>::Triangulation(
9238 const MeshSmoothing smooth_grid,
9239 const bool check_for_distorted_cells)
9240 : smooth_grid(smooth_grid)
9241 , anisotropic_refinement(false)
9242 , check_for_distorted_cells(check_for_distorted_cells)
9243 {
9244 if (dim == 1)
9245 {
9246 vertex_to_boundary_id_map_1d =
9247 std::make_unique<std::map<unsigned int, types::boundary_id>>();
9248 vertex_to_manifold_id_map_1d =
9249 std::make_unique<std::map<unsigned int, types::manifold_id>>();
9250 }
9251
9252 // connect the any_change signal to the other top level signals
9253 signals.create.connect(signals.any_change);
9254 signals.post_refinement.connect(signals.any_change);
9255 signals.clear.connect(signals.any_change);
9256 signals.mesh_movement.connect(signals.any_change);
9257 }
9258
9259
9260
9261 template <int dim, int spacedim>
Triangulation(Triangulation<dim,spacedim> && tria)9262 Triangulation<dim, spacedim>::Triangulation(
9263 Triangulation<dim, spacedim> &&tria) noexcept
9264 : Subscriptor(std::move(tria))
9265 , smooth_grid(tria.smooth_grid)
9266 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
9267 , periodic_face_map(std::move(tria.periodic_face_map))
9268 , levels(std::move(tria.levels))
9269 , faces(std::move(tria.faces))
9270 , vertices(std::move(tria.vertices))
9271 , vertices_used(std::move(tria.vertices_used))
9272 , manifold(std::move(tria.manifold))
9273 , anisotropic_refinement(tria.anisotropic_refinement)
9274 , check_for_distorted_cells(tria.check_for_distorted_cells)
9275 , number_cache(std::move(tria.number_cache))
9276 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
9277 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
9278 {
9279 tria.number_cache = internal::TriangulationImplementation::NumberCache<dim>();
9280 }
9281
9282
9283 template <int dim, int spacedim>
9284 Triangulation<dim, spacedim> &
9285 Triangulation<dim, spacedim>::
operator =(Triangulation<dim,spacedim> && tria)9286 operator=(Triangulation<dim, spacedim> &&tria) noexcept
9287 {
9288 Subscriptor::operator=(std::move(tria));
9289
9290 smooth_grid = tria.smooth_grid;
9291 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
9292 periodic_face_map = std::move(tria.periodic_face_map);
9293 levels = std::move(tria.levels);
9294 faces = std::move(tria.faces);
9295 vertices = std::move(tria.vertices);
9296 vertices_used = std::move(tria.vertices_used);
9297 manifold = std::move(tria.manifold);
9298 anisotropic_refinement = tria.anisotropic_refinement;
9299 number_cache = tria.number_cache;
9300 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
9301 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
9302
9303 tria.number_cache = internal::TriangulationImplementation::NumberCache<dim>();
9304
9305 return *this;
9306 }
9307
9308
9309
9310 template <int dim, int spacedim>
~Triangulation()9311 Triangulation<dim, spacedim>::~Triangulation()
9312 {
9313 // notify listeners that the triangulation is going down...
9314 try
9315 {
9316 signals.clear();
9317 }
9318 catch (...)
9319 {}
9320
9321 levels.clear();
9322
9323 // the vertex_to_boundary_id_map_1d field should be unused except in
9324 // 1d. double check this here, as destruction is a good place to
9325 // ensure that what we've done over the course of the lifetime of
9326 // this object makes sense
9327 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
9328 ExcInternalError());
9329
9330 // the vertex_to_manifold_id_map_1d field should be also unused
9331 // except in 1d. check this as well
9332 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
9333 ExcInternalError());
9334 }
9335
9336
9337
9338 template <int dim, int spacedim>
9339 void
clear()9340 Triangulation<dim, spacedim>::clear()
9341 {
9342 // notify listeners that the triangulation is going down...
9343 signals.clear();
9344
9345 // ...and then actually clear all content of it
9346 clear_despite_subscriptions();
9347 periodic_face_pairs_level_0.clear();
9348 periodic_face_map.clear();
9349 }
9350
9351
9352
9353 template <int dim, int spacedim>
9354 void
set_mesh_smoothing(const MeshSmoothing mesh_smoothing)9355 Triangulation<dim, spacedim>::set_mesh_smoothing(
9356 const MeshSmoothing mesh_smoothing)
9357 {
9358 Assert(n_levels() == 0,
9359 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
9360 smooth_grid = mesh_smoothing;
9361 }
9362
9363
9364
9365 template <int dim, int spacedim>
9366 const typename Triangulation<dim, spacedim>::MeshSmoothing &
get_mesh_smoothing() const9367 Triangulation<dim, spacedim>::get_mesh_smoothing() const
9368 {
9369 return smooth_grid;
9370 }
9371
9372
9373
9374 template <int dim, int spacedim>
9375 void
set_manifold(const types::manifold_id m_number,const Manifold<dim,spacedim> & manifold_object)9376 Triangulation<dim, spacedim>::set_manifold(
9377 const types::manifold_id m_number,
9378 const Manifold<dim, spacedim> &manifold_object)
9379 {
9380 AssertIndexRange(m_number, numbers::flat_manifold_id);
9381
9382 manifold[m_number] = manifold_object.clone();
9383 }
9384
9385
9386
9387 template <int dim, int spacedim>
9388 void
reset_manifold(const types::manifold_id m_number)9389 Triangulation<dim, spacedim>::reset_manifold(const types::manifold_id m_number)
9390 {
9391 AssertIndexRange(m_number, numbers::flat_manifold_id);
9392
9393 // delete the entry located at number.
9394 manifold.erase(m_number);
9395 }
9396
9397
9398 template <int dim, int spacedim>
9399 void
reset_all_manifolds()9400 Triangulation<dim, spacedim>::reset_all_manifolds()
9401 {
9402 manifold.clear();
9403 }
9404
9405
9406 template <int dim, int spacedim>
9407 void
set_all_manifold_ids(const types::manifold_id m_number)9408 Triangulation<dim, spacedim>::set_all_manifold_ids(
9409 const types::manifold_id m_number)
9410 {
9411 Assert(
9412 n_cells() > 0,
9413 ExcMessage(
9414 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
9415
9416 for (const auto &cell : this->active_cell_iterators())
9417 cell->set_all_manifold_ids(m_number);
9418 }
9419
9420
9421 template <int dim, int spacedim>
9422 void
set_all_manifold_ids_on_boundary(const types::manifold_id m_number)9423 Triangulation<dim, spacedim>::set_all_manifold_ids_on_boundary(
9424 const types::manifold_id m_number)
9425 {
9426 Assert(
9427 n_cells() > 0,
9428 ExcMessage(
9429 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
9430
9431 for (const auto &cell : this->active_cell_iterators())
9432 for (auto f : GeometryInfo<dim>::face_indices())
9433 if (cell->face(f)->at_boundary())
9434 cell->face(f)->set_all_manifold_ids(m_number);
9435 }
9436
9437
9438 template <int dim, int spacedim>
9439 void
set_all_manifold_ids_on_boundary(const types::boundary_id b_id,const types::manifold_id m_number)9440 Triangulation<dim, spacedim>::set_all_manifold_ids_on_boundary(
9441 const types::boundary_id b_id,
9442 const types::manifold_id m_number)
9443 {
9444 Assert(
9445 n_cells() > 0,
9446 ExcMessage(
9447 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
9448
9449 bool boundary_found = false;
9450
9451 for (const auto &cell : this->active_cell_iterators())
9452 {
9453 // loop on faces
9454 for (auto f : GeometryInfo<dim>::face_indices())
9455 if (cell->face(f)->at_boundary() &&
9456 cell->face(f)->boundary_id() == b_id)
9457 {
9458 boundary_found = true;
9459 cell->face(f)->set_manifold_id(m_number);
9460 }
9461
9462 // loop on edges if dim >= 3
9463 if (dim >= 3)
9464 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
9465 if (cell->line(e)->at_boundary() &&
9466 cell->line(e)->boundary_id() == b_id)
9467 {
9468 boundary_found = true;
9469 cell->line(e)->set_manifold_id(m_number);
9470 }
9471 }
9472
9473 (void)boundary_found;
9474 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
9475 }
9476
9477
9478
9479 template <int dim, int spacedim>
9480 const Manifold<dim, spacedim> &
get_manifold(const types::manifold_id m_number) const9481 Triangulation<dim, spacedim>::get_manifold(
9482 const types::manifold_id m_number) const
9483 {
9484 // look, if there is a manifold stored at
9485 // manifold_id number.
9486 const auto it = manifold.find(m_number);
9487
9488 if (it != manifold.end())
9489 {
9490 // if we have found an entry, return it
9491 return *(it->second);
9492 }
9493
9494 // if we have not found an entry connected with number, we return
9495 // the default (flat) manifold
9496 return internal::TriangulationImplementation::
9497 get_default_flat_manifold<dim, spacedim>();
9498 }
9499
9500
9501
9502 template <int dim, int spacedim>
9503 std::vector<types::boundary_id>
get_boundary_ids() const9504 Triangulation<dim, spacedim>::get_boundary_ids() const
9505 {
9506 // in 1d, we store a map of all used boundary indicators. use it for
9507 // our purposes
9508 if (dim == 1)
9509 {
9510 std::vector<types::boundary_id> boundary_ids;
9511 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
9512 vertex_to_boundary_id_map_1d->begin();
9513 p != vertex_to_boundary_id_map_1d->end();
9514 ++p)
9515 boundary_ids.push_back(p->second);
9516
9517 return boundary_ids;
9518 }
9519 else
9520 {
9521 std::set<types::boundary_id> b_ids;
9522 for (auto cell : active_cell_iterators())
9523 if (cell->is_locally_owned())
9524 for (const unsigned int face : GeometryInfo<dim>::face_indices())
9525 if (cell->at_boundary(face))
9526 b_ids.insert(cell->face(face)->boundary_id());
9527 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
9528 return boundary_ids;
9529 }
9530 }
9531
9532
9533
9534 template <int dim, int spacedim>
9535 std::vector<types::manifold_id>
get_manifold_ids() const9536 Triangulation<dim, spacedim>::get_manifold_ids() const
9537 {
9538 std::set<types::manifold_id> m_ids;
9539 for (auto cell : active_cell_iterators())
9540 if (cell->is_locally_owned())
9541 {
9542 m_ids.insert(cell->manifold_id());
9543 if (dim > 1)
9544 for (const unsigned int face : GeometryInfo<dim>::face_indices())
9545 if (cell->at_boundary(face))
9546 m_ids.insert(cell->face(face)->manifold_id());
9547 }
9548 std::vector<types::manifold_id> manifold_indicators(m_ids.begin(),
9549 m_ids.end());
9550 return manifold_indicators;
9551 }
9552
9553 /*-----------------------------------------------------------------*/
9554
9555
9556 template <int dim, int spacedim>
9557 void
copy_triangulation(const Triangulation<dim,spacedim> & other_tria)9558 Triangulation<dim, spacedim>::copy_triangulation(
9559 const Triangulation<dim, spacedim> &other_tria)
9560 {
9561 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
9562 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
9563 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
9564 (dim == 1 || other_tria.faces != nullptr),
9565 ExcMessage(
9566 "When calling Triangulation::copy_triangulation(), "
9567 "the target triangulation must be empty but the source "
9568 "triangulation (the argument to this function) must contain "
9569 "something. Here, it seems like the source does not "
9570 "contain anything at all."));
9571
9572
9573 // copy normal elements
9574 vertices = other_tria.vertices;
9575 vertices_used = other_tria.vertices_used;
9576 anisotropic_refinement = other_tria.anisotropic_refinement;
9577 smooth_grid = other_tria.smooth_grid;
9578
9579 if (dim > 1)
9580 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
9581 *other_tria.faces);
9582
9583 auto bdry_iterator = other_tria.manifold.begin();
9584 for (; bdry_iterator != other_tria.manifold.end(); ++bdry_iterator)
9585 manifold[bdry_iterator->first] = bdry_iterator->second->clone();
9586
9587
9588 levels.reserve(other_tria.levels.size());
9589 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
9590 levels.push_back(
9591 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
9592 *other_tria.levels[level]));
9593
9594 number_cache = other_tria.number_cache;
9595
9596 if (dim == 1)
9597 {
9598 vertex_to_boundary_id_map_1d =
9599 std::make_unique<std::map<unsigned int, types::boundary_id>>(
9600 *other_tria.vertex_to_boundary_id_map_1d);
9601
9602 vertex_to_manifold_id_map_1d =
9603 std::make_unique<std::map<unsigned int, types::manifold_id>>(
9604 *other_tria.vertex_to_manifold_id_map_1d);
9605 }
9606
9607 // inform those who are listening on other_tria of the copy operation
9608 other_tria.signals.copy(*this);
9609 // also inform all listeners of the current triangulation that the
9610 // triangulation has been created
9611 signals.create();
9612
9613 // note that we need not copy the
9614 // subscriptor!
9615 }
9616
9617
9618
9619 template <int dim, int spacedim>
9620 void
create_triangulation_compatibility(const std::vector<Point<spacedim>> & v,const std::vector<CellData<dim>> & cells,const SubCellData & subcelldata)9621 Triangulation<dim, spacedim>::create_triangulation_compatibility(
9622 const std::vector<Point<spacedim>> &v,
9623 const std::vector<CellData<dim>> & cells,
9624 const SubCellData & subcelldata)
9625 {
9626 std::vector<CellData<dim>> reordered_cells(cells); // NOLINT
9627 SubCellData reordered_subcelldata(subcelldata); // NOLINT
9628
9629 // in-place reordering of data
9630 reorder_compatibility(reordered_cells, reordered_subcelldata);
9631
9632 // now create triangulation from
9633 // reordered data
9634 create_triangulation(v, reordered_cells, reordered_subcelldata);
9635 }
9636
9637
9638
9639 template <int dim, int spacedim>
9640 void
create_triangulation(const std::vector<Point<spacedim>> & v,const std::vector<CellData<dim>> & cells,const SubCellData & subcelldata)9641 Triangulation<dim, spacedim>::create_triangulation(
9642 const std::vector<Point<spacedim>> &v,
9643 const std::vector<CellData<dim>> & cells,
9644 const SubCellData & subcelldata)
9645 {
9646 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
9647 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
9648 // check that no forbidden arrays
9649 // are used
9650 Assert(subcelldata.check_consistency(dim), ExcInternalError());
9651
9652 // try to create a triangulation; if this fails, we still want to
9653 // throw an exception but if we just do so we'll get into trouble
9654 // because sometimes other objects are already attached to it:
9655 try
9656 {
9657 #ifndef DEAL_II_WITH_SIMPLEX_SUPPORT
9658 AssertThrow(
9659 std::any_of(cells.begin(),
9660 cells.end(),
9661 [](const auto &cell) {
9662 return cell.vertices.size() !=
9663 GeometryInfo<dim>::vertices_per_cell;
9664 }) == false,
9665 ExcMessage(
9666 "A cell with invalid number of vertices has been provided."));
9667 #endif
9668
9669 internal::TriangulationImplementation::Implementation::
9670 create_triangulation(v, cells, subcelldata, *this);
9671 }
9672 catch (...)
9673 {
9674 clear_despite_subscriptions();
9675 throw;
9676 }
9677
9678 // update our counts of the various elements of a triangulation, and set
9679 // active_cell_indices of all cells
9680 internal::TriangulationImplementation::Implementation::compute_number_cache(
9681 *this, levels.size(), number_cache);
9682 reset_active_cell_indices();
9683
9684 // now verify that there are indeed no distorted cells. as per the
9685 // documentation of this class, we first collect all distorted cells
9686 // and then throw an exception if there are any
9687 if (check_for_distorted_cells)
9688 {
9689 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
9690 // throw the array (and fill the various location fields) if
9691 // there are distorted cells. otherwise, just fall off the end
9692 // of the function
9693 AssertThrow(distorted_cells.distorted_cells.size() == 0, distorted_cells);
9694 }
9695
9696
9697 /*
9698 When the triangulation is a manifold (dim < spacedim), the normal field
9699 provided from the map class depends on the order of the vertices.
9700 It may happen that this normal field is discontinuous.
9701 The following code takes care that this is not the case by setting the
9702 cell direction flag on those cell that produce the wrong orientation.
9703
9704 To determine if 2 neighbours have the same or opposite orientation
9705 we use a table of truth.
9706 Its entries are indexes by the local indices of the common face.
9707 For example if two elements share a face, and this face is
9708 face 0 for element 0 and face 1 for element 1, then
9709 table(0,1) will tell whether the orientation are the same (true) or
9710 opposite (false).
9711
9712 Even though there may be a combinatorial/graph theory argument to get
9713 this table in any dimension, I tested by hand all the different possible
9714 cases in 1D and 2D to generate the table.
9715
9716 Assuming that a surface respects the standard orientation for 2d meshes,
9717 the tables of truth are symmetric and their true values are the following
9718 1D curves: (0,1)
9719 2D surface: (0,1),(0,2),(1,3),(2,3)
9720
9721 We store this data using an n_faces x n_faces full matrix, which is
9722 actually much bigger than the minimal data required, but it makes the code
9723 more readable.
9724
9725 */
9726 if (dim < spacedim)
9727 {
9728 Table<2, bool> correct(GeometryInfo<dim>::faces_per_cell,
9729 GeometryInfo<dim>::faces_per_cell);
9730 switch (dim)
9731 {
9732 case 1:
9733 {
9734 bool values[][2] = {{false, true}, {true, false}};
9735 for (const unsigned int i : GeometryInfo<dim>::face_indices())
9736 for (const unsigned int j : GeometryInfo<dim>::face_indices())
9737 correct(i, j) = (values[i][j]);
9738 break;
9739 }
9740 case 2:
9741 {
9742 bool values[][4] = {{false, true, true, false},
9743 {true, false, false, true},
9744 {true, false, false, true},
9745 {false, true, true, false}};
9746 for (const unsigned int i : GeometryInfo<dim>::face_indices())
9747 for (const unsigned int j : GeometryInfo<dim>::face_indices())
9748 correct(i, j) = (values[i][j]);
9749 break;
9750 }
9751 default:
9752 Assert(false, ExcNotImplemented());
9753 }
9754
9755
9756 std::list<active_cell_iterator> this_round, next_round;
9757 active_cell_iterator neighbor;
9758
9759 this_round.push_back(begin_active());
9760 begin_active()->set_direction_flag(true);
9761 begin_active()->set_user_flag();
9762
9763 while (this_round.size() > 0)
9764 {
9765 for (typename std::list<active_cell_iterator>::iterator cell =
9766 this_round.begin();
9767 cell != this_round.end();
9768 ++cell)
9769 {
9770 for (const unsigned int i : (*cell)->face_indices())
9771 {
9772 if (!((*cell)->face(i)->at_boundary()))
9773 {
9774 neighbor = (*cell)->neighbor(i);
9775
9776 unsigned int cf = (*cell)->face_index(i);
9777 unsigned int j = 0;
9778 while (neighbor->face_index(j) != cf)
9779 {
9780 ++j;
9781 }
9782
9783
9784 // If we already saw this guy, check that everything is
9785 // fine
9786 if (neighbor->user_flag_set())
9787 {
9788 // If we have visited this guy, then the ordering and
9789 // the orientation should agree
9790 Assert(!(correct(i, j) ^
9791 (neighbor->direction_flag() ==
9792 (*cell)->direction_flag())),
9793 ExcNonOrientableTriangulation());
9794 }
9795 else
9796 {
9797 next_round.push_back(neighbor);
9798 neighbor->set_user_flag();
9799 if ((correct(i, j) ^ (neighbor->direction_flag() ==
9800 (*cell)->direction_flag())))
9801 neighbor->set_direction_flag(
9802 !neighbor->direction_flag());
9803 }
9804 }
9805 }
9806 }
9807
9808 // Before we quit let's check
9809 // that if the triangulation
9810 // is disconnected that we
9811 // still get all cells
9812 if (next_round.size() == 0)
9813 for (const auto &cell : this->active_cell_iterators())
9814 if (cell->user_flag_set() == false)
9815 {
9816 next_round.push_back(cell);
9817 cell->set_direction_flag(true);
9818 cell->set_user_flag();
9819 break;
9820 }
9821
9822 this_round = next_round;
9823 next_round.clear();
9824 }
9825 }
9826
9827 // inform all listeners that the triangulation has been created
9828 signals.create();
9829 }
9830
9831
9832
9833 template <int dim, int spacedim>
9834 void
create_triangulation(const TriangulationDescription::Description<dim,spacedim> & construction_data)9835 Triangulation<dim, spacedim>::create_triangulation(
9836 const TriangulationDescription::Description<dim, spacedim> &construction_data)
9837 {
9838 // 1) create coarse grid
9839 create_triangulation(construction_data.coarse_cell_vertices,
9840 construction_data.coarse_cells,
9841 SubCellData());
9842
9843 // create a copy of cell_infos such that we can sort them
9844 auto cell_infos = construction_data.cell_infos;
9845
9846 // sort cell_infos on each level separately
9847 for (auto &cell_info : cell_infos)
9848 std::sort(
9849 cell_info.begin(),
9850 cell_info.end(),
9851 [&](TriangulationDescription::CellData<dim> a,
9852 TriangulationDescription::CellData<dim> b) {
9853 const CellId a_id(a.id);
9854 const CellId b_id(b.id);
9855
9856 const auto a_coarse_cell_index =
9857 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
9858 const auto b_coarse_cell_index =
9859 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
9860
9861 // according to their coarse-cell index and if that is
9862 // same according to their cell id (the result is that
9863 // cells on each level are sorted according to their
9864 // index on that level - what we need in the following
9865 // operations)
9866 if (a_coarse_cell_index != b_coarse_cell_index)
9867 return a_coarse_cell_index < b_coarse_cell_index;
9868 else
9869 return a_id < b_id;
9870 });
9871
9872 // 2) create all levels via a sequence of refinements
9873 for (unsigned int level = 0; level < cell_infos.size(); ++level)
9874 {
9875 // a) set manifold ids here (because new vertices have to be
9876 // positioned correctly during each refinement step)
9877 {
9878 auto cell = this->begin(level);
9879 auto cell_info = cell_infos[level].begin();
9880 for (; cell_info != cell_infos[level].end(); ++cell_info)
9881 {
9882 while (cell_info->id != cell->id().template to_binary<dim>())
9883 ++cell;
9884 if (dim == 3)
9885 for (const auto quad : cell->face_indices())
9886 cell->quad(quad)->set_manifold_id(
9887 cell_info->manifold_quad_ids[quad]);
9888
9889 if (dim >= 2)
9890 for (const auto line : cell->line_indices())
9891 cell->line(line)->set_manifold_id(
9892 cell_info->manifold_line_ids[line]);
9893
9894 cell->set_manifold_id(cell_info->manifold_id);
9895 }
9896 }
9897
9898 // b) perform refinement on all levels but on the finest
9899 if (level + 1 != cell_infos.size())
9900 {
9901 // find cells that should have children and mark them for
9902 // refinement
9903 auto coarse_cell = this->begin(level);
9904 auto fine_cell_info = cell_infos[level + 1].begin();
9905
9906 // loop over all cells on the next level
9907 for (; fine_cell_info != cell_infos[level + 1].end();
9908 ++fine_cell_info)
9909 {
9910 // find the parent of that cell
9911 while (
9912 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
9913 ++coarse_cell;
9914
9915 // set parent for refinement
9916 coarse_cell->set_refine_flag();
9917 }
9918
9919 // execute refinement
9920 dealii::Triangulation<dim,
9921 spacedim>::execute_coarsening_and_refinement();
9922 }
9923 }
9924
9925 // 3) set boundary ids
9926 for (unsigned int level = 0; level < cell_infos.size(); ++level)
9927 {
9928 auto cell = this->begin(level);
9929 auto cell_info = cell_infos[level].begin();
9930 for (; cell_info != cell_infos[level].end(); ++cell_info)
9931 {
9932 // find cell that has the correct cell
9933 while (cell_info->id != cell->id().template to_binary<dim>())
9934 ++cell;
9935
9936 // boundary ids
9937 for (auto pair : cell_info->boundary_ids)
9938 {
9939 Assert(cell->at_boundary(pair.first),
9940 ExcMessage("Cell face is not on the boundary!"));
9941 cell->face(pair.first)->set_boundary_id(pair.second);
9942 }
9943 }
9944 }
9945 }
9946
9947
9948 template <int dim, int spacedim>
9949 void
flip_all_direction_flags()9950 Triangulation<dim, spacedim>::flip_all_direction_flags()
9951 {
9952 AssertThrow(dim + 1 == spacedim,
9953 ExcMessage("Only works for dim == spacedim-1"));
9954 for (const auto &cell : this->active_cell_iterators())
9955 cell->set_direction_flag(!cell->direction_flag());
9956 }
9957
9958
9959
9960 template <int dim, int spacedim>
9961 void
set_all_refine_flags()9962 Triangulation<dim, spacedim>::set_all_refine_flags()
9963 {
9964 Assert(n_cells() > 0,
9965 ExcMessage("Error: An empty Triangulation can not be refined."));
9966
9967 for (const auto &cell : this->active_cell_iterators())
9968 {
9969 cell->clear_coarsen_flag();
9970 cell->set_refine_flag();
9971 }
9972 }
9973
9974
9975
9976 template <int dim, int spacedim>
9977 void
refine_global(const unsigned int times)9978 Triangulation<dim, spacedim>::refine_global(const unsigned int times)
9979 {
9980 for (unsigned int i = 0; i < times; ++i)
9981 {
9982 set_all_refine_flags();
9983 execute_coarsening_and_refinement();
9984 }
9985 }
9986
9987
9988
9989 /*-------------------- refine/coarsen flags -------------------------*/
9990
9991
9992
9993 template <int dim, int spacedim>
9994 void
save_refine_flags(std::vector<bool> & v) const9995 Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
9996 {
9997 v.resize(dim * n_active_cells(), false);
9998 std::vector<bool>::iterator i = v.begin();
9999
10000 for (const auto &cell : this->active_cell_iterators())
10001 for (unsigned int j = 0; j < dim; ++j, ++i)
10002 if (cell->refine_flag_set() & (1 << j))
10003 *i = true;
10004
10005 Assert(i == v.end(), ExcInternalError());
10006 }
10007
10008
10009
10010 template <int dim, int spacedim>
10011 void
save_refine_flags(std::ostream & out) const10012 Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
10013 {
10014 std::vector<bool> v;
10015 save_refine_flags(v);
10016 write_bool_vector(mn_tria_refine_flags_begin,
10017 v,
10018 mn_tria_refine_flags_end,
10019 out);
10020 }
10021
10022
10023
10024 template <int dim, int spacedim>
10025 void
load_refine_flags(std::istream & in)10026 Triangulation<dim, spacedim>::load_refine_flags(std::istream &in)
10027 {
10028 std::vector<bool> v;
10029 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
10030 load_refine_flags(v);
10031 }
10032
10033
10034
10035 template <int dim, int spacedim>
10036 void
load_refine_flags(const std::vector<bool> & v)10037 Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
10038 {
10039 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
10040
10041 std::vector<bool>::const_iterator i = v.begin();
10042 for (const auto &cell : this->active_cell_iterators())
10043 {
10044 unsigned int ref_case = 0;
10045
10046 for (unsigned int j = 0; j < dim; ++j, ++i)
10047 if (*i == true)
10048 ref_case += 1 << j;
10049 Assert(ref_case < RefinementCase<dim>::isotropic_refinement + 1,
10050 ExcGridReadError());
10051 if (ref_case > 0)
10052 cell->set_refine_flag(RefinementCase<dim>(ref_case));
10053 else
10054 cell->clear_refine_flag();
10055 }
10056
10057 Assert(i == v.end(), ExcInternalError());
10058 }
10059
10060
10061
10062 template <int dim, int spacedim>
10063 void
save_coarsen_flags(std::vector<bool> & v) const10064 Triangulation<dim, spacedim>::save_coarsen_flags(std::vector<bool> &v) const
10065 {
10066 v.resize(n_active_cells(), false);
10067 std::vector<bool>::iterator i = v.begin();
10068 for (const auto &cell : this->active_cell_iterators())
10069 {
10070 *i = cell->coarsen_flag_set();
10071 ++i;
10072 }
10073
10074 Assert(i == v.end(), ExcInternalError());
10075 }
10076
10077
10078
10079 template <int dim, int spacedim>
10080 void
save_coarsen_flags(std::ostream & out) const10081 Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
10082 {
10083 std::vector<bool> v;
10084 save_coarsen_flags(v);
10085 write_bool_vector(mn_tria_coarsen_flags_begin,
10086 v,
10087 mn_tria_coarsen_flags_end,
10088 out);
10089 }
10090
10091
10092
10093 template <int dim, int spacedim>
10094 void
load_coarsen_flags(std::istream & in)10095 Triangulation<dim, spacedim>::load_coarsen_flags(std::istream &in)
10096 {
10097 std::vector<bool> v;
10098 read_bool_vector(mn_tria_coarsen_flags_begin,
10099 v,
10100 mn_tria_coarsen_flags_end,
10101 in);
10102 load_coarsen_flags(v);
10103 }
10104
10105
10106
10107 template <int dim, int spacedim>
10108 void
load_coarsen_flags(const std::vector<bool> & v)10109 Triangulation<dim, spacedim>::load_coarsen_flags(const std::vector<bool> &v)
10110 {
10111 Assert(v.size() == n_active_cells(), ExcGridReadError());
10112
10113 std::vector<bool>::const_iterator i = v.begin();
10114 for (const auto &cell : this->active_cell_iterators())
10115 {
10116 if (*i == true)
10117 cell->set_coarsen_flag();
10118 else
10119 cell->clear_coarsen_flag();
10120 ++i;
10121 }
10122
10123 Assert(i == v.end(), ExcInternalError());
10124 }
10125
10126
10127 template <int dim, int spacedim>
10128 bool
get_anisotropic_refinement_flag() const10129 Triangulation<dim, spacedim>::get_anisotropic_refinement_flag() const
10130 {
10131 return anisotropic_refinement;
10132 }
10133
10134
10135
10136 /*-------------------- user data/flags -------------------------*/
10137
10138
10139 namespace
10140 {
10141 // clear user data of cells
10142 void
clear_user_data(std::vector<std::unique_ptr<internal::TriangulationImplementation::TriaLevel>> & levels)10143 clear_user_data(std::vector<std::unique_ptr<
10144 internal::TriangulationImplementation::TriaLevel>> &levels)
10145 {
10146 for (auto &level : levels)
10147 level->cells.clear_user_data();
10148 }
10149
10150
10151 // clear user data of faces
10152 void
clear_user_data(internal::TriangulationImplementation::TriaFaces * faces)10153 clear_user_data(internal::TriangulationImplementation::TriaFaces *faces)
10154 {
10155 if (faces->dim == 2)
10156 {
10157 faces->lines.clear_user_data();
10158 }
10159
10160
10161 if (faces->dim == 3)
10162 {
10163 faces->lines.clear_user_data();
10164 faces->quads.clear_user_data();
10165 }
10166 }
10167 } // namespace
10168
10169
10170 template <int dim, int spacedim>
10171 void
clear_user_data()10172 Triangulation<dim, spacedim>::clear_user_data()
10173 {
10174 // let functions in anonymous namespace do their work
10175 dealii::clear_user_data(levels);
10176 dealii::clear_user_data(faces.get());
10177 }
10178
10179
10180
10181 namespace
10182 {
10183 void
clear_user_flags_line(unsigned int dim,std::vector<std::unique_ptr<internal::TriangulationImplementation::TriaLevel>> & levels,internal::TriangulationImplementation::TriaFaces * faces)10184 clear_user_flags_line(
10185 unsigned int dim,
10186 std::vector<
10187 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
10188 & levels,
10189 internal::TriangulationImplementation::TriaFaces *faces)
10190 {
10191 if (dim == 1)
10192 {
10193 for (const auto &level : levels)
10194 level->cells.clear_user_flags();
10195 }
10196 else if (dim == 2 || dim == 3)
10197 {
10198 faces->lines.clear_user_flags();
10199 }
10200 else
10201 {
10202 Assert(false, ExcNotImplemented())
10203 }
10204 }
10205 } // namespace
10206
10207
10208 template <int dim, int spacedim>
10209 void
clear_user_flags_line()10210 Triangulation<dim, spacedim>::clear_user_flags_line()
10211 {
10212 dealii::clear_user_flags_line(dim, levels, faces.get());
10213 }
10214
10215
10216
10217 namespace
10218 {
10219 void
clear_user_flags_quad(unsigned int dim,std::vector<std::unique_ptr<internal::TriangulationImplementation::TriaLevel>> & levels,internal::TriangulationImplementation::TriaFaces * faces)10220 clear_user_flags_quad(
10221 unsigned int dim,
10222 std::vector<
10223 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
10224 & levels,
10225 internal::TriangulationImplementation::TriaFaces *faces)
10226 {
10227 if (dim == 1)
10228 {
10229 // nothing to do in 1d
10230 }
10231 else if (dim == 2)
10232 {
10233 for (const auto &level : levels)
10234 level->cells.clear_user_flags();
10235 }
10236 else if (dim == 3)
10237 {
10238 faces->quads.clear_user_flags();
10239 }
10240 else
10241 {
10242 Assert(false, ExcNotImplemented())
10243 }
10244 }
10245 } // namespace
10246
10247
10248 template <int dim, int spacedim>
10249 void
clear_user_flags_quad()10250 Triangulation<dim, spacedim>::clear_user_flags_quad()
10251 {
10252 dealii::clear_user_flags_quad(dim, levels, faces.get());
10253 }
10254
10255
10256
10257 namespace
10258 {
10259 void
clear_user_flags_hex(unsigned int dim,std::vector<std::unique_ptr<internal::TriangulationImplementation::TriaLevel>> & levels,internal::TriangulationImplementation::TriaFaces *)10260 clear_user_flags_hex(
10261 unsigned int dim,
10262 std::vector<
10263 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
10264 &levels,
10265 internal::TriangulationImplementation::TriaFaces *)
10266 {
10267 if (dim == 1)
10268 {
10269 // nothing to do in 1d
10270 }
10271 else if (dim == 2)
10272 {
10273 // nothing to do in 2d
10274 }
10275 else if (dim == 3)
10276 {
10277 for (const auto &level : levels)
10278 level->cells.clear_user_flags();
10279 }
10280 else
10281 {
10282 Assert(false, ExcNotImplemented())
10283 }
10284 }
10285 } // namespace
10286
10287
10288 template <int dim, int spacedim>
10289 void
clear_user_flags_hex()10290 Triangulation<dim, spacedim>::clear_user_flags_hex()
10291 {
10292 dealii::clear_user_flags_hex(dim, levels, faces.get());
10293 }
10294
10295
10296
10297 template <int dim, int spacedim>
10298 void
clear_user_flags()10299 Triangulation<dim, spacedim>::clear_user_flags()
10300 {
10301 clear_user_flags_line();
10302 clear_user_flags_quad();
10303 clear_user_flags_hex();
10304 }
10305
10306
10307
10308 template <int dim, int spacedim>
10309 void
save_user_flags(std::ostream & out) const10310 Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
10311 {
10312 save_user_flags_line(out);
10313
10314 if (dim >= 2)
10315 save_user_flags_quad(out);
10316
10317 if (dim >= 3)
10318 save_user_flags_hex(out);
10319
10320 if (dim >= 4)
10321 Assert(false, ExcNotImplemented());
10322 }
10323
10324
10325
10326 template <int dim, int spacedim>
10327 void
save_user_flags(std::vector<bool> & v) const10328 Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
10329 {
10330 // clear vector and append
10331 // all the stuff later on
10332 v.clear();
10333
10334 std::vector<bool> tmp;
10335
10336 save_user_flags_line(tmp);
10337 v.insert(v.end(), tmp.begin(), tmp.end());
10338
10339 if (dim >= 2)
10340 {
10341 save_user_flags_quad(tmp);
10342 v.insert(v.end(), tmp.begin(), tmp.end());
10343 }
10344
10345 if (dim >= 3)
10346 {
10347 save_user_flags_hex(tmp);
10348 v.insert(v.end(), tmp.begin(), tmp.end());
10349 }
10350
10351 if (dim >= 4)
10352 Assert(false, ExcNotImplemented());
10353 }
10354
10355
10356
10357 template <int dim, int spacedim>
10358 void
load_user_flags(std::istream & in)10359 Triangulation<dim, spacedim>::load_user_flags(std::istream &in)
10360 {
10361 load_user_flags_line(in);
10362
10363 if (dim >= 2)
10364 load_user_flags_quad(in);
10365
10366 if (dim >= 3)
10367 load_user_flags_hex(in);
10368
10369 if (dim >= 4)
10370 Assert(false, ExcNotImplemented());
10371 }
10372
10373
10374
10375 template <int dim, int spacedim>
10376 void
load_user_flags(const std::vector<bool> & v)10377 Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
10378 {
10379 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
10380 std::vector<bool> tmp;
10381
10382 // first extract the flags
10383 // belonging to lines
10384 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
10385 // and set the lines
10386 load_user_flags_line(tmp);
10387
10388 if (dim >= 2)
10389 {
10390 tmp.clear();
10391 tmp.insert(tmp.end(),
10392 v.begin() + n_lines(),
10393 v.begin() + n_lines() + n_quads());
10394 load_user_flags_quad(tmp);
10395 }
10396
10397 if (dim >= 3)
10398 {
10399 tmp.clear();
10400 tmp.insert(tmp.end(),
10401 v.begin() + n_lines() + n_quads(),
10402 v.begin() + n_lines() + n_quads() + n_hexs());
10403 load_user_flags_hex(tmp);
10404 }
10405
10406 if (dim >= 4)
10407 Assert(false, ExcNotImplemented());
10408 }
10409
10410
10411
10412 template <int dim, int spacedim>
10413 void
save_user_flags_line(std::vector<bool> & v) const10414 Triangulation<dim, spacedim>::save_user_flags_line(std::vector<bool> &v) const
10415 {
10416 v.resize(n_lines(), false);
10417 std::vector<bool>::iterator i = v.begin();
10418 line_iterator line = begin_line(), endl = end_line();
10419 for (; line != endl; ++line, ++i)
10420 *i = line->user_flag_set();
10421
10422 Assert(i == v.end(), ExcInternalError());
10423 }
10424
10425
10426
10427 template <int dim, int spacedim>
10428 void
save_user_flags_line(std::ostream & out) const10429 Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
10430 {
10431 std::vector<bool> v;
10432 save_user_flags_line(v);
10433 write_bool_vector(mn_tria_line_user_flags_begin,
10434 v,
10435 mn_tria_line_user_flags_end,
10436 out);
10437 }
10438
10439
10440
10441 template <int dim, int spacedim>
10442 void
load_user_flags_line(std::istream & in)10443 Triangulation<dim, spacedim>::load_user_flags_line(std::istream &in)
10444 {
10445 std::vector<bool> v;
10446 read_bool_vector(mn_tria_line_user_flags_begin,
10447 v,
10448 mn_tria_line_user_flags_end,
10449 in);
10450 load_user_flags_line(v);
10451 }
10452
10453
10454
10455 template <int dim, int spacedim>
10456 void
load_user_flags_line(const std::vector<bool> & v)10457 Triangulation<dim, spacedim>::load_user_flags_line(const std::vector<bool> &v)
10458 {
10459 Assert(v.size() == n_lines(), ExcGridReadError());
10460
10461 line_iterator line = begin_line(), endl = end_line();
10462 std::vector<bool>::const_iterator i = v.begin();
10463 for (; line != endl; ++line, ++i)
10464 if (*i == true)
10465 line->set_user_flag();
10466 else
10467 line->clear_user_flag();
10468
10469 Assert(i == v.end(), ExcInternalError());
10470 }
10471
10472
10473 namespace
10474 {
10475 template <typename Iterator>
10476 bool
get_user_flag(const Iterator & i)10477 get_user_flag(const Iterator &i)
10478 {
10479 return i->user_flag_set();
10480 }
10481
10482
10483
10484 template <int structdim, int dim, int spacedim>
10485 bool
get_user_flag(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &)10486 get_user_flag(const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
10487 {
10488 Assert(false, ExcInternalError());
10489 return false;
10490 }
10491
10492
10493
10494 template <typename Iterator>
10495 void
set_user_flag(const Iterator & i)10496 set_user_flag(const Iterator &i)
10497 {
10498 i->set_user_flag();
10499 }
10500
10501
10502
10503 template <int structdim, int dim, int spacedim>
10504 void
set_user_flag(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &)10505 set_user_flag(const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
10506 {
10507 Assert(false, ExcInternalError());
10508 }
10509
10510
10511
10512 template <typename Iterator>
10513 void
clear_user_flag(const Iterator & i)10514 clear_user_flag(const Iterator &i)
10515 {
10516 i->clear_user_flag();
10517 }
10518
10519
10520
10521 template <int structdim, int dim, int spacedim>
10522 void
clear_user_flag(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &)10523 clear_user_flag(
10524 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
10525 {
10526 Assert(false, ExcInternalError());
10527 }
10528 } // namespace
10529
10530
10531 template <int dim, int spacedim>
10532 void
save_user_flags_quad(std::vector<bool> & v) const10533 Triangulation<dim, spacedim>::save_user_flags_quad(std::vector<bool> &v) const
10534 {
10535 v.resize(n_quads(), false);
10536
10537 if (dim >= 2)
10538 {
10539 std::vector<bool>::iterator i = v.begin();
10540 quad_iterator quad = begin_quad(), endq = end_quad();
10541 for (; quad != endq; ++quad, ++i)
10542 *i = get_user_flag(quad);
10543
10544 Assert(i == v.end(), ExcInternalError());
10545 }
10546 }
10547
10548
10549
10550 template <int dim, int spacedim>
10551 void
save_user_flags_quad(std::ostream & out) const10552 Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
10553 {
10554 std::vector<bool> v;
10555 save_user_flags_quad(v);
10556 write_bool_vector(mn_tria_quad_user_flags_begin,
10557 v,
10558 mn_tria_quad_user_flags_end,
10559 out);
10560 }
10561
10562
10563
10564 template <int dim, int spacedim>
10565 void
load_user_flags_quad(std::istream & in)10566 Triangulation<dim, spacedim>::load_user_flags_quad(std::istream &in)
10567 {
10568 std::vector<bool> v;
10569 read_bool_vector(mn_tria_quad_user_flags_begin,
10570 v,
10571 mn_tria_quad_user_flags_end,
10572 in);
10573 load_user_flags_quad(v);
10574 }
10575
10576
10577
10578 template <int dim, int spacedim>
10579 void
load_user_flags_quad(const std::vector<bool> & v)10580 Triangulation<dim, spacedim>::load_user_flags_quad(const std::vector<bool> &v)
10581 {
10582 Assert(v.size() == n_quads(), ExcGridReadError());
10583
10584 if (dim >= 2)
10585 {
10586 quad_iterator quad = begin_quad(), endq = end_quad();
10587 std::vector<bool>::const_iterator i = v.begin();
10588 for (; quad != endq; ++quad, ++i)
10589 if (*i == true)
10590 set_user_flag(quad);
10591 else
10592 clear_user_flag(quad);
10593
10594 Assert(i == v.end(), ExcInternalError());
10595 }
10596 }
10597
10598
10599
10600 template <int dim, int spacedim>
10601 void
save_user_flags_hex(std::vector<bool> & v) const10602 Triangulation<dim, spacedim>::save_user_flags_hex(std::vector<bool> &v) const
10603 {
10604 v.resize(n_hexs(), false);
10605
10606 if (dim >= 3)
10607 {
10608 std::vector<bool>::iterator i = v.begin();
10609 hex_iterator hex = begin_hex(), endh = end_hex();
10610 for (; hex != endh; ++hex, ++i)
10611 *i = get_user_flag(hex);
10612
10613 Assert(i == v.end(), ExcInternalError());
10614 }
10615 }
10616
10617
10618
10619 template <int dim, int spacedim>
10620 void
save_user_flags_hex(std::ostream & out) const10621 Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
10622 {
10623 std::vector<bool> v;
10624 save_user_flags_hex(v);
10625 write_bool_vector(mn_tria_hex_user_flags_begin,
10626 v,
10627 mn_tria_hex_user_flags_end,
10628 out);
10629 }
10630
10631
10632
10633 template <int dim, int spacedim>
10634 void
load_user_flags_hex(std::istream & in)10635 Triangulation<dim, spacedim>::load_user_flags_hex(std::istream &in)
10636 {
10637 std::vector<bool> v;
10638 read_bool_vector(mn_tria_hex_user_flags_begin,
10639 v,
10640 mn_tria_hex_user_flags_end,
10641 in);
10642 load_user_flags_hex(v);
10643 }
10644
10645
10646
10647 template <int dim, int spacedim>
10648 void
load_user_flags_hex(const std::vector<bool> & v)10649 Triangulation<dim, spacedim>::load_user_flags_hex(const std::vector<bool> &v)
10650 {
10651 Assert(v.size() == n_hexs(), ExcGridReadError());
10652
10653 if (dim >= 3)
10654 {
10655 hex_iterator hex = begin_hex(), endh = end_hex();
10656 std::vector<bool>::const_iterator i = v.begin();
10657 for (; hex != endh; ++hex, ++i)
10658 if (*i == true)
10659 set_user_flag(hex);
10660 else
10661 clear_user_flag(hex);
10662
10663 Assert(i == v.end(), ExcInternalError());
10664 }
10665 }
10666
10667
10668
10669 template <int dim, int spacedim>
10670 void
save_user_indices(std::vector<unsigned int> & v) const10671 Triangulation<dim, spacedim>::save_user_indices(
10672 std::vector<unsigned int> &v) const
10673 {
10674 // clear vector and append all the
10675 // stuff later on
10676 v.clear();
10677
10678 std::vector<unsigned int> tmp;
10679
10680 save_user_indices_line(tmp);
10681 v.insert(v.end(), tmp.begin(), tmp.end());
10682
10683 if (dim >= 2)
10684 {
10685 save_user_indices_quad(tmp);
10686 v.insert(v.end(), tmp.begin(), tmp.end());
10687 }
10688
10689 if (dim >= 3)
10690 {
10691 save_user_indices_hex(tmp);
10692 v.insert(v.end(), tmp.begin(), tmp.end());
10693 }
10694
10695 if (dim >= 4)
10696 Assert(false, ExcNotImplemented());
10697 }
10698
10699
10700
10701 template <int dim, int spacedim>
10702 void
load_user_indices(const std::vector<unsigned int> & v)10703 Triangulation<dim, spacedim>::load_user_indices(
10704 const std::vector<unsigned int> &v)
10705 {
10706 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
10707 std::vector<unsigned int> tmp;
10708
10709 // first extract the indices
10710 // belonging to lines
10711 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
10712 // and set the lines
10713 load_user_indices_line(tmp);
10714
10715 if (dim >= 2)
10716 {
10717 tmp.clear();
10718 tmp.insert(tmp.end(),
10719 v.begin() + n_lines(),
10720 v.begin() + n_lines() + n_quads());
10721 load_user_indices_quad(tmp);
10722 }
10723
10724 if (dim >= 3)
10725 {
10726 tmp.clear();
10727 tmp.insert(tmp.end(),
10728 v.begin() + n_lines() + n_quads(),
10729 v.begin() + n_lines() + n_quads() + n_hexs());
10730 load_user_indices_hex(tmp);
10731 }
10732
10733 if (dim >= 4)
10734 Assert(false, ExcNotImplemented());
10735 }
10736
10737
10738
10739 namespace
10740 {
10741 template <typename Iterator>
10742 unsigned int
get_user_index(const Iterator & i)10743 get_user_index(const Iterator &i)
10744 {
10745 return i->user_index();
10746 }
10747
10748
10749
10750 template <int structdim, int dim, int spacedim>
10751 unsigned int
get_user_index(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &)10752 get_user_index(
10753 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
10754 {
10755 Assert(false, ExcInternalError());
10756 return numbers::invalid_unsigned_int;
10757 }
10758
10759
10760
10761 template <typename Iterator>
10762 void
set_user_index(const Iterator & i,const unsigned int x)10763 set_user_index(const Iterator &i, const unsigned int x)
10764 {
10765 i->set_user_index(x);
10766 }
10767
10768
10769
10770 template <int structdim, int dim, int spacedim>
10771 void
set_user_index(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &,const unsigned int)10772 set_user_index(
10773 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &,
10774 const unsigned int)
10775 {
10776 Assert(false, ExcInternalError());
10777 }
10778 } // namespace
10779
10780
10781 template <int dim, int spacedim>
10782 void
save_user_indices_line(std::vector<unsigned int> & v) const10783 Triangulation<dim, spacedim>::save_user_indices_line(
10784 std::vector<unsigned int> &v) const
10785 {
10786 v.resize(n_lines(), 0);
10787 std::vector<unsigned int>::iterator i = v.begin();
10788 line_iterator line = begin_line(), endl = end_line();
10789 for (; line != endl; ++line, ++i)
10790 *i = line->user_index();
10791 }
10792
10793
10794
10795 template <int dim, int spacedim>
10796 void
load_user_indices_line(const std::vector<unsigned int> & v)10797 Triangulation<dim, spacedim>::load_user_indices_line(
10798 const std::vector<unsigned int> &v)
10799 {
10800 Assert(v.size() == n_lines(), ExcGridReadError());
10801
10802 line_iterator line = begin_line(), endl = end_line();
10803 std::vector<unsigned int>::const_iterator i = v.begin();
10804 for (; line != endl; ++line, ++i)
10805 line->set_user_index(*i);
10806 }
10807
10808
10809 template <int dim, int spacedim>
10810 void
save_user_indices_quad(std::vector<unsigned int> & v) const10811 Triangulation<dim, spacedim>::save_user_indices_quad(
10812 std::vector<unsigned int> &v) const
10813 {
10814 v.resize(n_quads(), 0);
10815
10816 if (dim >= 2)
10817 {
10818 std::vector<unsigned int>::iterator i = v.begin();
10819 quad_iterator quad = begin_quad(), endq = end_quad();
10820 for (; quad != endq; ++quad, ++i)
10821 *i = get_user_index(quad);
10822 }
10823 }
10824
10825
10826
10827 template <int dim, int spacedim>
10828 void
load_user_indices_quad(const std::vector<unsigned int> & v)10829 Triangulation<dim, spacedim>::load_user_indices_quad(
10830 const std::vector<unsigned int> &v)
10831 {
10832 Assert(v.size() == n_quads(), ExcGridReadError());
10833
10834 if (dim >= 2)
10835 {
10836 quad_iterator quad = begin_quad(), endq = end_quad();
10837 std::vector<unsigned int>::const_iterator i = v.begin();
10838 for (; quad != endq; ++quad, ++i)
10839 set_user_index(quad, *i);
10840 }
10841 }
10842
10843
10844 template <int dim, int spacedim>
10845 void
save_user_indices_hex(std::vector<unsigned int> & v) const10846 Triangulation<dim, spacedim>::save_user_indices_hex(
10847 std::vector<unsigned int> &v) const
10848 {
10849 v.resize(n_hexs(), 0);
10850
10851 if (dim >= 3)
10852 {
10853 std::vector<unsigned int>::iterator i = v.begin();
10854 hex_iterator hex = begin_hex(), endh = end_hex();
10855 for (; hex != endh; ++hex, ++i)
10856 *i = get_user_index(hex);
10857 }
10858 }
10859
10860
10861
10862 template <int dim, int spacedim>
10863 void
load_user_indices_hex(const std::vector<unsigned int> & v)10864 Triangulation<dim, spacedim>::load_user_indices_hex(
10865 const std::vector<unsigned int> &v)
10866 {
10867 Assert(v.size() == n_hexs(), ExcGridReadError());
10868
10869 if (dim >= 3)
10870 {
10871 hex_iterator hex = begin_hex(), endh = end_hex();
10872 std::vector<unsigned int>::const_iterator i = v.begin();
10873 for (; hex != endh; ++hex, ++i)
10874 set_user_index(hex, *i);
10875 }
10876 }
10877
10878
10879
10880 //---------------- user pointers ----------------------------------------//
10881
10882
10883 namespace
10884 {
10885 template <typename Iterator>
10886 void *
get_user_pointer(const Iterator & i)10887 get_user_pointer(const Iterator &i)
10888 {
10889 return i->user_pointer();
10890 }
10891
10892
10893
10894 template <int structdim, int dim, int spacedim>
10895 void *
get_user_pointer(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &)10896 get_user_pointer(
10897 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
10898 {
10899 Assert(false, ExcInternalError());
10900 return nullptr;
10901 }
10902
10903
10904
10905 template <typename Iterator>
10906 void
set_user_pointer(const Iterator & i,void * x)10907 set_user_pointer(const Iterator &i, void *x)
10908 {
10909 i->set_user_pointer(x);
10910 }
10911
10912
10913
10914 template <int structdim, int dim, int spacedim>
10915 void
set_user_pointer(const TriaIterator<InvalidAccessor<structdim,dim,spacedim>> &,void *)10916 set_user_pointer(
10917 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &,
10918 void *)
10919 {
10920 Assert(false, ExcInternalError());
10921 }
10922 } // namespace
10923
10924
10925 template <int dim, int spacedim>
10926 void
save_user_pointers(std::vector<void * > & v) const10927 Triangulation<dim, spacedim>::save_user_pointers(std::vector<void *> &v) const
10928 {
10929 // clear vector and append all the
10930 // stuff later on
10931 v.clear();
10932
10933 std::vector<void *> tmp;
10934
10935 save_user_pointers_line(tmp);
10936 v.insert(v.end(), tmp.begin(), tmp.end());
10937
10938 if (dim >= 2)
10939 {
10940 save_user_pointers_quad(tmp);
10941 v.insert(v.end(), tmp.begin(), tmp.end());
10942 }
10943
10944 if (dim >= 3)
10945 {
10946 save_user_pointers_hex(tmp);
10947 v.insert(v.end(), tmp.begin(), tmp.end());
10948 }
10949
10950 if (dim >= 4)
10951 Assert(false, ExcNotImplemented());
10952 }
10953
10954
10955
10956 template <int dim, int spacedim>
10957 void
load_user_pointers(const std::vector<void * > & v)10958 Triangulation<dim, spacedim>::load_user_pointers(const std::vector<void *> &v)
10959 {
10960 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
10961 std::vector<void *> tmp;
10962
10963 // first extract the pointers
10964 // belonging to lines
10965 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
10966 // and set the lines
10967 load_user_pointers_line(tmp);
10968
10969 if (dim >= 2)
10970 {
10971 tmp.clear();
10972 tmp.insert(tmp.end(),
10973 v.begin() + n_lines(),
10974 v.begin() + n_lines() + n_quads());
10975 load_user_pointers_quad(tmp);
10976 }
10977
10978 if (dim >= 3)
10979 {
10980 tmp.clear();
10981 tmp.insert(tmp.end(),
10982 v.begin() + n_lines() + n_quads(),
10983 v.begin() + n_lines() + n_quads() + n_hexs());
10984 load_user_pointers_hex(tmp);
10985 }
10986
10987 if (dim >= 4)
10988 Assert(false, ExcNotImplemented());
10989 }
10990
10991
10992
10993 template <int dim, int spacedim>
10994 void
save_user_pointers_line(std::vector<void * > & v) const10995 Triangulation<dim, spacedim>::save_user_pointers_line(
10996 std::vector<void *> &v) const
10997 {
10998 v.resize(n_lines(), nullptr);
10999 std::vector<void *>::iterator i = v.begin();
11000 line_iterator line = begin_line(), endl = end_line();
11001 for (; line != endl; ++line, ++i)
11002 *i = line->user_pointer();
11003 }
11004
11005
11006
11007 template <int dim, int spacedim>
11008 void
load_user_pointers_line(const std::vector<void * > & v)11009 Triangulation<dim, spacedim>::load_user_pointers_line(
11010 const std::vector<void *> &v)
11011 {
11012 Assert(v.size() == n_lines(), ExcGridReadError());
11013
11014 line_iterator line = begin_line(), endl = end_line();
11015 std::vector<void *>::const_iterator i = v.begin();
11016 for (; line != endl; ++line, ++i)
11017 line->set_user_pointer(*i);
11018 }
11019
11020
11021
11022 template <int dim, int spacedim>
11023 void
save_user_pointers_quad(std::vector<void * > & v) const11024 Triangulation<dim, spacedim>::save_user_pointers_quad(
11025 std::vector<void *> &v) const
11026 {
11027 v.resize(n_quads(), nullptr);
11028
11029 if (dim >= 2)
11030 {
11031 std::vector<void *>::iterator i = v.begin();
11032 quad_iterator quad = begin_quad(), endq = end_quad();
11033 for (; quad != endq; ++quad, ++i)
11034 *i = get_user_pointer(quad);
11035 }
11036 }
11037
11038
11039
11040 template <int dim, int spacedim>
11041 void
load_user_pointers_quad(const std::vector<void * > & v)11042 Triangulation<dim, spacedim>::load_user_pointers_quad(
11043 const std::vector<void *> &v)
11044 {
11045 Assert(v.size() == n_quads(), ExcGridReadError());
11046
11047 if (dim >= 2)
11048 {
11049 quad_iterator quad = begin_quad(), endq = end_quad();
11050 std::vector<void *>::const_iterator i = v.begin();
11051 for (; quad != endq; ++quad, ++i)
11052 set_user_pointer(quad, *i);
11053 }
11054 }
11055
11056
11057 template <int dim, int spacedim>
11058 void
save_user_pointers_hex(std::vector<void * > & v) const11059 Triangulation<dim, spacedim>::save_user_pointers_hex(
11060 std::vector<void *> &v) const
11061 {
11062 v.resize(n_hexs(), nullptr);
11063
11064 if (dim >= 3)
11065 {
11066 std::vector<void *>::iterator i = v.begin();
11067 hex_iterator hex = begin_hex(), endh = end_hex();
11068 for (; hex != endh; ++hex, ++i)
11069 *i = get_user_pointer(hex);
11070 }
11071 }
11072
11073
11074
11075 template <int dim, int spacedim>
11076 void
load_user_pointers_hex(const std::vector<void * > & v)11077 Triangulation<dim, spacedim>::load_user_pointers_hex(
11078 const std::vector<void *> &v)
11079 {
11080 Assert(v.size() == n_hexs(), ExcGridReadError());
11081
11082 if (dim >= 3)
11083 {
11084 hex_iterator hex = begin_hex(), endh = end_hex();
11085 std::vector<void *>::const_iterator i = v.begin();
11086 for (; hex != endh; ++hex, ++i)
11087 set_user_pointer(hex, *i);
11088 }
11089 }
11090
11091
11092
11093 /*------------------------ Cell iterator functions ------------------------*/
11094
11095
11096 template <int dim, int spacedim>
11097 typename Triangulation<dim, spacedim>::raw_cell_iterator
begin_raw(const unsigned int level) const11098 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
11099 {
11100 switch (dim)
11101 {
11102 case 1:
11103 return begin_raw_line(level);
11104 case 2:
11105 return begin_raw_quad(level);
11106 case 3:
11107 return begin_raw_hex(level);
11108 default:
11109 Assert(false, ExcNotImplemented());
11110 return raw_cell_iterator();
11111 }
11112 }
11113
11114
11115
11116 template <int dim, int spacedim>
11117 typename Triangulation<dim, spacedim>::cell_iterator
begin(const unsigned int level) const11118 Triangulation<dim, spacedim>::begin(const unsigned int level) const
11119 {
11120 switch (dim)
11121 {
11122 case 1:
11123 return begin_line(level);
11124 case 2:
11125 return begin_quad(level);
11126 case 3:
11127 return begin_hex(level);
11128 default:
11129 Assert(false, ExcImpossibleInDim(dim));
11130 return cell_iterator();
11131 }
11132 }
11133
11134
11135
11136 template <int dim, int spacedim>
11137 typename Triangulation<dim, spacedim>::active_cell_iterator
begin_active(const unsigned int level) const11138 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
11139 {
11140 switch (dim)
11141 {
11142 case 1:
11143 return begin_active_line(level);
11144 case 2:
11145 return begin_active_quad(level);
11146 case 3:
11147 return begin_active_hex(level);
11148 default:
11149 Assert(false, ExcNotImplemented());
11150 return active_cell_iterator();
11151 }
11152 }
11153
11154
11155
11156 template <int dim, int spacedim>
11157 typename Triangulation<dim, spacedim>::cell_iterator
last() const11158 Triangulation<dim, spacedim>::last() const
11159 {
11160 const unsigned int level = levels.size() - 1;
11161 if (levels[level]->cells.n_objects() == 0)
11162 return end(level);
11163
11164 // find the last raw iterator on
11165 // this level
11166 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
11167 level,
11168 levels[level]->cells.n_objects() - 1);
11169
11170 // then move to the last used one
11171 if (ri->used() == true)
11172 return ri;
11173 while ((--ri).state() == IteratorState::valid)
11174 if (ri->used() == true)
11175 return ri;
11176 return ri;
11177 }
11178
11179
11180
11181 template <int dim, int spacedim>
11182 typename Triangulation<dim, spacedim>::active_cell_iterator
last_active() const11183 Triangulation<dim, spacedim>::last_active() const
11184 {
11185 // get the last used cell
11186 cell_iterator cell = last();
11187
11188 if (cell != end())
11189 {
11190 // then move to the last active one
11191 if (cell->is_active() == true)
11192 return cell;
11193 while ((--cell).state() == IteratorState::valid)
11194 if (cell->is_active() == true)
11195 return cell;
11196 }
11197 return cell;
11198 }
11199
11200
11201
11202 template <int dim, int spacedim>
11203 typename Triangulation<dim, spacedim>::cell_iterator
end() const11204 Triangulation<dim, spacedim>::end() const
11205 {
11206 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
11207 -1,
11208 -1);
11209 }
11210
11211
11212
11213 template <int dim, int spacedim>
11214 typename Triangulation<dim, spacedim>::raw_cell_iterator
end_raw(const unsigned int level) const11215 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
11216 {
11217 // This function may be called on parallel triangulations on levels
11218 // that exist globally, but not on the local portion of the
11219 // triangulation. In that case, just return the end iterator.
11220 //
11221 // We need to use levels.size() instead of n_levels() because the
11222 // latter function uses the cache, but we need to be able to call
11223 // this function at a time when the cache is not currently up to
11224 // date.
11225 if (level >= levels.size())
11226 {
11227 Assert(level < n_global_levels(),
11228 ExcInvalidLevel(level, n_global_levels()));
11229 return end();
11230 }
11231
11232 // Query whether the given level is valid for the local portion of the
11233 // triangulation.
11234 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11235 if (level < levels.size() - 1)
11236 return begin_raw(level + 1);
11237 else
11238 return end();
11239 }
11240
11241
11242 template <int dim, int spacedim>
11243 typename Triangulation<dim, spacedim>::cell_iterator
end(const unsigned int level) const11244 Triangulation<dim, spacedim>::end(const unsigned int level) const
11245 {
11246 // This function may be called on parallel triangulations on levels
11247 // that exist globally, but not on the local portion of the
11248 // triangulation. In that case, just retrn the end iterator.
11249 //
11250 // We need to use levels.size() instead of n_levels() because the
11251 // latter function uses the cache, but we need to be able to call
11252 // this function at a time when the cache is not currently up to
11253 // date.
11254 if (level >= levels.size())
11255 {
11256 Assert(level < n_global_levels(),
11257 ExcInvalidLevel(level, n_global_levels()));
11258 return end();
11259 }
11260
11261 // Query whether the given level is valid for the local portion of the
11262 // triangulation.
11263 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11264 if (level < levels.size() - 1)
11265 return begin(level + 1);
11266 else
11267 return end();
11268 }
11269
11270
11271 template <int dim, int spacedim>
11272 typename Triangulation<dim, spacedim>::active_cell_iterator
end_active(const unsigned int level) const11273 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
11274 {
11275 // This function may be called on parallel triangulations on levels
11276 // that exist globally, but not on the local portion of the
11277 // triangulation. In that case, just return the end iterator.
11278 //
11279 // We need to use levels.size() instead of n_levels() because the
11280 // latter function uses the cache, but we need to be able to call
11281 // this function at a time when the cache is not currently up to
11282 // date.
11283 if (level >= levels.size())
11284 {
11285 Assert(level < n_global_levels(),
11286 ExcInvalidLevel(level, n_global_levels()));
11287 return end();
11288 }
11289
11290 // Query whether the given level is valid for the local portion of the
11291 // triangulation.
11292 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11293 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
11294 begin_active(level + 1));
11295 }
11296
11297
11298
11299 template <int dim, int spacedim>
11300 IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
cell_iterators() const11301 Triangulation<dim, spacedim>::cell_iterators() const
11302 {
11303 return IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>(
11304 begin(), end());
11305 }
11306
11307
11308 template <int dim, int spacedim>
11309 IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
active_cell_iterators() const11310 Triangulation<dim, spacedim>::active_cell_iterators() const
11311 {
11312 return IteratorRange<
11313 typename Triangulation<dim, spacedim>::active_cell_iterator>(begin_active(),
11314 end());
11315 }
11316
11317
11318
11319 template <int dim, int spacedim>
11320 IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>
cell_iterators_on_level(const unsigned int level) const11321 Triangulation<dim, spacedim>::cell_iterators_on_level(
11322 const unsigned int level) const
11323 {
11324 return IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>(
11325 begin(level), end(level));
11326 }
11327
11328
11329
11330 template <int dim, int spacedim>
11331 IteratorRange<typename Triangulation<dim, spacedim>::active_cell_iterator>
active_cell_iterators_on_level(const unsigned int level) const11332 Triangulation<dim, spacedim>::active_cell_iterators_on_level(
11333 const unsigned int level) const
11334 {
11335 return IteratorRange<
11336 typename Triangulation<dim, spacedim>::active_cell_iterator>(
11337 begin_active(level), end_active(level));
11338 }
11339
11340
11341 /*------------------------ Face iterator functions ------------------------*/
11342
11343
11344 template <int dim, int spacedim>
11345 typename Triangulation<dim, spacedim>::face_iterator
begin_face() const11346 Triangulation<dim, spacedim>::begin_face() const
11347 {
11348 switch (dim)
11349 {
11350 case 1:
11351 Assert(false, ExcImpossibleInDim(1));
11352 return raw_face_iterator();
11353 case 2:
11354 return begin_line();
11355 case 3:
11356 return begin_quad();
11357 default:
11358 Assert(false, ExcNotImplemented());
11359 return face_iterator();
11360 }
11361 }
11362
11363
11364
11365 template <int dim, int spacedim>
11366 typename Triangulation<dim, spacedim>::active_face_iterator
begin_active_face() const11367 Triangulation<dim, spacedim>::begin_active_face() const
11368 {
11369 switch (dim)
11370 {
11371 case 1:
11372 Assert(false, ExcImpossibleInDim(1));
11373 return raw_face_iterator();
11374 case 2:
11375 return begin_active_line();
11376 case 3:
11377 return begin_active_quad();
11378 default:
11379 Assert(false, ExcNotImplemented());
11380 return active_face_iterator();
11381 }
11382 }
11383
11384
11385
11386 template <int dim, int spacedim>
11387 typename Triangulation<dim, spacedim>::face_iterator
end_face() const11388 Triangulation<dim, spacedim>::end_face() const
11389 {
11390 switch (dim)
11391 {
11392 case 1:
11393 Assert(false, ExcImpossibleInDim(1));
11394 return raw_face_iterator();
11395 case 2:
11396 return end_line();
11397 case 3:
11398 return end_quad();
11399 default:
11400 Assert(false, ExcNotImplemented());
11401 return raw_face_iterator();
11402 }
11403 }
11404
11405
11406
11407 template <int dim, int spacedim>
11408 IteratorRange<typename Triangulation<dim, spacedim>::active_face_iterator>
active_face_iterators() const11409 Triangulation<dim, spacedim>::active_face_iterators() const
11410 {
11411 return IteratorRange<
11412 typename Triangulation<dim, spacedim>::active_face_iterator>(
11413 begin_active_face(), end_face());
11414 }
11415
11416 /*------------------------ Vertex iterator functions ------------------------*/
11417
11418
11419 template <int dim, int spacedim>
11420 typename Triangulation<dim, spacedim>::vertex_iterator
begin_vertex() const11421 Triangulation<dim, spacedim>::begin_vertex() const
11422 {
11423 vertex_iterator i =
11424 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
11425 if (i.state() != IteratorState::valid)
11426 return i;
11427 // This loop will end because every triangulation has used vertices.
11428 while (i->used() == false)
11429 if ((++i).state() != IteratorState::valid)
11430 return i;
11431 return i;
11432 }
11433
11434
11435
11436 template <int dim, int spacedim>
11437 typename Triangulation<dim, spacedim>::active_vertex_iterator
begin_active_vertex() const11438 Triangulation<dim, spacedim>::begin_active_vertex() const
11439 {
11440 // every vertex is active
11441 return begin_vertex();
11442 }
11443
11444
11445
11446 template <int dim, int spacedim>
11447 typename Triangulation<dim, spacedim>::vertex_iterator
end_vertex() const11448 Triangulation<dim, spacedim>::end_vertex() const
11449 {
11450 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
11451 -1,
11452 numbers::invalid_unsigned_int);
11453 }
11454
11455
11456
11457 /*------------------------ Line iterator functions ------------------------*/
11458
11459
11460
11461 template <int dim, int spacedim>
11462 typename Triangulation<dim, spacedim>::raw_line_iterator
begin_raw_line(const unsigned int level) const11463 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
11464 {
11465 // This function may be called on parallel triangulations on levels
11466 // that exist globally, but not on the local portion of the
11467 // triangulation. In that case, just return the end iterator.
11468 //
11469 // We need to use levels.size() instead of n_levels() because the
11470 // latter function uses the cache, but we need to be able to call
11471 // this function at a time when the cache is not currently up to
11472 // date.
11473 if (level >= levels.size())
11474 {
11475 Assert(level < n_global_levels(),
11476 ExcInvalidLevel(level, n_global_levels()));
11477 return end_line();
11478 }
11479
11480 switch (dim)
11481 {
11482 case 1:
11483 // Query whether the given level is valid for the local portion of the
11484 // triangulation.
11485 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11486
11487 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
11488 return end_line();
11489
11490 return raw_line_iterator(
11491 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
11492
11493 default:
11494 Assert(level == 0, ExcFacesHaveNoLevel());
11495 return raw_line_iterator(
11496 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
11497 }
11498 }
11499
11500
11501 template <int dim, int spacedim>
11502 typename Triangulation<dim, spacedim>::line_iterator
begin_line(const unsigned int level) const11503 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
11504 {
11505 // level is checked in begin_raw
11506 raw_line_iterator ri = begin_raw_line(level);
11507 if (ri.state() != IteratorState::valid)
11508 return ri;
11509 while (ri->used() == false)
11510 if ((++ri).state() != IteratorState::valid)
11511 return ri;
11512 return ri;
11513 }
11514
11515
11516
11517 template <int dim, int spacedim>
11518 typename Triangulation<dim, spacedim>::active_line_iterator
begin_active_line(const unsigned int level) const11519 Triangulation<dim, spacedim>::begin_active_line(const unsigned int level) const
11520 {
11521 // level is checked in begin_raw
11522 line_iterator i = begin_line(level);
11523 if (i.state() != IteratorState::valid)
11524 return i;
11525 while (i->has_children())
11526 if ((++i).state() != IteratorState::valid)
11527 return i;
11528 return i;
11529 }
11530
11531
11532
11533 template <int dim, int spacedim>
11534 typename Triangulation<dim, spacedim>::line_iterator
end_line() const11535 Triangulation<dim, spacedim>::end_line() const
11536 {
11537 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
11538 -1,
11539 -1);
11540 }
11541
11542
11543
11544 /*------------------------ Quad iterator functions ------------------------*/
11545
11546
11547 template <int dim, int spacedim>
11548 typename Triangulation<dim, spacedim>::raw_quad_iterator
begin_raw_quad(const unsigned int level) const11549 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
11550 {
11551 // This function may be called on parallel triangulations on levels
11552 // that exist globally, but not on the local portion of the
11553 // triangulation. In that case, just return the end iterator.
11554 //
11555 // We need to use levels.size() instead of n_levels() because the
11556 // latter function uses the cache, but we need to be able to call
11557 // this function at a time when the cache is not currently up to
11558 // date.
11559 if (level >= levels.size())
11560 {
11561 Assert(level < n_global_levels(),
11562 ExcInvalidLevel(level, n_global_levels()));
11563 return end_quad();
11564 }
11565
11566 switch (dim)
11567 {
11568 case 1:
11569 Assert(false, ExcImpossibleInDim(1));
11570 return raw_hex_iterator();
11571 case 2:
11572 {
11573 // Query whether the given level is valid for the local portion of the
11574 // triangulation.
11575 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11576
11577 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
11578 return end_quad();
11579
11580 return raw_quad_iterator(
11581 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
11582 }
11583
11584 case 3:
11585 {
11586 Assert(level == 0, ExcFacesHaveNoLevel());
11587
11588 return raw_quad_iterator(
11589 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
11590 }
11591
11592
11593 default:
11594 Assert(false, ExcNotImplemented());
11595 return raw_hex_iterator();
11596 }
11597 }
11598
11599
11600
11601 template <int dim, int spacedim>
11602 typename Triangulation<dim, spacedim>::quad_iterator
begin_quad(const unsigned int level) const11603 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
11604 {
11605 // level is checked in begin_raw
11606 raw_quad_iterator ri = begin_raw_quad(level);
11607 if (ri.state() != IteratorState::valid)
11608 return ri;
11609 while (ri->used() == false)
11610 if ((++ri).state() != IteratorState::valid)
11611 return ri;
11612 return ri;
11613 }
11614
11615
11616
11617 template <int dim, int spacedim>
11618 typename Triangulation<dim, spacedim>::active_quad_iterator
begin_active_quad(const unsigned int level) const11619 Triangulation<dim, spacedim>::begin_active_quad(const unsigned int level) const
11620 {
11621 // level is checked in begin_raw
11622 quad_iterator i = begin_quad(level);
11623 if (i.state() != IteratorState::valid)
11624 return i;
11625 while (i->has_children())
11626 if ((++i).state() != IteratorState::valid)
11627 return i;
11628 return i;
11629 }
11630
11631
11632
11633 template <int dim, int spacedim>
11634 typename Triangulation<dim, spacedim>::quad_iterator
end_quad() const11635 Triangulation<dim, spacedim>::end_quad() const
11636 {
11637 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
11638 -1,
11639 -1);
11640 }
11641
11642
11643 /*------------------------ Hex iterator functions ------------------------*/
11644
11645
11646 template <int dim, int spacedim>
11647 typename Triangulation<dim, spacedim>::raw_hex_iterator
begin_raw_hex(const unsigned int level) const11648 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
11649 {
11650 // This function may be called on parallel triangulations on levels
11651 // that exist globally, but not on the local portion of the
11652 // triangulation. In that case, just return the end iterator.
11653 //
11654 // We need to use levels.size() instead of n_levels() because the
11655 // latter function uses the cache, but we need to be able to call
11656 // this function at a time when the cache is not currently up to
11657 // date.
11658 if (level >= levels.size())
11659 {
11660 Assert(level < n_global_levels(),
11661 ExcInvalidLevel(level, n_global_levels()));
11662 return end_hex();
11663 }
11664
11665 switch (dim)
11666 {
11667 case 1:
11668 case 2:
11669 Assert(false, ExcImpossibleInDim(1));
11670 return raw_hex_iterator();
11671 case 3:
11672 {
11673 // Query whether the given level is valid for the local portion of the
11674 // triangulation.
11675 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
11676
11677 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
11678 return end_hex();
11679
11680 return raw_hex_iterator(
11681 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
11682 }
11683
11684 default:
11685 Assert(false, ExcNotImplemented());
11686 return raw_hex_iterator();
11687 }
11688 }
11689
11690
11691
11692 template <int dim, int spacedim>
11693 typename Triangulation<dim, spacedim>::hex_iterator
begin_hex(const unsigned int level) const11694 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
11695 {
11696 // level is checked in begin_raw
11697 raw_hex_iterator ri = begin_raw_hex(level);
11698 if (ri.state() != IteratorState::valid)
11699 return ri;
11700 while (ri->used() == false)
11701 if ((++ri).state() != IteratorState::valid)
11702 return ri;
11703 return ri;
11704 }
11705
11706
11707
11708 template <int dim, int spacedim>
11709 typename Triangulation<dim, spacedim>::active_hex_iterator
begin_active_hex(const unsigned int level) const11710 Triangulation<dim, spacedim>::begin_active_hex(const unsigned int level) const
11711 {
11712 // level is checked in begin_raw
11713 hex_iterator i = begin_hex(level);
11714 if (i.state() != IteratorState::valid)
11715 return i;
11716 while (i->has_children())
11717 if ((++i).state() != IteratorState::valid)
11718 return i;
11719 return i;
11720 }
11721
11722
11723
11724 template <int dim, int spacedim>
11725 typename Triangulation<dim, spacedim>::hex_iterator
end_hex() const11726 Triangulation<dim, spacedim>::end_hex() const
11727 {
11728 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
11729 -1,
11730 -1);
11731 }
11732
11733
11734
11735 // -------------------------------- number of cells etc ---------------
11736
11737
11738 namespace internal
11739 {
11740 namespace TriangulationImplementation
11741 {
11742 inline unsigned int
n_cells(const internal::TriangulationImplementation::NumberCache<1> & c)11743 n_cells(const internal::TriangulationImplementation::NumberCache<1> &c)
11744 {
11745 return c.n_lines;
11746 }
11747
11748
11749 inline unsigned int
n_active_cells(const internal::TriangulationImplementation::NumberCache<1> & c)11750 n_active_cells(
11751 const internal::TriangulationImplementation::NumberCache<1> &c)
11752 {
11753 return c.n_active_lines;
11754 }
11755
11756
11757 inline unsigned int
n_cells(const internal::TriangulationImplementation::NumberCache<2> & c)11758 n_cells(const internal::TriangulationImplementation::NumberCache<2> &c)
11759 {
11760 return c.n_quads;
11761 }
11762
11763
11764 inline unsigned int
n_active_cells(const internal::TriangulationImplementation::NumberCache<2> & c)11765 n_active_cells(
11766 const internal::TriangulationImplementation::NumberCache<2> &c)
11767 {
11768 return c.n_active_quads;
11769 }
11770
11771
11772 inline unsigned int
n_cells(const internal::TriangulationImplementation::NumberCache<3> & c)11773 n_cells(const internal::TriangulationImplementation::NumberCache<3> &c)
11774 {
11775 return c.n_hexes;
11776 }
11777
11778
11779 inline unsigned int
n_active_cells(const internal::TriangulationImplementation::NumberCache<3> & c)11780 n_active_cells(
11781 const internal::TriangulationImplementation::NumberCache<3> &c)
11782 {
11783 return c.n_active_hexes;
11784 }
11785 } // namespace TriangulationImplementation
11786 } // namespace internal
11787
11788
11789
11790 template <int dim, int spacedim>
11791 unsigned int
n_cells() const11792 Triangulation<dim, spacedim>::n_cells() const
11793 {
11794 return internal::TriangulationImplementation::n_cells(number_cache);
11795 }
11796
11797
11798 template <int dim, int spacedim>
11799 unsigned int
n_active_cells() const11800 Triangulation<dim, spacedim>::n_active_cells() const
11801 {
11802 return internal::TriangulationImplementation::n_active_cells(number_cache);
11803 }
11804
11805 template <int dim, int spacedim>
11806 types::global_cell_index
n_global_active_cells() const11807 Triangulation<dim, spacedim>::n_global_active_cells() const
11808 {
11809 return n_active_cells();
11810 }
11811
11812
11813
11814 template <int dim, int spacedim>
11815 unsigned int
n_faces() const11816 Triangulation<dim, spacedim>::n_faces() const
11817 {
11818 switch (dim)
11819 {
11820 case 1:
11821 return n_used_vertices();
11822 case 2:
11823 return n_lines();
11824 case 3:
11825 return n_quads();
11826 default:
11827 Assert(false, ExcNotImplemented());
11828 }
11829 return 0;
11830 }
11831
11832
11833 template <int dim, int spacedim>
11834 unsigned int
n_raw_faces() const11835 Triangulation<dim, spacedim>::n_raw_faces() const
11836 {
11837 switch (dim)
11838 {
11839 case 1:
11840 return n_vertices();
11841 case 2:
11842 return n_raw_lines();
11843 case 3:
11844 return n_raw_quads();
11845 default:
11846 Assert(false, ExcNotImplemented());
11847 }
11848 return 0;
11849 }
11850
11851
11852 template <int dim, int spacedim>
11853 unsigned int
n_active_faces() const11854 Triangulation<dim, spacedim>::n_active_faces() const
11855 {
11856 switch (dim)
11857 {
11858 case 1:
11859 return n_used_vertices();
11860 case 2:
11861 return n_active_lines();
11862 case 3:
11863 return n_active_quads();
11864 default:
11865 Assert(false, ExcNotImplemented());
11866 }
11867 return 0;
11868 }
11869
11870
11871 template <int dim, int spacedim>
11872 unsigned int
n_raw_cells(const unsigned int level) const11873 Triangulation<dim, spacedim>::n_raw_cells(const unsigned int level) const
11874 {
11875 switch (dim)
11876 {
11877 case 1:
11878 return n_raw_lines(level);
11879 case 2:
11880 return n_raw_quads(level);
11881 case 3:
11882 return n_raw_hexs(level);
11883 default:
11884 Assert(false, ExcNotImplemented());
11885 }
11886 return 0;
11887 }
11888
11889
11890
11891 template <int dim, int spacedim>
11892 unsigned int
n_cells(const unsigned int level) const11893 Triangulation<dim, spacedim>::n_cells(const unsigned int level) const
11894 {
11895 switch (dim)
11896 {
11897 case 1:
11898 return n_lines(level);
11899 case 2:
11900 return n_quads(level);
11901 case 3:
11902 return n_hexs(level);
11903 default:
11904 Assert(false, ExcNotImplemented());
11905 }
11906 return 0;
11907 }
11908
11909
11910
11911 template <int dim, int spacedim>
11912 unsigned int
n_active_cells(const unsigned int level) const11913 Triangulation<dim, spacedim>::n_active_cells(const unsigned int level) const
11914 {
11915 switch (dim)
11916 {
11917 case 1:
11918 return n_active_lines(level);
11919 case 2:
11920 return n_active_quads(level);
11921 case 3:
11922 return n_active_hexs(level);
11923 default:
11924 Assert(false, ExcNotImplemented());
11925 }
11926 return 0;
11927 }
11928
11929
11930 template <int dim, int spacedim>
11931 bool
has_hanging_nodes() const11932 Triangulation<dim, spacedim>::has_hanging_nodes() const
11933 {
11934 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; lvl++)
11935 if (n_active_cells(lvl) != 0)
11936 return true;
11937
11938 return false;
11939 }
11940
11941
11942 template <int dim, int spacedim>
11943 unsigned int
n_lines() const11944 Triangulation<dim, spacedim>::n_lines() const
11945 {
11946 return number_cache.n_lines;
11947 }
11948
11949
11950
11951 template <int dim, int spacedim>
11952 unsigned int
n_raw_lines(const unsigned int level) const11953 Triangulation<dim, spacedim>::n_raw_lines(const unsigned int level) const
11954 {
11955 if (dim == 1)
11956 {
11957 AssertIndexRange(level, n_levels());
11958 return levels[level]->cells.n_objects();
11959 }
11960
11961 Assert(false, ExcFacesHaveNoLevel());
11962 return 0;
11963 }
11964
11965
11966 template <int dim, int spacedim>
11967 unsigned int
n_raw_lines() const11968 Triangulation<dim, spacedim>::n_raw_lines() const
11969 {
11970 if (dim == 1)
11971 {
11972 Assert(false, ExcNotImplemented());
11973 return 0;
11974 }
11975
11976 return faces->lines.n_objects();
11977 }
11978
11979
11980 template <int dim, int spacedim>
11981 unsigned int
n_lines(const unsigned int level) const11982 Triangulation<dim, spacedim>::n_lines(const unsigned int level) const
11983 {
11984 AssertIndexRange(level, number_cache.n_lines_level.size());
11985 Assert(dim == 1, ExcFacesHaveNoLevel());
11986 return number_cache.n_lines_level[level];
11987 }
11988
11989
11990 template <int dim, int spacedim>
11991 unsigned int
n_active_lines() const11992 Triangulation<dim, spacedim>::n_active_lines() const
11993 {
11994 return number_cache.n_active_lines;
11995 }
11996
11997
11998 template <int dim, int spacedim>
11999 unsigned int
n_active_lines(const unsigned int level) const12000 Triangulation<dim, spacedim>::n_active_lines(const unsigned int level) const
12001 {
12002 AssertIndexRange(level, number_cache.n_lines_level.size());
12003 Assert(dim == 1, ExcFacesHaveNoLevel());
12004
12005 return number_cache.n_active_lines_level[level];
12006 }
12007
12008
12009 template <>
12010 unsigned int
n_quads() const12011 Triangulation<1, 1>::n_quads() const
12012 {
12013 return 0;
12014 }
12015
12016
12017 template <>
12018 unsigned int
n_quads(const unsigned int) const12019 Triangulation<1, 1>::n_quads(const unsigned int) const
12020 {
12021 return 0;
12022 }
12023
12024
12025 template <>
12026 unsigned int
n_raw_quads(const unsigned int) const12027 Triangulation<1, 1>::n_raw_quads(const unsigned int) const
12028 {
12029 return 0;
12030 }
12031
12032
12033 template <>
12034 unsigned int
n_raw_hexs(const unsigned int) const12035 Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
12036 {
12037 return 0;
12038 }
12039
12040
12041 template <>
12042 unsigned int
n_active_quads(const unsigned int) const12043 Triangulation<1, 1>::n_active_quads(const unsigned int) const
12044 {
12045 return 0;
12046 }
12047
12048
12049 template <>
12050 unsigned int
n_active_quads() const12051 Triangulation<1, 1>::n_active_quads() const
12052 {
12053 return 0;
12054 }
12055
12056
12057
12058 template <>
12059 unsigned int
n_quads() const12060 Triangulation<1, 2>::n_quads() const
12061 {
12062 return 0;
12063 }
12064
12065
12066 template <>
12067 unsigned int
n_quads(const unsigned int) const12068 Triangulation<1, 2>::n_quads(const unsigned int) const
12069 {
12070 return 0;
12071 }
12072
12073
12074 template <>
12075 unsigned int
n_raw_quads(const unsigned int) const12076 Triangulation<1, 2>::n_raw_quads(const unsigned int) const
12077 {
12078 return 0;
12079 }
12080
12081
12082 template <>
12083 unsigned int
n_raw_hexs(const unsigned int) const12084 Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
12085 {
12086 return 0;
12087 }
12088
12089
12090 template <>
12091 unsigned int
n_active_quads(const unsigned int) const12092 Triangulation<1, 2>::n_active_quads(const unsigned int) const
12093 {
12094 return 0;
12095 }
12096
12097
12098 template <>
12099 unsigned int
n_active_quads() const12100 Triangulation<1, 2>::n_active_quads() const
12101 {
12102 return 0;
12103 }
12104
12105
12106 template <>
12107 unsigned int
n_quads() const12108 Triangulation<1, 3>::n_quads() const
12109 {
12110 return 0;
12111 }
12112
12113
12114 template <>
12115 unsigned int
n_quads(const unsigned int) const12116 Triangulation<1, 3>::n_quads(const unsigned int) const
12117 {
12118 return 0;
12119 }
12120
12121
12122 template <>
12123 unsigned int
n_raw_quads(const unsigned int) const12124 Triangulation<1, 3>::n_raw_quads(const unsigned int) const
12125 {
12126 return 0;
12127 }
12128
12129
12130 template <>
12131 unsigned int
n_raw_hexs(const unsigned int) const12132 Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
12133 {
12134 return 0;
12135 }
12136
12137
12138 template <>
12139 unsigned int
n_active_quads(const unsigned int) const12140 Triangulation<1, 3>::n_active_quads(const unsigned int) const
12141 {
12142 return 0;
12143 }
12144
12145
12146 template <>
12147 unsigned int
n_active_quads() const12148 Triangulation<1, 3>::n_active_quads() const
12149 {
12150 return 0;
12151 }
12152
12153
12154
12155 template <int dim, int spacedim>
12156 unsigned int
n_quads() const12157 Triangulation<dim, spacedim>::n_quads() const
12158 {
12159 return number_cache.n_quads;
12160 }
12161
12162
12163 template <int dim, int spacedim>
12164 unsigned int
n_quads(const unsigned int level) const12165 Triangulation<dim, spacedim>::n_quads(const unsigned int level) const
12166 {
12167 Assert(dim == 2, ExcFacesHaveNoLevel());
12168 AssertIndexRange(level, number_cache.n_quads_level.size());
12169 return number_cache.n_quads_level[level];
12170 }
12171
12172
12173
12174 template <>
12175 unsigned int
n_raw_quads(const unsigned int level) const12176 Triangulation<2, 2>::n_raw_quads(const unsigned int level) const
12177 {
12178 AssertIndexRange(level, n_levels());
12179 return levels[level]->cells.n_objects();
12180 }
12181
12182
12183
12184 template <>
12185 unsigned int
n_raw_quads(const unsigned int level) const12186 Triangulation<2, 3>::n_raw_quads(const unsigned int level) const
12187 {
12188 AssertIndexRange(level, n_levels());
12189 return levels[level]->cells.n_objects();
12190 }
12191
12192
12193 template <>
12194 unsigned int
n_raw_quads(const unsigned int) const12195 Triangulation<3, 3>::n_raw_quads(const unsigned int) const
12196 {
12197 Assert(false, ExcFacesHaveNoLevel());
12198 return 0;
12199 }
12200
12201
12202
12203 template <int dim, int spacedim>
12204 unsigned int
n_raw_quads() const12205 Triangulation<dim, spacedim>::n_raw_quads() const
12206 {
12207 Assert(false, ExcNotImplemented());
12208 return 0;
12209 }
12210
12211
12212
12213 template <>
12214 unsigned int
n_raw_quads() const12215 Triangulation<3, 3>::n_raw_quads() const
12216 {
12217 return faces->quads.n_objects();
12218 }
12219
12220
12221
12222 template <int dim, int spacedim>
12223 unsigned int
n_active_quads() const12224 Triangulation<dim, spacedim>::n_active_quads() const
12225 {
12226 return number_cache.n_active_quads;
12227 }
12228
12229
12230 template <int dim, int spacedim>
12231 unsigned int
n_active_quads(const unsigned int level) const12232 Triangulation<dim, spacedim>::n_active_quads(const unsigned int level) const
12233 {
12234 AssertIndexRange(level, number_cache.n_quads_level.size());
12235 Assert(dim == 2, ExcFacesHaveNoLevel());
12236
12237 return number_cache.n_active_quads_level[level];
12238 }
12239
12240
12241 template <int dim, int spacedim>
12242 unsigned int
n_hexs() const12243 Triangulation<dim, spacedim>::n_hexs() const
12244 {
12245 return 0;
12246 }
12247
12248
12249
12250 template <int dim, int spacedim>
12251 unsigned int
n_hexs(const unsigned int) const12252 Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
12253 {
12254 return 0;
12255 }
12256
12257
12258
12259 template <int dim, int spacedim>
12260 unsigned int
n_raw_hexs(const unsigned int) const12261 Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
12262 {
12263 return 0;
12264 }
12265
12266
12267 template <int dim, int spacedim>
12268 unsigned int
n_active_hexs() const12269 Triangulation<dim, spacedim>::n_active_hexs() const
12270 {
12271 return 0;
12272 }
12273
12274
12275
12276 template <int dim, int spacedim>
12277 unsigned int
n_active_hexs(const unsigned int) const12278 Triangulation<dim, spacedim>::n_active_hexs(const unsigned int) const
12279 {
12280 return 0;
12281 }
12282
12283
12284 template <>
12285 unsigned int
n_hexs() const12286 Triangulation<3, 3>::n_hexs() const
12287 {
12288 return number_cache.n_hexes;
12289 }
12290
12291
12292
12293 template <>
12294 unsigned int
n_hexs(const unsigned int level) const12295 Triangulation<3, 3>::n_hexs(const unsigned int level) const
12296 {
12297 AssertIndexRange(level, number_cache.n_hexes_level.size());
12298
12299 return number_cache.n_hexes_level[level];
12300 }
12301
12302
12303
12304 template <>
12305 unsigned int
n_raw_hexs(const unsigned int level) const12306 Triangulation<3, 3>::n_raw_hexs(const unsigned int level) const
12307 {
12308 AssertIndexRange(level, n_levels());
12309 return levels[level]->cells.n_objects();
12310 }
12311
12312
12313 template <>
12314 unsigned int
n_active_hexs() const12315 Triangulation<3, 3>::n_active_hexs() const
12316 {
12317 return number_cache.n_active_hexes;
12318 }
12319
12320
12321
12322 template <>
12323 unsigned int
n_active_hexs(const unsigned int level) const12324 Triangulation<3, 3>::n_active_hexs(const unsigned int level) const
12325 {
12326 AssertIndexRange(level, number_cache.n_hexes_level.size());
12327
12328 return number_cache.n_active_hexes_level[level];
12329 }
12330
12331
12332
12333 template <int dim, int spacedim>
12334 unsigned int
n_used_vertices() const12335 Triangulation<dim, spacedim>::n_used_vertices() const
12336 {
12337 return std::count(vertices_used.begin(), vertices_used.end(), true);
12338 }
12339
12340
12341
12342 template <int dim, int spacedim>
12343 const std::vector<bool> &
get_used_vertices() const12344 Triangulation<dim, spacedim>::get_used_vertices() const
12345 {
12346 return vertices_used;
12347 }
12348
12349
12350
12351 template <>
12352 unsigned int
max_adjacent_cells() const12353 Triangulation<1, 1>::max_adjacent_cells() const
12354 {
12355 return 2;
12356 }
12357
12358
12359
12360 template <>
12361 unsigned int
max_adjacent_cells() const12362 Triangulation<1, 2>::max_adjacent_cells() const
12363 {
12364 return 2;
12365 }
12366
12367
12368 template <>
12369 unsigned int
max_adjacent_cells() const12370 Triangulation<1, 3>::max_adjacent_cells() const
12371 {
12372 return 2;
12373 }
12374
12375
12376 template <int dim, int spacedim>
12377 unsigned int
max_adjacent_cells() const12378 Triangulation<dim, spacedim>::max_adjacent_cells() const
12379 {
12380 cell_iterator cell = begin(0),
12381 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
12382 // store the largest index of the
12383 // vertices used on level 0
12384 unsigned int max_vertex_index = 0;
12385 for (; cell != endc; ++cell)
12386 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
12387 if (cell->vertex_index(vertex) > max_vertex_index)
12388 max_vertex_index = cell->vertex_index(vertex);
12389
12390 // store the number of times a cell
12391 // touches a vertex. An unsigned
12392 // int should suffice, even for
12393 // larger dimensions
12394 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
12395 // touch a vertex's usage count
12396 // every time we find an adjacent
12397 // element
12398 for (cell = begin(); cell != endc; ++cell)
12399 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
12400 ++usage_count[cell->vertex_index(vertex)];
12401
12402 return std::max(GeometryInfo<dim>::vertices_per_cell,
12403 static_cast<unsigned int>(
12404 *std::max_element(usage_count.begin(), usage_count.end())));
12405 }
12406
12407
12408
12409 template <int dim, int spacedim>
12410 types::subdomain_id
locally_owned_subdomain() const12411 Triangulation<dim, spacedim>::locally_owned_subdomain() const
12412 {
12413 return numbers::invalid_subdomain_id;
12414 }
12415
12416
12417
12418 template <int dim, int spacedim>
12419 Triangulation<dim, spacedim> &
get_triangulation()12420 Triangulation<dim, spacedim>::get_triangulation()
12421 {
12422 return *this;
12423 }
12424
12425
12426
12427 template <int dim, int spacedim>
12428 const Triangulation<dim, spacedim> &
get_triangulation() const12429 Triangulation<dim, spacedim>::get_triangulation() const
12430 {
12431 return *this;
12432 }
12433
12434
12435
12436 template <int dim, int spacedim>
12437 void
add_periodicity(const std::vector<GridTools::PeriodicFacePair<cell_iterator>> & periodicity_vector)12438 Triangulation<dim, spacedim>::add_periodicity(
12439 const std::vector<GridTools::PeriodicFacePair<cell_iterator>>
12440 &periodicity_vector)
12441 {
12442 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
12443 periodicity_vector.begin(),
12444 periodicity_vector.end());
12445
12446 // Now initialize periodic_face_map
12447 update_periodic_face_map();
12448 }
12449
12450
12451
12452 template <int dim, int spacedim>
12453 const typename std::map<
12454 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
12455 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
12456 unsigned int>,
12457 std::bitset<3>>> &
get_periodic_face_map() const12458 Triangulation<dim, spacedim>::get_periodic_face_map() const
12459 {
12460 return periodic_face_map;
12461 }
12462
12463
12464
12465 template <int dim, int spacedim>
12466 void
execute_coarsening_and_refinement()12467 Triangulation<dim, spacedim>::execute_coarsening_and_refinement()
12468 {
12469 prepare_coarsening_and_refinement();
12470
12471 // verify a case with which we have had
12472 // some difficulty in the past (see the
12473 // deal.II/coarsening_* tests)
12474 if (smooth_grid & limit_level_difference_at_vertices)
12475 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
12476
12477 // Inform all listeners about beginning of refinement.
12478 signals.pre_refinement();
12479
12480 execute_coarsening();
12481
12482 const DistortedCellList cells_with_distorted_children = execute_refinement();
12483
12484 // verify a case with which we have had
12485 // some difficulty in the past (see the
12486 // deal.II/coarsening_* tests)
12487 if (smooth_grid & limit_level_difference_at_vertices)
12488 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
12489
12490 // finally build up neighbor connectivity information, and set
12491 // active cell indices
12492 update_neighbors(*this);
12493 reset_active_cell_indices();
12494
12495 // Inform all listeners about end of refinement.
12496 signals.post_refinement();
12497
12498 AssertThrow(cells_with_distorted_children.distorted_cells.size() == 0,
12499 cells_with_distorted_children);
12500
12501 update_periodic_face_map();
12502 }
12503
12504
12505
12506 template <int dim, int spacedim>
12507 void
reset_active_cell_indices()12508 Triangulation<dim, spacedim>::reset_active_cell_indices()
12509 {
12510 unsigned int active_cell_index = 0;
12511 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
12512 if ((cell->used() == false) || cell->has_children())
12513 cell->set_active_cell_index(numbers::invalid_unsigned_int);
12514 else
12515 {
12516 cell->set_active_cell_index(active_cell_index);
12517 ++active_cell_index;
12518 }
12519
12520 Assert(active_cell_index == n_active_cells(), ExcInternalError());
12521 }
12522
12523
12524 template <int dim, int spacedim>
12525 void
update_periodic_face_map()12526 Triangulation<dim, spacedim>::update_periodic_face_map()
12527 {
12528 // first empty the currently stored objects
12529 periodic_face_map.clear();
12530
12531 typename std::vector<
12532 GridTools::PeriodicFacePair<cell_iterator>>::const_iterator it;
12533 for (it = periodic_face_pairs_level_0.begin();
12534 it != periodic_face_pairs_level_0.end();
12535 ++it)
12536 {
12537 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
12538 it->cell[1],
12539 it->face_idx[0],
12540 it->face_idx[1],
12541 it->orientation,
12542 periodic_face_map);
12543
12544 // for the other way, we need to invert the orientation
12545 std::bitset<3> inverted_orientation;
12546 {
12547 bool orientation, flip, rotation;
12548 orientation = it->orientation[0];
12549 rotation = it->orientation[2];
12550 flip = orientation ? rotation ^ it->orientation[1] : it->orientation[1];
12551 inverted_orientation[0] = orientation;
12552 inverted_orientation[1] = flip;
12553 inverted_orientation[2] = rotation;
12554 }
12555 update_periodic_face_map_recursively<dim, spacedim>(it->cell[1],
12556 it->cell[0],
12557 it->face_idx[1],
12558 it->face_idx[0],
12559 inverted_orientation,
12560 periodic_face_map);
12561 }
12562
12563 // check consistency
12564 typename std::map<std::pair<cell_iterator, unsigned int>,
12565 std::pair<std::pair<cell_iterator, unsigned int>,
12566 std::bitset<3>>>::const_iterator it_test;
12567 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
12568 ++it_test)
12569 {
12570 const Triangulation<dim, spacedim>::cell_iterator cell_1 =
12571 it_test->first.first;
12572 const Triangulation<dim, spacedim>::cell_iterator cell_2 =
12573 it_test->second.first.first;
12574 if (cell_1->level() == cell_2->level())
12575 {
12576 // if both cells have the same neighbor, then the same pair
12577 // order swapped has to be in the map
12578 Assert(periodic_face_map[it_test->second.first].first ==
12579 it_test->first,
12580 ExcInternalError());
12581 }
12582 }
12583 }
12584
12585
12586
12587 template <int dim, int spacedim>
12588 void
clear_despite_subscriptions()12589 Triangulation<dim, spacedim>::clear_despite_subscriptions()
12590 {
12591 levels.clear();
12592 faces.reset();
12593
12594 vertices.clear();
12595 vertices_used.clear();
12596
12597 manifold.clear();
12598
12599 number_cache = internal::TriangulationImplementation::NumberCache<dim>();
12600 }
12601
12602
12603 template <int dim, int spacedim>
12604 typename Triangulation<dim, spacedim>::DistortedCellList
execute_refinement()12605 Triangulation<dim, spacedim>::execute_refinement()
12606 {
12607 const DistortedCellList cells_with_distorted_children =
12608 internal::TriangulationImplementation::Implementation::execute_refinement(
12609 *this, check_for_distorted_cells);
12610
12611
12612
12613 // re-compute number of lines
12614 internal::TriangulationImplementation::Implementation::compute_number_cache(
12615 *this, levels.size(), number_cache);
12616
12617 #ifdef DEBUG
12618 for (const auto &level : levels)
12619 monitor_memory(level->cells, dim);
12620
12621 // check whether really all refinement flags are reset (also of
12622 // previously non-active cells which we may not have touched. If the
12623 // refinement flag of a non-active cell is set, something went wrong
12624 // since the cell-accessors should have caught this)
12625 for (const auto &cell : this->cell_iterators())
12626 Assert(!cell->refine_flag_set(), ExcInternalError());
12627 #endif
12628
12629 return cells_with_distorted_children;
12630 }
12631
12632
12633
12634 template <int dim, int spacedim>
12635 void
execute_coarsening()12636 Triangulation<dim, spacedim>::execute_coarsening()
12637 {
12638 // create a vector counting for each line how many cells contain
12639 // this line. in 3D, this is used later on to decide which lines can
12640 // be deleted after coarsening a cell. in other dimensions it will
12641 // be ignored
12642 std::vector<unsigned int> line_cell_count =
12643 count_cells_bounded_by_line(*this);
12644 std::vector<unsigned int> quad_cell_count =
12645 count_cells_bounded_by_quad(*this);
12646
12647 // loop over all cells. Flag all cells of which all children are
12648 // flagged for coarsening and delete the childrens' flags. In
12649 // effect, only those cells are flagged of which originally all
12650 // children were flagged and for which all children are on the same
12651 // refinement level. For flagging, the user flags are used, to avoid
12652 // confusion and because non-active cells can't be flagged for
12653 // coarsening. Note that because of the effects of
12654 // @p{fix_coarsen_flags}, of a cell either all or no children must
12655 // be flagged for coarsening, so it is ok to only check the first
12656 // child
12657 clear_user_flags();
12658
12659 for (const auto &cell : this->cell_iterators())
12660 if (!cell->is_active())
12661 if (cell->child(0)->coarsen_flag_set())
12662 {
12663 cell->set_user_flag();
12664 for (unsigned int child = 0; child < cell->n_children(); ++child)
12665 {
12666 Assert(cell->child(child)->coarsen_flag_set(),
12667 ExcInternalError());
12668 cell->child(child)->clear_coarsen_flag();
12669 }
12670 }
12671
12672
12673 // now do the actual coarsening step. Since the loop goes over used
12674 // cells we only need not worry about deleting some cells since the
12675 // ++operator will then just hop over them if we should hit one. Do
12676 // the loop in the reverse way since we may only delete some cells
12677 // if their neighbors have already been deleted (if the latter are
12678 // on a higher level for example)
12679 //
12680 // since we delete the *children* of cells, we can ignore cells
12681 // on the highest level, i.e., level must be less than or equal
12682 // to n_levels()-2.
12683 cell_iterator cell = begin(), endc = end();
12684 if (levels.size() >= 2)
12685 for (cell = last(); cell != endc; --cell)
12686 if (cell->level() <= static_cast<int>(levels.size() - 2) &&
12687 cell->user_flag_set())
12688 {
12689 // inform all listeners that cell coarsening is going to happen
12690 signals.pre_coarsening_on_cell(cell);
12691 // use a separate function, since this is dimension specific
12692 internal::TriangulationImplementation::Implementation::
12693 delete_children(*this, cell, line_cell_count, quad_cell_count);
12694 }
12695
12696 // re-compute number of lines and quads
12697 internal::TriangulationImplementation::Implementation::compute_number_cache(
12698 *this, levels.size(), number_cache);
12699
12700 // in principle no user flags should be set any more at this point
12701 #if DEBUG
12702 for (cell = begin(); cell != endc; ++cell)
12703 Assert(cell->user_flag_set() == false, ExcInternalError());
12704 #endif
12705 }
12706
12707
12708
12709 template <int dim, int spacedim>
12710 void
fix_coarsen_flags()12711 Triangulation<dim, spacedim>::fix_coarsen_flags()
12712 {
12713 // copy a piece of code from prepare_coarsening_and_refinement that
12714 // ensures that the level difference at vertices is limited if so
12715 // desired. we need this code here since at least in 1d we don't
12716 // call the dimension-independent version of
12717 // prepare_coarsening_and_refinement function. in 2d and 3d, having
12718 // this hunk here makes our lives a bit easier as well as it takes
12719 // care of these cases earlier than it would otherwise happen.
12720 //
12721 // the main difference to the code in p_c_and_r is that here we
12722 // absolutely have to make sure that we get things right, i.e. that
12723 // in particular we set flags right if
12724 // limit_level_difference_at_vertices is set. to do so we iterate
12725 // until the flags don't change any more
12726 std::vector<bool> previous_coarsen_flags(n_active_cells());
12727 save_coarsen_flags(previous_coarsen_flags);
12728
12729 std::vector<int> vertex_level(vertices.size(), 0);
12730
12731 bool continue_iterating = true;
12732
12733 do
12734 {
12735 if (smooth_grid & limit_level_difference_at_vertices)
12736 {
12737 Assert(!anisotropic_refinement,
12738 ExcMessage("In case of anisotropic refinement the "
12739 "limit_level_difference_at_vertices flag for "
12740 "mesh smoothing must not be set!"));
12741
12742 // store highest level one of the cells adjacent to a vertex
12743 // belongs to
12744 std::fill(vertex_level.begin(), vertex_level.end(), 0);
12745 for (const auto &cell : this->active_cell_iterators())
12746 {
12747 if (cell->refine_flag_set())
12748 for (const unsigned int vertex :
12749 GeometryInfo<dim>::vertex_indices())
12750 vertex_level[cell->vertex_index(vertex)] =
12751 std::max(vertex_level[cell->vertex_index(vertex)],
12752 cell->level() + 1);
12753 else if (!cell->coarsen_flag_set())
12754 for (const unsigned int vertex :
12755 GeometryInfo<dim>::vertex_indices())
12756 vertex_level[cell->vertex_index(vertex)] =
12757 std::max(vertex_level[cell->vertex_index(vertex)],
12758 cell->level());
12759 else
12760 {
12761 // if coarsen flag is set then tentatively assume
12762 // that the cell will be coarsened. this isn't
12763 // always true (the coarsen flag could be removed
12764 // again) and so we may make an error here. we try
12765 // to correct this by iterating over the entire
12766 // process until we are converged
12767 Assert(cell->coarsen_flag_set(), ExcInternalError());
12768 for (const unsigned int vertex :
12769 GeometryInfo<dim>::vertex_indices())
12770 vertex_level[cell->vertex_index(vertex)] =
12771 std::max(vertex_level[cell->vertex_index(vertex)],
12772 cell->level() - 1);
12773 }
12774 }
12775
12776
12777 // loop over all cells in reverse order. do so because we
12778 // can then update the vertex levels on the adjacent
12779 // vertices and maybe already flag additional cells in this
12780 // loop
12781 //
12782 // note that not only may we have to add additional
12783 // refinement flags, but we will also have to remove
12784 // coarsening flags on cells adjacent to vertices that will
12785 // see refinement
12786 active_cell_iterator cell = begin_active(), endc = end();
12787 for (cell = last_active(); cell != endc; --cell)
12788 if (cell->refine_flag_set() == false)
12789 {
12790 for (const unsigned int vertex :
12791 GeometryInfo<dim>::vertex_indices())
12792 if (vertex_level[cell->vertex_index(vertex)] >=
12793 cell->level() + 1)
12794 {
12795 // remove coarsen flag...
12796 cell->clear_coarsen_flag();
12797
12798 // ...and if necessary also refine the current
12799 // cell, at the same time updating the level
12800 // information about vertices
12801 if (vertex_level[cell->vertex_index(vertex)] >
12802 cell->level() + 1)
12803 {
12804 cell->set_refine_flag();
12805
12806 for (const unsigned int v :
12807 GeometryInfo<dim>::vertex_indices())
12808 vertex_level[cell->vertex_index(v)] =
12809 std::max(vertex_level[cell->vertex_index(v)],
12810 cell->level() + 1);
12811 }
12812
12813 // continue and see whether we may, for example,
12814 // go into the inner 'if' above based on a
12815 // different vertex
12816 }
12817 }
12818 }
12819
12820 // loop over all cells. Flag all cells of which all children are
12821 // flagged for coarsening and delete the childrens' flags. Also
12822 // delete all flags of cells for which not all children of a
12823 // cell are flagged. In effect, only those cells are flagged of
12824 // which originally all children were flagged and for which all
12825 // children are on the same refinement level. For flagging, the
12826 // user flags are used, to avoid confusion and because
12827 // non-active cells can't be flagged for coarsening
12828 //
12829 // In effect, all coarsen flags are turned into user flags of
12830 // the mother cell if coarsening is possible or deleted
12831 // otherwise.
12832 clear_user_flags();
12833 // Coarsen flags of cells with no mother cell, i.e. on the
12834 // coarsest level are deleted explicitly.
12835 for (const auto &acell : this->active_cell_iterators_on_level(0))
12836 acell->clear_coarsen_flag();
12837
12838 for (const auto &cell : this->cell_iterators())
12839 {
12840 // nothing to do if we are already on the finest level
12841 if (cell->is_active())
12842 continue;
12843
12844 const unsigned int n_children = cell->n_children();
12845 unsigned int flagged_children = 0;
12846 for (unsigned int child = 0; child < n_children; ++child)
12847 if (cell->child(child)->is_active() &&
12848 cell->child(child)->coarsen_flag_set())
12849 {
12850 ++flagged_children;
12851 // clear flag since we don't need it anymore
12852 cell->child(child)->clear_coarsen_flag();
12853 }
12854
12855 // flag this cell for coarsening if all children were
12856 // flagged
12857 if (flagged_children == n_children)
12858 cell->set_user_flag();
12859 }
12860
12861 // in principle no coarsen flags should be set any more at this
12862 // point
12863 #if DEBUG
12864 for (auto &cell : this->cell_iterators())
12865 Assert(cell->coarsen_flag_set() == false, ExcInternalError());
12866 #endif
12867
12868 // now loop over all cells which have the user flag set. their
12869 // children were flagged for coarsening. set the coarsen flag
12870 // again if we are sure that none of the neighbors of these
12871 // children are refined, or will be refined, since then we would
12872 // get a two-level jump in refinement. on the other hand, if one
12873 // of the children's neighbors has their user flag set, then we
12874 // know that its children will go away by coarsening, and we
12875 // will be ok.
12876 //
12877 // note on the other hand that we do allow level-2 jumps in
12878 // refinement between neighbors in 1d, so this whole procedure
12879 // is only necessary if we are not in 1d
12880 //
12881 // since we remove some coarsening/user flags in the process, we
12882 // have to work from the finest level to the coarsest one, since
12883 // we occasionally inspect user flags of cells on finer levels
12884 // and need to be sure that these flags are final
12885 cell_iterator cell = begin(), endc = end();
12886 for (cell = last(); cell != endc; --cell)
12887 if (cell->user_flag_set())
12888 // if allowed: flag the
12889 // children for coarsening
12890 if (internal::TriangulationImplementation::Implementation::
12891 template coarsening_allowed<dim, spacedim>(cell))
12892 for (unsigned int c = 0; c < cell->n_children(); ++c)
12893 {
12894 Assert(cell->child(c)->refine_flag_set() == false,
12895 ExcInternalError());
12896
12897 cell->child(c)->set_coarsen_flag();
12898 }
12899
12900 // clear all user flags again, now that we don't need them any
12901 // more
12902 clear_user_flags();
12903
12904
12905 // now see if anything has changed in the last iteration of this
12906 // function
12907 std::vector<bool> current_coarsen_flags(n_active_cells());
12908 save_coarsen_flags(current_coarsen_flags);
12909
12910 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
12911 previous_coarsen_flags = current_coarsen_flags;
12912 }
12913 while (continue_iterating == true);
12914 }
12915
12916
12917 // TODO: merge the following 3 functions since they are the same
12918 template <>
12919 bool
prepare_coarsening_and_refinement()12920 Triangulation<1, 1>::prepare_coarsening_and_refinement()
12921 {
12922 // save the flags to determine whether something was changed in the
12923 // course of this function
12924 std::vector<bool> flags_before;
12925 save_coarsen_flags(flags_before);
12926
12927 // do nothing in 1d, except setting the coarsening flags correctly
12928 fix_coarsen_flags();
12929
12930 std::vector<bool> flags_after;
12931 save_coarsen_flags(flags_after);
12932
12933 return (flags_before != flags_after);
12934 }
12935
12936
12937 template <>
12938 bool
prepare_coarsening_and_refinement()12939 Triangulation<1, 2>::prepare_coarsening_and_refinement()
12940 {
12941 // save the flags to determine whether something was changed in the
12942 // course of this function
12943 std::vector<bool> flags_before;
12944 save_coarsen_flags(flags_before);
12945
12946 // do nothing in 1d, except setting the coarsening flags correctly
12947 fix_coarsen_flags();
12948
12949 std::vector<bool> flags_after;
12950 save_coarsen_flags(flags_after);
12951
12952 return (flags_before != flags_after);
12953 }
12954
12955
12956 template <>
12957 bool
prepare_coarsening_and_refinement()12958 Triangulation<1, 3>::prepare_coarsening_and_refinement()
12959 {
12960 // save the flags to determine whether something was changed in the
12961 // course of this function
12962 std::vector<bool> flags_before;
12963 save_coarsen_flags(flags_before);
12964
12965 // do nothing in 1d, except setting the coarsening flags correctly
12966 fix_coarsen_flags();
12967
12968 std::vector<bool> flags_after;
12969 save_coarsen_flags(flags_after);
12970
12971 return (flags_before != flags_after);
12972 }
12973
12974
12975
12976 namespace
12977 {
12978 // check if the given @param cell marked for coarsening would
12979 // produce an unrefined island. To break up long chains of these
12980 // cells we recursively check our neighbors in case we change this
12981 // cell. This reduces the number of outer iterations dramatically.
12982 template <int dim, int spacedim>
12983 void
possibly_do_not_produce_unrefined_islands(const typename Triangulation<dim,spacedim>::cell_iterator & cell)12984 possibly_do_not_produce_unrefined_islands(
12985 const typename Triangulation<dim, spacedim>::cell_iterator &cell)
12986 {
12987 Assert(cell->has_children(), ExcInternalError());
12988
12989 unsigned int n_neighbors = 0;
12990 // count all neighbors that will be refined along the face of our
12991 // cell after the next step
12992 unsigned int count = 0;
12993 for (unsigned int n : GeometryInfo<dim>::face_indices())
12994 {
12995 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
12996 cell->neighbor(n);
12997 if (neighbor.state() == IteratorState::valid)
12998 {
12999 ++n_neighbors;
13000 if (face_will_be_refined_by_neighbor(cell, n))
13001 ++count;
13002 }
13003 }
13004 // clear coarsen flags if either all existing neighbors will be
13005 // refined or all but one will be and the cell is in the interior
13006 // of the domain
13007 if (count == n_neighbors ||
13008 (count >= n_neighbors - 1 &&
13009 n_neighbors == GeometryInfo<dim>::faces_per_cell))
13010 {
13011 for (unsigned int c = 0; c < cell->n_children(); ++c)
13012 cell->child(c)->clear_coarsen_flag();
13013
13014 for (const unsigned int face : GeometryInfo<dim>::face_indices())
13015 if (!cell->at_boundary(face) &&
13016 (!cell->neighbor(face)->is_active()) &&
13017 (cell_will_be_coarsened(cell->neighbor(face))))
13018 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
13019 cell->neighbor(face));
13020 }
13021 }
13022
13023
13024 // see if the current cell needs to be refined to avoid unrefined
13025 // islands.
13026 //
13027 // there are sometimes chains of cells that induce refinement of
13028 // each other. to avoid running the loop in
13029 // prepare_coarsening_and_refinement over and over again for each
13030 // one of them, at least for the isotropic refinement case we seek
13031 // to flag neighboring elements as well as necessary. this takes
13032 // care of (slightly pathological) cases like
13033 // deal.II/mesh_smoothing_03
13034 template <int dim, int spacedim>
13035 void
possibly_refine_unrefined_island(const typename Triangulation<dim,spacedim>::cell_iterator & cell,const bool allow_anisotropic_smoothing)13036 possibly_refine_unrefined_island(
13037 const typename Triangulation<dim, spacedim>::cell_iterator &cell,
13038 const bool allow_anisotropic_smoothing)
13039 {
13040 Assert(cell->is_active(), ExcInternalError());
13041 Assert(cell->refine_flag_set() == false, ExcInternalError());
13042
13043
13044 // now we provide two algorithms. the first one is the standard
13045 // one, coming from the time, where only isotropic refinement was
13046 // possible. it simply counts the neighbors that are or will be
13047 // refined and compares to the number of other ones. the second
13048 // one does this check independently for each direction: if all
13049 // neighbors in one direction (normally two, at the boundary only
13050 // one) are refined, the current cell is flagged to be refined in
13051 // an according direction.
13052
13053 if (allow_anisotropic_smoothing == false)
13054 {
13055 // use first algorithm
13056 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
13057 for (const unsigned int face : GeometryInfo<dim>::face_indices())
13058 if (!cell->at_boundary(face))
13059 {
13060 if (face_will_be_refined_by_neighbor(cell, face))
13061 ++refined_neighbors;
13062 else
13063 ++unrefined_neighbors;
13064 }
13065
13066 if (unrefined_neighbors < refined_neighbors)
13067 {
13068 cell->clear_coarsen_flag();
13069 cell->set_refine_flag();
13070
13071 // ok, so now we have flagged this cell. if we know that
13072 // there were any unrefined neighbors at all, see if any
13073 // of those will have to be refined as well
13074 if (unrefined_neighbors > 0)
13075 for (const unsigned int face : GeometryInfo<dim>::face_indices())
13076 if (!cell->at_boundary(face) &&
13077 (face_will_be_refined_by_neighbor(cell, face) == false) &&
13078 (cell->neighbor(face)->has_children() == false) &&
13079 (cell->neighbor(face)->refine_flag_set() == false))
13080 possibly_refine_unrefined_island<dim, spacedim>(
13081 cell->neighbor(face), allow_anisotropic_smoothing);
13082 }
13083 }
13084 else
13085 {
13086 // variable to store the cell refine case needed to fulfill
13087 // all smoothing requirements
13088 RefinementCase<dim> smoothing_cell_refinement_case =
13089 RefinementCase<dim>::no_refinement;
13090
13091 // use second algorithm, do the check individually for each
13092 // direction
13093 for (unsigned int face_pair = 0;
13094 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
13095 ++face_pair)
13096 {
13097 // variable to store the cell refine case needed to refine
13098 // at the current face pair in the same way as the
13099 // neighbors do...
13100 RefinementCase<dim> directional_cell_refinement_case =
13101 RefinementCase<dim>::isotropic_refinement;
13102
13103 for (unsigned int face_index = 0; face_index < 2; ++face_index)
13104 {
13105 unsigned int face = 2 * face_pair + face_index;
13106 // variable to store the refine case (to come) of the
13107 // face under consideration
13108 RefinementCase<dim - 1> expected_face_ref_case =
13109 RefinementCase<dim - 1>::no_refinement;
13110
13111 if (cell->neighbor(face).state() == IteratorState::valid)
13112 face_will_be_refined_by_neighbor<dim, spacedim>(
13113 cell, face, expected_face_ref_case);
13114 // now extract which refine case would be necessary to
13115 // achieve the same face refinement. set the
13116 // intersection with other requirements for the same
13117 // direction.
13118
13119 // note: using the intersection is not an obvious
13120 // decision, we could also argue that it is more
13121 // natural to use the union. however, intersection is
13122 // the less aggressive tactic and favours a smaller
13123 // number of refined cells over an intensive
13124 // smoothing. this way we try not to lose too much of
13125 // the effort we put in anisotropic refinement
13126 // indicators due to overly aggressive smoothing...
13127 directional_cell_refinement_case =
13128 (directional_cell_refinement_case &
13129 GeometryInfo<dim>::
13130 min_cell_refinement_case_for_face_refinement(
13131 expected_face_ref_case,
13132 face,
13133 cell->face_orientation(face),
13134 cell->face_flip(face),
13135 cell->face_rotation(face)));
13136 } // for both face indices
13137 // if both requirements sum up to something useful, add
13138 // this to the refine case for smoothing. note: if
13139 // directional_cell_refinement_case is isotropic still,
13140 // then something went wrong...
13141 Assert(directional_cell_refinement_case <
13142 RefinementCase<dim>::isotropic_refinement,
13143 ExcInternalError());
13144 smoothing_cell_refinement_case =
13145 smoothing_cell_refinement_case | directional_cell_refinement_case;
13146 } // for all face_pairs
13147 // no we collected contributions from all directions. combine
13148 // the new flags with the existing refine case, but only if
13149 // smoothing is required
13150 if (smoothing_cell_refinement_case)
13151 {
13152 cell->clear_coarsen_flag();
13153 cell->set_refine_flag(cell->refine_flag_set() |
13154 smoothing_cell_refinement_case);
13155 }
13156 }
13157 }
13158 } // namespace
13159
13160
13161 template <int dim, int spacedim>
13162 bool
prepare_coarsening_and_refinement()13163 Triangulation<dim, spacedim>::prepare_coarsening_and_refinement()
13164 {
13165 // save the flags to determine whether something was changed in the
13166 // course of this function
13167 std::vector<bool> flags_before[2];
13168 save_coarsen_flags(flags_before[0]);
13169 save_refine_flags(flags_before[1]);
13170
13171 // save the flags at the outset of each loop. we do so in order to
13172 // find out whether something was changed in the present loop, in
13173 // which case we would have to re-run the loop. the other
13174 // possibility to find this out would be to set a flag
13175 // @p{something_changed} to true each time we change something.
13176 // however, sometimes one change in one of the parts of the loop is
13177 // undone by another one, so we might end up in an endless loop. we
13178 // could be tempted to break this loop at an arbitrary number of
13179 // runs, but that would not be a clean solution, since we would
13180 // either have to 1/ break the loop too early, in which case the
13181 // promise that a second call to this function immediately after the
13182 // first one does not change anything, would be broken, or 2/ we do
13183 // as many loops as there are levels. we know that information is
13184 // transported over one level in each run of the loop, so this is
13185 // enough. Unfortunately, each loop is rather expensive, so we chose
13186 // the way presented here
13187 std::vector<bool> flags_before_loop[2] = {flags_before[0], flags_before[1]};
13188
13189 // now for what is done in each loop: we have to fulfill several
13190 // tasks at the same time, namely several mesh smoothing algorithms
13191 // and mesh regularization, by which we mean that the next mesh
13192 // fulfills several requirements such as no double refinement at
13193 // each face or line, etc.
13194 //
13195 // since doing these things at once seems almost impossible (in the
13196 // first year of this library, they were done in two functions, one
13197 // for refinement and one for coarsening, and most things within
13198 // these were done at once, so the code was rather impossible to
13199 // join into this, only, function), we do them one after each
13200 // other. the order in which we do them is such that the important
13201 // tasks, namely regularization, are done last and the least
13202 // important things are done the first. the following order is
13203 // chosen:
13204 //
13205 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
13206 // coarsen flags on level 1 to avoid level 0 cells being created
13207 // by coarsening. As coarsen flags will never be added, this can
13208 // be done once and for all before the actual loop starts.
13209 //
13210 // 1/ do not coarsen a cell if 'most of the neighbors' will be
13211 // refined after the step. This is to prevent occurrence of
13212 // unrefined islands.
13213 //
13214 // 2/ eliminate refined islands in the interior and at the
13215 // boundary. since they don't do much harm besides increasing the
13216 // number of degrees of freedom, doing this has a rather low
13217 // priority.
13218 //
13219 // 3/ limit the level difference of neighboring cells at each
13220 // vertex.
13221 //
13222 // 4/ eliminate unrefined islands. this has higher priority since
13223 // this diminishes the approximation properties not only of the
13224 // unrefined island, but also of the surrounding patch.
13225 //
13226 // 5/ ensure patch level 1. Then the triangulation consists of
13227 // patches, i.e. of cells that are refined once. It follows that
13228 // if at least one of the children of a cell is or will be
13229 // refined than all children need to be refined. This step only
13230 // sets refinement flags and does not set coarsening flags. If
13231 // the patch_level_1 flag is set, then
13232 // eliminate_unrefined_islands, eliminate_refined_inner_islands
13233 // and eliminate_refined_boundary_islands will be fulfilled
13234 // automatically and do not need to be enforced separately.
13235 //
13236 // 6/ take care of the requirement that no double refinement is done
13237 // at each face
13238 //
13239 // 7/ take care that no double refinement is done at each line in 3d
13240 // or higher dimensions.
13241 //
13242 // 8/ make sure that all children of each cell are either flagged
13243 // for coarsening or none of the children is
13244 //
13245 // For some of these steps, it is known that they interact. Namely,
13246 // it is not possible to guarantee that after step 6 another step 5
13247 // would have no effect; the same holds for the opposite order and
13248 // also when taking into account step 7. however, it is important to
13249 // guarantee that step five or six do not undo something that step 5
13250 // did, and step 7 not something of step 6, otherwise the
13251 // requirements will not be satisfied even if the loop
13252 // terminates. this is accomplished by the fact that steps 5 and 6
13253 // only *add* refinement flags and delete coarsening flags
13254 // (therefore, step 6 can't undo something that step 4 already did),
13255 // and step 7 only deletes coarsening flags, never adds some. step 7
13256 // needs also take care that it won't tag cells for refinement for
13257 // which some neighbors are more refined or will be refined.
13258
13259 //////////////////////////////////////
13260 // STEP 0:
13261 // Only if coarsest_level_1 or patch_level_1 is set: clear all
13262 // coarsen flags on level 1 to avoid level 0 cells being created
13263 // by coarsening.
13264 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
13265 n_levels() >= 2)
13266 {
13267 for (const auto &cell : active_cell_iterators_on_level(1))
13268 cell->clear_coarsen_flag();
13269 }
13270
13271 bool mesh_changed_in_this_loop = false;
13272 do
13273 {
13274 //////////////////////////////////////
13275 // STEP 1:
13276 // do not coarsen a cell if 'most of the neighbors' will be
13277 // refined after the step. This is to prevent the occurrence
13278 // of unrefined islands. If patch_level_1 is set, this will
13279 // be automatically fulfilled.
13280 if (smooth_grid & do_not_produce_unrefined_islands &&
13281 !(smooth_grid & patch_level_1))
13282 {
13283 for (const auto &cell : cell_iterators())
13284 {
13285 // only do something if this
13286 // cell will be coarsened
13287 if (!cell->is_active() && cell_will_be_coarsened(cell))
13288 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
13289 }
13290 }
13291
13292
13293 //////////////////////////////////////
13294 // STEP 2:
13295 // eliminate refined islands in the interior and at the
13296 // boundary. since they don't do much harm besides increasing
13297 // the number of degrees of freedom, doing this has a rather
13298 // low priority. If patch_level_1 is set, this will be
13299 // automatically fulfilled.
13300 //
13301 // there is one corner case to consider: if this is a
13302 // distributed triangulation, there may be refined islands on
13303 // the boundary of which we own only part (e.g. a single cell
13304 // in the corner of a domain). the rest of the island is
13305 // ghost cells and it *looks* like the area around it
13306 // (artificial cells) are coarser but this is only because
13307 // they may actually be equally fine on other
13308 // processors. it's hard to detect this case but we can do
13309 // the following: only set coarsen flags to remove this
13310 // refined island if all cells we want to set flags on are
13311 // locally owned
13312 if (smooth_grid & (eliminate_refined_inner_islands |
13313 eliminate_refined_boundary_islands) &&
13314 !(smooth_grid & patch_level_1))
13315 {
13316 for (const auto &cell : cell_iterators())
13317 if (!cell->is_active() ||
13318 (cell->is_active() && cell->refine_flag_set() &&
13319 cell->is_locally_owned()))
13320 {
13321 // check whether all children are active, i.e. not
13322 // refined themselves. This is a precondition that the
13323 // children may be coarsened away. If the cell is only
13324 // flagged for refinement, then all future children
13325 // will be active
13326 bool all_children_active = true;
13327 if (!cell->is_active())
13328 for (unsigned int c = 0; c < cell->n_children(); ++c)
13329 if (!cell->child(c)->is_active() ||
13330 cell->child(c)->is_ghost() ||
13331 cell->child(c)->is_artificial())
13332 {
13333 all_children_active = false;
13334 break;
13335 }
13336
13337 if (all_children_active)
13338 {
13339 // count number of refined and unrefined neighbors
13340 // of cell. neighbors on lower levels are counted
13341 // as unrefined since they can only get to the
13342 // same level as this cell by the next refinement
13343 // cycle
13344 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
13345
13346 // Keep track if this cell is at a periodic
13347 // boundary or not. TODO: We do not currently run
13348 // the algorithm for inner islands at a periodic
13349 // boundary (remains to be implemented), but we
13350 // also don't want to consider them
13351 // boundary_island cells as this can interfere
13352 // with 2:1 refinement across periodic faces.
13353 // Instead: just ignore those cells for this
13354 // smoothing operation below.
13355 bool at_periodic_boundary = false;
13356
13357 for (const unsigned int n :
13358 GeometryInfo<dim>::face_indices())
13359 {
13360 const cell_iterator neighbor = cell->neighbor(n);
13361 if (neighbor.state() == IteratorState::valid)
13362 {
13363 ++total_neighbors;
13364
13365 if (!face_will_be_refined_by_neighbor(cell, n))
13366 ++unrefined_neighbors;
13367 }
13368 else if (cell->has_periodic_neighbor(n))
13369 {
13370 ++total_neighbors;
13371 at_periodic_boundary = true;
13372 }
13373 }
13374
13375 // if all neighbors unrefined: mark this cell for
13376 // coarsening or don't refine if marked for that
13377 //
13378 // also do the distinction between the two
13379 // versions of the eliminate_refined_*_islands
13380 // flag
13381 //
13382 // the last check is whether there are any
13383 // neighbors at all. if not so, then we are (e.g.)
13384 // on the coarsest grid with one cell, for which,
13385 // of course, we do not remove the refine flag.
13386 if ((unrefined_neighbors == total_neighbors) &&
13387 ((!cell->at_boundary() &&
13388 (smooth_grid & eliminate_refined_inner_islands)) ||
13389 (cell->at_boundary() && !at_periodic_boundary &&
13390 (smooth_grid &
13391 eliminate_refined_boundary_islands))) &&
13392 (total_neighbors != 0))
13393 {
13394 if (!cell->is_active())
13395 for (unsigned int c = 0; c < cell->n_children(); ++c)
13396 {
13397 cell->child(c)->clear_refine_flag();
13398 cell->child(c)->set_coarsen_flag();
13399 }
13400 else
13401 cell->clear_refine_flag();
13402 }
13403 }
13404 }
13405 }
13406
13407 //////////////////////////////////////
13408 // STEP 3:
13409 // limit the level difference of neighboring cells at each
13410 // vertex.
13411 //
13412 // in case of anisotropic refinement this does not make
13413 // sense. as soon as one cell is anisotropically refined, an
13414 // Assertion is thrown. therefore we can ignore this problem
13415 // later on
13416 if (smooth_grid & limit_level_difference_at_vertices)
13417 {
13418 Assert(!anisotropic_refinement,
13419 ExcMessage("In case of anisotropic refinement the "
13420 "limit_level_difference_at_vertices flag for "
13421 "mesh smoothing must not be set!"));
13422
13423 // store highest level one of the cells adjacent to a vertex
13424 // belongs to
13425 std::vector<int> vertex_level(vertices.size(), 0);
13426 for (const auto &cell : active_cell_iterators())
13427 {
13428 if (cell->refine_flag_set())
13429 for (const unsigned int vertex :
13430 GeometryInfo<dim>::vertex_indices())
13431 vertex_level[cell->vertex_index(vertex)] =
13432 std::max(vertex_level[cell->vertex_index(vertex)],
13433 cell->level() + 1);
13434 else if (!cell->coarsen_flag_set())
13435 for (const unsigned int vertex :
13436 GeometryInfo<dim>::vertex_indices())
13437 vertex_level[cell->vertex_index(vertex)] =
13438 std::max(vertex_level[cell->vertex_index(vertex)],
13439 cell->level());
13440 else
13441 {
13442 // if coarsen flag is set then tentatively assume
13443 // that the cell will be coarsened. this isn't
13444 // always true (the coarsen flag could be removed
13445 // again) and so we may make an error here
13446 Assert(cell->coarsen_flag_set(), ExcInternalError());
13447 for (const unsigned int vertex :
13448 GeometryInfo<dim>::vertex_indices())
13449 vertex_level[cell->vertex_index(vertex)] =
13450 std::max(vertex_level[cell->vertex_index(vertex)],
13451 cell->level() - 1);
13452 }
13453 }
13454
13455
13456 // loop over all cells in reverse order. do so because we
13457 // can then update the vertex levels on the adjacent
13458 // vertices and maybe already flag additional cells in this
13459 // loop
13460 //
13461 // note that not only may we have to add additional
13462 // refinement flags, but we will also have to remove
13463 // coarsening flags on cells adjacent to vertices that will
13464 // see refinement
13465 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
13466 if (cell->refine_flag_set() == false)
13467 {
13468 for (const unsigned int vertex :
13469 GeometryInfo<dim>::vertex_indices())
13470 if (vertex_level[cell->vertex_index(vertex)] >=
13471 cell->level() + 1)
13472 {
13473 // remove coarsen flag...
13474 cell->clear_coarsen_flag();
13475
13476 // ...and if necessary also refine the current
13477 // cell, at the same time updating the level
13478 // information about vertices
13479 if (vertex_level[cell->vertex_index(vertex)] >
13480 cell->level() + 1)
13481 {
13482 cell->set_refine_flag();
13483
13484 for (const unsigned int v :
13485 GeometryInfo<dim>::vertex_indices())
13486 vertex_level[cell->vertex_index(v)] =
13487 std::max(vertex_level[cell->vertex_index(v)],
13488 cell->level() + 1);
13489 }
13490
13491 // continue and see whether we may, for example,
13492 // go into the inner'if'
13493 // above based on a
13494 // different vertex
13495 }
13496 }
13497 }
13498
13499 /////////////////////////////////////
13500 // STEP 4:
13501 // eliminate unrefined islands. this has higher priority
13502 // since this diminishes the approximation properties not
13503 // only of the unrefined island, but also of the surrounding
13504 // patch.
13505 //
13506 // do the loop from finest to coarsest cells since we may
13507 // trigger a cascade by marking cells for refinement which
13508 // may trigger more cells further down below
13509 if (smooth_grid & eliminate_unrefined_islands)
13510 {
13511 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
13512 // only do something if cell is not already flagged for
13513 // (isotropic) refinement
13514 if (cell->refine_flag_set() !=
13515 RefinementCase<dim>::isotropic_refinement)
13516 possibly_refine_unrefined_island<dim, spacedim>(
13517 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
13518 }
13519
13520 /////////////////////////////////
13521 // STEP 5:
13522 // ensure patch level 1.
13523 //
13524 // Introduce some terminology:
13525 // - a cell that is refined
13526 // once is a patch of
13527 // level 1 simply called patch.
13528 // - a cell that is globally
13529 // refined twice is called
13530 // a patch of level 2.
13531 // - patch level n says that
13532 // the triangulation consists
13533 // of patches of level n.
13534 // This makes sense only
13535 // if the grid is already at
13536 // least n times globally
13537 // refined.
13538 //
13539 // E.g. from patch level 1 follows: if at least one of the
13540 // children of a cell is or will be refined than enforce all
13541 // children to be refined.
13542
13543 // This step 4 only sets refinement flags and does not set
13544 // coarsening flags.
13545 if (smooth_grid & patch_level_1)
13546 {
13547 // An important assumption (A) is that before calling this
13548 // function the grid was already of patch level 1.
13549
13550 // loop over all cells whose children are all active. (By
13551 // assumption (A) either all or none of the children are
13552 // active). If the refine flag of at least one of the
13553 // children is set then set_refine_flag and
13554 // clear_coarsen_flag of all children.
13555 for (const auto &cell : cell_iterators())
13556 if (!cell->is_active())
13557 {
13558 // ensure the invariant. we can then check whether all
13559 // of its children are further refined or not by
13560 // simply looking at the first child
13561 Assert(cell_is_patch_level_1(cell), ExcInternalError());
13562 if (cell->child(0)->has_children() == true)
13563 continue;
13564
13565 // cell is found to be a patch. combine the refine
13566 // cases of all children
13567 RefinementCase<dim> combined_ref_case =
13568 RefinementCase<dim>::no_refinement;
13569 for (unsigned int i = 0; i < cell->n_children(); ++i)
13570 combined_ref_case =
13571 combined_ref_case | cell->child(i)->refine_flag_set();
13572 if (combined_ref_case != RefinementCase<dim>::no_refinement)
13573 for (unsigned int i = 0; i < cell->n_children(); ++i)
13574 {
13575 cell_iterator child = cell->child(i);
13576
13577 child->clear_coarsen_flag();
13578 child->set_refine_flag(combined_ref_case);
13579 }
13580 }
13581
13582 // The code above dealt with the case where we may get a
13583 // non-patch_level_1 mesh from refinement. Now also deal
13584 // with the case where we could get such a mesh by
13585 // coarsening. Coarsen the children (and remove the
13586 // grandchildren) only if all cell->grandchild(i)
13587 // ->coarsen_flag_set() are set.
13588 //
13589 // for a case where this is a bit tricky, take a look at the
13590 // mesh_smoothing_0[12] testcases
13591 for (const auto &cell : cell_iterators())
13592 {
13593 // check if this cell has active grandchildren. note
13594 // that we know that it is patch_level_1, i.e. if one of
13595 // its children is active then so are all, and it isn't
13596 // going to have any grandchildren at all:
13597 if (cell->is_active() || cell->child(0)->is_active())
13598 continue;
13599
13600 // cell is not active, and so are none of its
13601 // children. check the grandchildren. note that the
13602 // children are also patch_level_1, and so we only ever
13603 // need to check their first child
13604 const unsigned int n_children = cell->n_children();
13605 bool has_active_grandchildren = false;
13606
13607 for (unsigned int i = 0; i < n_children; ++i)
13608 if (cell->child(i)->child(0)->is_active())
13609 {
13610 has_active_grandchildren = true;
13611 break;
13612 }
13613
13614 if (has_active_grandchildren == false)
13615 continue;
13616
13617
13618 // ok, there are active grandchildren. see if either all
13619 // or none of them are flagged for coarsening
13620 unsigned int n_grandchildren = 0;
13621
13622 // count all coarsen flags of the grandchildren.
13623 unsigned int n_coarsen_flags = 0;
13624
13625 // cell is not a patch (of level 1) as it has a
13626 // grandchild. Is cell a patch of level 2?? Therefore:
13627 // find out whether all cell->child(i) are patches
13628 for (unsigned int c = 0; c < n_children; ++c)
13629 {
13630 // get at the child. by assumption (A), and the
13631 // check by which we got here, the child is not
13632 // active
13633 cell_iterator child = cell->child(c);
13634
13635 const unsigned int nn_children = child->n_children();
13636 n_grandchildren += nn_children;
13637
13638 // if child is found to be a patch of active cells
13639 // itself, then add up how many of its children are
13640 // supposed to be coarsened
13641 if (child->child(0)->is_active())
13642 for (unsigned int cc = 0; cc < nn_children; ++cc)
13643 if (child->child(cc)->coarsen_flag_set())
13644 ++n_coarsen_flags;
13645 }
13646
13647 // if not all grandchildren are supposed to be coarsened
13648 // (e.g. because some simply don't have the flag set, or
13649 // because they are not active and therefore cannot
13650 // carry the flag), then remove the coarsen flag from
13651 // all of the active grandchildren. note that there may
13652 // be coarsen flags on the grandgrandchildren -- we
13653 // don't clear them here, but we'll get to them in later
13654 // iterations if necessary
13655 //
13656 // there is nothing we have to do if no coarsen flags
13657 // have been set at all
13658 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
13659 for (unsigned int c = 0; c < n_children; ++c)
13660 {
13661 const cell_iterator child = cell->child(c);
13662 if (child->child(0)->is_active())
13663 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
13664 child->child(cc)->clear_coarsen_flag();
13665 }
13666 }
13667 }
13668
13669 //////////////////////////////////
13670 //
13671 // at the boundary we could end up with cells with negative
13672 // volume or at least with a part, that is negative, if the
13673 // cell is refined anisotropically. we have to check, whether
13674 // that can happen
13675 internal::TriangulationImplementation::Implementation::
13676 prevent_distorted_boundary_cells(*this);
13677
13678 /////////////////////////////////
13679 // STEP 6:
13680 // take care of the requirement that no
13681 // double refinement is done at each face
13682 //
13683 // in case of anisotropic refinement it is only likely, but
13684 // not sure, that the cells, which are more refined along a
13685 // certain face common to two cells are on a higher
13686 // level. therefore we cannot be sure, that the requirement
13687 // of no double refinement is fulfilled after a single pass
13688 // of the following actions. We could just wait for the next
13689 // global loop. when this function terminates, the
13690 // requirement will be fulfilled. However, it might be faster
13691 // to insert an inner loop here.
13692 bool changed = true;
13693 while (changed)
13694 {
13695 changed = false;
13696 active_cell_iterator cell = last_active(), endc = end();
13697
13698 for (; cell != endc; --cell)
13699 if (cell->refine_flag_set())
13700 {
13701 // loop over neighbors of cell
13702 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13703 {
13704 // only do something if the face is not at the
13705 // boundary and if the face will be refined with
13706 // the RefineCase currently flagged for
13707 const bool has_periodic_neighbor =
13708 cell->has_periodic_neighbor(i);
13709 const bool has_neighbor_or_periodic_neighbor =
13710 !cell->at_boundary(i) || has_periodic_neighbor;
13711 if (has_neighbor_or_periodic_neighbor &&
13712 GeometryInfo<dim>::face_refinement_case(
13713 cell->refine_flag_set(), i) !=
13714 RefinementCase<dim - 1>::no_refinement)
13715 {
13716 // 1) if the neighbor has children: nothing to
13717 // worry about. 2) if the neighbor is active
13718 // and a coarser one, ensure, that its
13719 // refine_flag is set 3) if the neighbor is
13720 // active and as refined along the face as our
13721 // current cell, make sure, that no
13722 // coarsen_flag is set. if we remove the
13723 // coarsen flag of our neighbor,
13724 // fix_coarsen_flags() makes sure, that the
13725 // mother cell will not be coarsened
13726 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
13727 {
13728 if ((!has_periodic_neighbor &&
13729 cell->neighbor_is_coarser(i)) ||
13730 (has_periodic_neighbor &&
13731 cell->periodic_neighbor_is_coarser(i)))
13732 {
13733 if (cell->neighbor_or_periodic_neighbor(i)
13734 ->coarsen_flag_set())
13735 cell->neighbor_or_periodic_neighbor(i)
13736 ->clear_coarsen_flag();
13737 // we'll set the refine flag for this
13738 // neighbor below. we note, that we
13739 // have changed something by setting
13740 // the changed flag to true. We do not
13741 // need to do so, if we just removed
13742 // the coarsen flag, as the changed
13743 // flag only indicates the need to
13744 // re-run the inner loop. however, we
13745 // only loop over cells flagged for
13746 // refinement here, so nothing to
13747 // worry about if we remove coarsen
13748 // flags
13749
13750 if (dim == 2)
13751 {
13752 if (smooth_grid &
13753 allow_anisotropic_smoothing)
13754 changed =
13755 has_periodic_neighbor ?
13756 cell->periodic_neighbor(i)
13757 ->flag_for_face_refinement(
13758 cell
13759 ->periodic_neighbor_of_coarser_periodic_neighbor(
13760 i)
13761 .first,
13762 RefinementCase<dim - 1>::cut_x) :
13763 cell->neighbor(i)
13764 ->flag_for_face_refinement(
13765 cell
13766 ->neighbor_of_coarser_neighbor(
13767 i)
13768 .first,
13769 RefinementCase<dim - 1>::cut_x);
13770 else
13771 {
13772 if (!cell
13773 ->neighbor_or_periodic_neighbor(
13774 i)
13775 ->refine_flag_set())
13776 changed = true;
13777 cell->neighbor_or_periodic_neighbor(i)
13778 ->set_refine_flag();
13779 }
13780 }
13781 else // i.e. if (dim==3)
13782 {
13783 // ugly situations might arise here,
13784 // consider the following situation, which
13785 // shows neighboring cells at the common
13786 // face, where the upper right element is
13787 // coarser at the given face. Now the upper
13788 // child element of the lower left wants to
13789 // refine according to cut_z, such that
13790 // there is a 'horizontal' refinement of the
13791 // face marked with #####
13792 //
13793 // / /
13794 // / /
13795 // *---------------*
13796 // | |
13797 // | |
13798 // | |
13799 // | |
13800 // | |
13801 // | | /
13802 // | |/
13803 // *---------------*
13804 //
13805 //
13806 // *---------------*
13807 // /| /|
13808 // / | ##### / |
13809 // | |
13810 // *---------------*
13811 // /| /|
13812 // / | / |
13813 // | |
13814 // *---------------*
13815 // / /
13816 // / /
13817 //
13818 // this introduces too many hanging nodes
13819 // and the neighboring (coarser) cell (upper
13820 // right) has to be refined. If it is only
13821 // refined according to cut_z, then
13822 // everything is ok:
13823 //
13824 // / /
13825 // / /
13826 // *---------------*
13827 // | |
13828 // | | /
13829 // | |/
13830 // *---------------*
13831 // | |
13832 // | | /
13833 // | |/
13834 // *---------------*
13835 //
13836 //
13837 // *---------------*
13838 // /| /|
13839 // / *---------------*
13840 // /| /|
13841 // *---------------*
13842 // /| /|
13843 // / | / |
13844 // | |
13845 // *---------------*
13846 // / /
13847 // / /
13848 //
13849 // if however the cell wants to refine
13850 // itself in an other way, or if we disallow
13851 // anisotropic smoothing, then simply
13852 // refining the neighbor isotropically is
13853 // not going to work, since this introduces
13854 // a refinement of face ##### with both
13855 // cut_x and cut_y, which is not possible:
13856 //
13857 // / / /
13858 // / / /
13859 // *-------*-------*
13860 // | | |
13861 // | | | /
13862 // | | |/
13863 // *-------*-------*
13864 // | | |
13865 // | | | /
13866 // | | |/
13867 // *-------*-------*
13868 //
13869 //
13870 // *---------------*
13871 // /| /|
13872 // / *---------------*
13873 // /| /|
13874 // *---------------*
13875 // /| /|
13876 // / | / |
13877 // | |
13878 // *---------------*
13879 // / /
13880 // / /
13881 //
13882 // thus, in this case we also need to refine
13883 // our current cell in the new direction:
13884 //
13885 // / / /
13886 // / / /
13887 // *-------*-------*
13888 // | | |
13889 // | | | /
13890 // | | |/
13891 // *-------*-------*
13892 // | | |
13893 // | | | /
13894 // | | |/
13895 // *-------*-------*
13896 //
13897 //
13898 // *-------*-------*
13899 // /| /| /|
13900 // / *-------*-------*
13901 // /| /| /|
13902 // *-------*-------*
13903 // /| / /|
13904 // / | / |
13905 // | |
13906 // *---------------*
13907 // / /
13908 // / /
13909
13910 std::pair<unsigned int, unsigned int>
13911 nb_indices =
13912 has_periodic_neighbor ?
13913 cell
13914 ->periodic_neighbor_of_coarser_periodic_neighbor(
13915 i) :
13916 cell->neighbor_of_coarser_neighbor(i);
13917 unsigned int refined_along_x = 0,
13918 refined_along_y = 0,
13919 to_be_refined_along_x = 0,
13920 to_be_refined_along_y = 0;
13921
13922 const int this_face_index =
13923 cell->face_index(i);
13924
13925 // step 1: detect, along which axis the face
13926 // is currently refined
13927
13928 // first, we need an iterator pointing to
13929 // the parent face. This requires a slight
13930 // detour in case the neighbor is behind a
13931 // periodic face.
13932 const auto parent_face = [&]() {
13933 if (has_periodic_neighbor)
13934 {
13935 const auto neighbor =
13936 cell->periodic_neighbor(i);
13937 const auto parent_face_no =
13938 neighbor
13939 ->periodic_neighbor_of_periodic_neighbor(
13940 nb_indices.first);
13941 auto parent =
13942 neighbor->periodic_neighbor(
13943 nb_indices.first);
13944 return parent->face(parent_face_no);
13945 }
13946 else
13947 return cell->neighbor(i)->face(
13948 nb_indices.first);
13949 }();
13950
13951 if ((this_face_index ==
13952 parent_face->child_index(0)) ||
13953 (this_face_index ==
13954 parent_face->child_index(1)))
13955 {
13956 // this might be an
13957 // anisotropic child. get the
13958 // face refine case of the
13959 // neighbors face and count
13960 // refinements in x and y
13961 // direction.
13962 RefinementCase<dim - 1> frc =
13963 parent_face->refinement_case();
13964 if (frc & RefinementCase<dim>::cut_x)
13965 ++refined_along_x;
13966 if (frc & RefinementCase<dim>::cut_y)
13967 ++refined_along_y;
13968 }
13969 else
13970 // this has to be an isotropic
13971 // child
13972 {
13973 ++refined_along_x;
13974 ++refined_along_y;
13975 }
13976 // step 2: detect, along which axis the face
13977 // has to be refined given the current
13978 // refine flag
13979 RefinementCase<dim - 1> flagged_frc =
13980 GeometryInfo<dim>::face_refinement_case(
13981 cell->refine_flag_set(),
13982 i,
13983 cell->face_orientation(i),
13984 cell->face_flip(i),
13985 cell->face_rotation(i));
13986 if (flagged_frc &
13987 RefinementCase<dim>::cut_x)
13988 ++to_be_refined_along_x;
13989 if (flagged_frc &
13990 RefinementCase<dim>::cut_y)
13991 ++to_be_refined_along_y;
13992
13993 // step 3: set the refine flag of the
13994 // (coarser and active) neighbor.
13995 if ((smooth_grid &
13996 allow_anisotropic_smoothing) ||
13997 cell->neighbor_or_periodic_neighbor(i)
13998 ->refine_flag_set())
13999 {
14000 if (refined_along_x +
14001 to_be_refined_along_x >
14002 1)
14003 changed |=
14004 cell
14005 ->neighbor_or_periodic_neighbor(i)
14006 ->flag_for_face_refinement(
14007 nb_indices.first,
14008 RefinementCase<dim -
14009 1>::cut_axis(0));
14010 if (refined_along_y +
14011 to_be_refined_along_y >
14012 1)
14013 changed |=
14014 cell
14015 ->neighbor_or_periodic_neighbor(i)
14016 ->flag_for_face_refinement(
14017 nb_indices.first,
14018 RefinementCase<dim -
14019 1>::cut_axis(1));
14020 }
14021 else
14022 {
14023 if (cell
14024 ->neighbor_or_periodic_neighbor(i)
14025 ->refine_flag_set() !=
14026 RefinementCase<
14027 dim>::isotropic_refinement)
14028 changed = true;
14029 cell->neighbor_or_periodic_neighbor(i)
14030 ->set_refine_flag();
14031 }
14032
14033 // step 4: if necessary (see above) add to
14034 // the refine flag of the current cell
14035 cell_iterator nb =
14036 cell->neighbor_or_periodic_neighbor(i);
14037 RefinementCase<dim - 1> nb_frc =
14038 GeometryInfo<dim>::face_refinement_case(
14039 nb->refine_flag_set(),
14040 nb_indices.first,
14041 nb->face_orientation(nb_indices.first),
14042 nb->face_flip(nb_indices.first),
14043 nb->face_rotation(nb_indices.first));
14044 if ((nb_frc & RefinementCase<dim>::cut_x) &&
14045 !(refined_along_x ||
14046 to_be_refined_along_x))
14047 changed |= cell->flag_for_face_refinement(
14048 i,
14049 RefinementCase<dim - 1>::cut_axis(0));
14050 if ((nb_frc & RefinementCase<dim>::cut_y) &&
14051 !(refined_along_y ||
14052 to_be_refined_along_y))
14053 changed |= cell->flag_for_face_refinement(
14054 i,
14055 RefinementCase<dim - 1>::cut_axis(1));
14056 }
14057 } // if neighbor is coarser
14058 else // -> now the neighbor is not coarser
14059 {
14060 cell->neighbor_or_periodic_neighbor(i)
14061 ->clear_coarsen_flag();
14062 const unsigned int nb_nb =
14063 has_periodic_neighbor ?
14064 cell
14065 ->periodic_neighbor_of_periodic_neighbor(
14066 i) :
14067 cell->neighbor_of_neighbor(i);
14068 const cell_iterator neighbor =
14069 cell->neighbor_or_periodic_neighbor(i);
14070 RefinementCase<dim - 1> face_ref_case =
14071 GeometryInfo<dim>::face_refinement_case(
14072 neighbor->refine_flag_set(),
14073 nb_nb,
14074 neighbor->face_orientation(nb_nb),
14075 neighbor->face_flip(nb_nb),
14076 neighbor->face_rotation(nb_nb));
14077 RefinementCase<dim - 1> needed_face_ref_case =
14078 GeometryInfo<dim>::face_refinement_case(
14079 cell->refine_flag_set(),
14080 i,
14081 cell->face_orientation(i),
14082 cell->face_flip(i),
14083 cell->face_rotation(i));
14084 // if the neighbor wants to refine the
14085 // face with cut_x and we want cut_y
14086 // or vice versa, we have to refine
14087 // isotropically at the given face
14088 if ((face_ref_case ==
14089 RefinementCase<dim>::cut_x &&
14090 needed_face_ref_case ==
14091 RefinementCase<dim>::cut_y) ||
14092 (face_ref_case ==
14093 RefinementCase<dim>::cut_y &&
14094 needed_face_ref_case ==
14095 RefinementCase<dim>::cut_x))
14096 {
14097 changed = cell->flag_for_face_refinement(
14098 i, face_ref_case);
14099 neighbor->flag_for_face_refinement(
14100 nb_nb, needed_face_ref_case);
14101 }
14102 }
14103 }
14104 else //-> the neighbor is not active
14105 {
14106 RefinementCase<dim - 1>
14107 face_ref_case = cell->face(i)->refinement_case(),
14108 needed_face_ref_case =
14109 GeometryInfo<dim>::face_refinement_case(
14110 cell->refine_flag_set(),
14111 i,
14112 cell->face_orientation(i),
14113 cell->face_flip(i),
14114 cell->face_rotation(i));
14115 // if the face is refined with cut_x and
14116 // we want cut_y or vice versa, we have to
14117 // refine isotropically at the given face
14118 if ((face_ref_case == RefinementCase<dim>::cut_x &&
14119 needed_face_ref_case ==
14120 RefinementCase<dim>::cut_y) ||
14121 (face_ref_case == RefinementCase<dim>::cut_y &&
14122 needed_face_ref_case ==
14123 RefinementCase<dim>::cut_x))
14124 changed =
14125 cell->flag_for_face_refinement(i,
14126 face_ref_case);
14127 }
14128 }
14129 }
14130 }
14131 }
14132
14133 //////////////////////////////////////
14134 // STEP 7:
14135 // take care that no double refinement
14136 // is done at each line in 3d or higher
14137 // dimensions.
14138 internal::TriangulationImplementation::Implementation::
14139 prepare_refinement_dim_dependent(*this);
14140
14141 //////////////////////////////////////
14142 // STEP 8:
14143 // make sure that all children of each
14144 // cell are either flagged for coarsening
14145 // or none of the children is
14146 fix_coarsen_flags();
14147 // get the refinement and coarsening
14148 // flags
14149 std::vector<bool> flags_after_loop[2];
14150 save_coarsen_flags(flags_after_loop[0]);
14151 save_refine_flags(flags_after_loop[1]);
14152
14153 // find out whether something was
14154 // changed in this loop
14155 mesh_changed_in_this_loop =
14156 ((flags_before_loop[0] != flags_after_loop[0]) ||
14157 (flags_before_loop[1] != flags_after_loop[1]));
14158
14159 // set the flags for the next loop
14160 // already
14161 flags_before_loop[0].swap(flags_after_loop[0]);
14162 flags_before_loop[1].swap(flags_after_loop[1]);
14163 }
14164 while (mesh_changed_in_this_loop);
14165
14166
14167 // find out whether something was really changed in this
14168 // function. Note that @p{flags_before_loop} represents the state
14169 // after the last loop, i.e. the present state
14170 return ((flags_before[0] != flags_before_loop[0]) ||
14171 (flags_before[1] != flags_before_loop[1]));
14172 }
14173
14174
14175
14176 template <int dim, int spacedim>
14177 void
write_bool_vector(const unsigned int magic_number1,const std::vector<bool> & v,const unsigned int magic_number2,std::ostream & out)14178 Triangulation<dim, spacedim>::write_bool_vector(
14179 const unsigned int magic_number1,
14180 const std::vector<bool> &v,
14181 const unsigned int magic_number2,
14182 std::ostream & out)
14183 {
14184 const unsigned int N = v.size();
14185 unsigned char * flags = new unsigned char[N / 8 + 1];
14186 for (unsigned int i = 0; i < N / 8 + 1; ++i)
14187 flags[i] = 0;
14188
14189 for (unsigned int position = 0; position < N; ++position)
14190 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
14191
14192 AssertThrow(out, ExcIO());
14193
14194 // format:
14195 // 0. magic number
14196 // 1. number of flags
14197 // 2. the flags
14198 // 3. magic number
14199 out << magic_number1 << ' ' << N << std::endl;
14200 for (unsigned int i = 0; i < N / 8 + 1; ++i)
14201 out << static_cast<unsigned int>(flags[i]) << ' ';
14202
14203 out << std::endl << magic_number2 << std::endl;
14204
14205 delete[] flags;
14206
14207 AssertThrow(out, ExcIO());
14208 }
14209
14210
14211 template <int dim, int spacedim>
14212 void
read_bool_vector(const unsigned int magic_number1,std::vector<bool> & v,const unsigned int magic_number2,std::istream & in)14213 Triangulation<dim, spacedim>::read_bool_vector(const unsigned int magic_number1,
14214 std::vector<bool> &v,
14215 const unsigned int magic_number2,
14216 std::istream & in)
14217 {
14218 AssertThrow(in, ExcIO());
14219
14220 unsigned int magic_number;
14221 in >> magic_number;
14222 AssertThrow(magic_number == magic_number1, ExcGridReadError());
14223
14224 unsigned int N;
14225 in >> N;
14226 v.resize(N);
14227
14228 unsigned char * flags = new unsigned char[N / 8 + 1];
14229 unsigned short int tmp;
14230 for (unsigned int i = 0; i < N / 8 + 1; ++i)
14231 {
14232 in >> tmp;
14233 flags[i] = tmp;
14234 }
14235
14236 for (unsigned int position = 0; position != N; ++position)
14237 v[position] = (flags[position / 8] & (1 << (position % 8)));
14238
14239 in >> magic_number;
14240 AssertThrow(magic_number == magic_number2, ExcGridReadError());
14241
14242 delete[] flags;
14243
14244 AssertThrow(in, ExcIO());
14245 }
14246
14247
14248
14249 template <int dim, int spacedim>
14250 std::size_t
memory_consumption() const14251 Triangulation<dim, spacedim>::memory_consumption() const
14252 {
14253 std::size_t mem = 0;
14254 mem += MemoryConsumption::memory_consumption(levels);
14255 for (const auto &level : levels)
14256 mem += MemoryConsumption::memory_consumption(*level);
14257 mem += MemoryConsumption::memory_consumption(vertices);
14258 mem += MemoryConsumption::memory_consumption(vertices_used);
14259 mem += sizeof(manifold);
14260 mem += sizeof(smooth_grid);
14261 mem += MemoryConsumption::memory_consumption(number_cache);
14262 mem += sizeof(faces);
14263 if (faces)
14264 mem += MemoryConsumption::memory_consumption(*faces);
14265
14266 return mem;
14267 }
14268
14269
14270 // explicit instantiations
14271 #include "tria.inst"
14272
14273 DEAL_II_NAMESPACE_CLOSE
14274