Reference documentation for deal.II version 9.5.0
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 1998 - 2023 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
20
25#include <deal.II/grid/tria.h>
30
31#include <algorithm>
32#include <array>
33#include <cmath>
34#include <functional>
35#include <list>
36#include <map>
37#include <memory>
38#include <numeric>
39
40
42
43
44namespace internal
45{
46 namespace TriangulationImplementation
47 {
49 : n_levels(0)
50 , n_lines(0)
51 , n_active_lines(0)
52 // all other fields are
53 // default constructed
54 {}
55
56
57
58 std::size_t
60 {
61 std::size_t mem =
66 MemoryConsumption::memory_consumption(n_active_lines_level);
67
68 if (active_cell_index_partitioner)
69 mem += active_cell_index_partitioner->memory_consumption();
70
71 for (const auto &partitioner : level_cell_index_partitioners)
72 if (partitioner)
73 mem += partitioner->memory_consumption();
74
75 return mem;
76 }
77
78
80 : n_quads(0)
81 , n_active_quads(0)
82 // all other fields are
83 // default constructed
84 {}
85
86
87
88 std::size_t
90 {
95 MemoryConsumption::memory_consumption(n_active_quads_level));
96 }
97
98
99
101 : n_hexes(0)
102 , n_active_hexes(0)
103 // all other fields are
104 // default constructed
105 {}
106
107
108
109 std::size_t
111 {
116 MemoryConsumption::memory_consumption(n_active_hexes_level));
117 }
118 } // namespace TriangulationImplementation
119} // namespace internal
120
121// anonymous namespace for internal helper functions
122namespace
123{
124 // return whether the given cell is
125 // patch_level_1, i.e. determine
126 // whether either all or none of
127 // its children are further
128 // refined. this function can only
129 // be called for non-active cells.
130 template <int dim, int spacedim>
131 bool
132 cell_is_patch_level_1(
134 {
135 Assert(cell->is_active() == false, ExcInternalError());
136
137 unsigned int n_active_children = 0;
138 for (unsigned int i = 0; i < cell->n_children(); ++i)
139 if (cell->child(i)->is_active())
140 ++n_active_children;
141
142 return (n_active_children == 0) ||
143 (n_active_children == cell->n_children());
144 }
145
146
147
148 // return, whether a given @p cell will be
149 // coarsened, which is the case if all
150 // children are active and have their coarsen
151 // flag set. In case only part of the coarsen
152 // flags are set, remove them.
153 template <int dim, int spacedim>
154 bool
155 cell_will_be_coarsened(
157 {
158 // only cells with children should be
159 // considered for coarsening
160
161 if (cell->has_children())
162 {
163 unsigned int children_to_coarsen = 0;
164 const unsigned int n_children = cell->n_children();
165
166 for (unsigned int c = 0; c < n_children; ++c)
167 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
168 ++children_to_coarsen;
169 if (children_to_coarsen == n_children)
170 return true;
171 else
172 for (unsigned int c = 0; c < n_children; ++c)
173 if (cell->child(c)->is_active())
174 cell->child(c)->clear_coarsen_flag();
175 }
176 // no children, so no coarsening
177 // possible. however, no children also
178 // means that this cell will be in the same
179 // state as if it had children and was
180 // coarsened. So, what should we return -
181 // false or true?
182 // make sure we do not have to do this at
183 // all...
184 Assert(cell->has_children(), ExcInternalError());
185 // ... and then simply return false
186 return false;
187 }
188
189
190 // return, whether the face @p face_no of the
191 // given @p cell will be refined after the
192 // current refinement step, considering
193 // refine and coarsen flags and considering
194 // only those refinemnts that will be caused
195 // by the neighboring cell.
196
197 // this function is used on both active cells
198 // and cells with children. on cells with
199 // children it also of interest to know 'how'
200 // the face will be refined. thus there is an
201 // additional third argument @p
202 // expected_face_ref_case returning just
203 // that. be aware, that this variable will
204 // only contain useful information if this
205 // function is called for an active cell.
206 //
207 // thus, this is an internal function, users
208 // should call one of the two alternatives
209 // following below.
210 template <int dim, int spacedim>
211 bool
212 face_will_be_refined_by_neighbor_internal(
214 const unsigned int face_no,
215 RefinementCase<dim - 1> &expected_face_ref_case)
216 {
217 // first of all: set the default value for
218 // expected_face_ref_case, which is no
219 // refinement at all
220 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
221
222 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
223 cell->neighbor(face_no);
224
225 // If we are at the boundary, there is no
226 // neighbor which could refine the face
227 if (neighbor.state() != IteratorState::valid)
228 return false;
229
230 if (neighbor->has_children())
231 {
232 // if the neighbor is refined, it may be
233 // coarsened. if so, then it won't refine
234 // the face, no matter what else happens
235 if (cell_will_be_coarsened(neighbor))
236 return false;
237 else
238 // if the neighbor is refined, then it
239 // is also refined at our current
240 // face. It will stay so without
241 // coarsening, so return true in that
242 // case.
243 {
244 expected_face_ref_case = cell->face(face_no)->refinement_case();
245 return true;
246 }
247 }
248
249 // now, the neighbor is not refined, but
250 // perhaps it will be
251 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
252 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
253 {
254 // now we need to know, which of the
255 // neighbors faces points towards us
256 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
257 // check, whether the cell will be
258 // refined in a way that refines our
259 // face
260 const RefinementCase<dim - 1> face_ref_case =
262 nb_ref_flag,
263 neighbor_neighbor,
264 neighbor->face_orientation(neighbor_neighbor),
265 neighbor->face_flip(neighbor_neighbor),
266 neighbor->face_rotation(neighbor_neighbor));
267 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
268 {
270 neighbor_face = neighbor->face(neighbor_neighbor);
271 const int this_face_index = cell->face_index(face_no);
272
273 // there are still two basic
274 // possibilities here: the neighbor
275 // might be coarser or as coarse
276 // as we are
277 if (neighbor_face->index() == this_face_index)
278 // the neighbor is as coarse as
279 // we are and will be refined at
280 // the face of consideration, so
281 // return true
282 {
283 expected_face_ref_case = face_ref_case;
284 return true;
285 }
286 else
287 {
288 // the neighbor is coarser.
289 // this is the most complicated
290 // case. It might be, that the
291 // neighbor's face will be
292 // refined, but that we will
293 // not see this, as we are
294 // refined in a similar way.
295
296 // so, the neighbor's face must
297 // have children. check, if our
298 // cell's face is one of these
299 // (it could also be a
300 // grand_child)
301 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
302 if (neighbor_face->child_index(c) == this_face_index)
303 {
304 // if the flagged refine
305 // case of the face is a
306 // subset or the same as
307 // the current refine case,
308 // then the face, as seen
309 // from our cell, won't be
310 // refined by the neighbor
311 if ((neighbor_face->refinement_case() | face_ref_case) ==
312 neighbor_face->refinement_case())
313 return false;
314 else
315 {
316 // if we are active, we
317 // must be an
318 // anisotropic child
319 // and the coming
320 // face_ref_case is
321 // isotropic. Thus,
322 // from our cell we
323 // will see exactly the
324 // opposite refine case
325 // that the face has
326 // now...
327 Assert(
328 face_ref_case ==
331 expected_face_ref_case =
332 ~neighbor_face->refinement_case();
333 return true;
334 }
335 }
336
337 // so, obviously we were not
338 // one of the children, but a
339 // grandchild. This is only
340 // possible in 3d.
341 Assert(dim == 3, ExcInternalError());
342 // In that case, however, no
343 // matter what the neighbor
344 // does, it won't be finer
345 // after the next refinement
346 // step.
347 return false;
348 }
349 } // if face will be refined
350 } // if neighbor is flagged for refinement
351
352 // no cases left, so the neighbor will not
353 // refine the face
354 return false;
355 }
356
357 // version of above function for both active
358 // and non-active cells
359 template <int dim, int spacedim>
360 bool
361 face_will_be_refined_by_neighbor(
363 const unsigned int face_no)
364 {
365 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
366 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
367 }
368
369 // version of above function for active cells
370 // only. Additionally returning the refine
371 // case (to come) of the face under
372 // consideration
373 template <int dim, int spacedim>
374 bool
375 face_will_be_refined_by_neighbor(
377 const unsigned int face_no,
378 RefinementCase<dim - 1> &expected_face_ref_case)
379 {
380 return face_will_be_refined_by_neighbor_internal(cell,
381 face_no,
382 expected_face_ref_case);
383 }
384
385
386
387 template <int dim, int spacedim>
388 bool
389 satisfies_level1_at_vertex_rule(
391 {
392 std::vector<unsigned int> min_adjacent_cell_level(
393 triangulation.n_vertices(), triangulation.n_levels());
394 std::vector<unsigned int> max_adjacent_cell_level(
395 triangulation.n_vertices(), 0);
396
397 for (const auto &cell : triangulation.active_cell_iterators())
398 for (const unsigned int v : cell->vertex_indices())
399 {
400 min_adjacent_cell_level[cell->vertex_index(v)] =
401 std::min<unsigned int>(
402 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
403 max_adjacent_cell_level[cell->vertex_index(v)] =
404 std::max<unsigned int>(
405 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
406 }
407
408 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
409 if (triangulation.vertex_used(k))
410 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
411 return false;
412 return true;
413 }
414
415
416
428 void
429 reorder_compatibility(const std::vector<CellData<1>> &, const SubCellData &)
430 {
431 // nothing to do here: the format
432 // hasn't changed for 1d
433 }
434
435
436 void
437 reorder_compatibility(std::vector<CellData<2>> &cells, const SubCellData &)
438 {
439 for (auto &cell : cells)
440 if (cell.vertices.size() == GeometryInfo<2>::vertices_per_cell)
441 std::swap(cell.vertices[2], cell.vertices[3]);
442 }
443
444
445 void
446 reorder_compatibility(std::vector<CellData<3>> &cells,
447 SubCellData & subcelldata)
448 {
449 unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
450 static constexpr std::array<unsigned int,
452 local_vertex_numbering{{0, 1, 5, 4, 2, 3, 7, 6}};
453 for (auto &cell : cells)
454 if (cell.vertices.size() == GeometryInfo<3>::vertices_per_cell)
455 {
456 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
457 tmp[i] = cell.vertices[i];
458 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
459 cell.vertices[local_vertex_numbering[i]] = tmp[i];
460 }
461
462 // now points in boundary quads
463 for (auto &boundary_quad : subcelldata.boundary_quads)
464 if (boundary_quad.vertices.size() == GeometryInfo<2>::vertices_per_cell)
465 std::swap(boundary_quad.vertices[2], boundary_quad.vertices[3]);
466 }
467
468
469
487 template <int dim, int spacedim>
488 unsigned int
489 middle_vertex_index(
491 {
492 if (line->has_children())
493 return line->child(0)->vertex_index(1);
495 }
496
497
498 template <int dim, int spacedim>
499 unsigned int
500 middle_vertex_index(
502 {
503 switch (static_cast<unsigned char>(quad->refinement_case()))
504 {
506 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
507 break;
509 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
510 break;
512 return quad->child(0)->vertex_index(3);
513 break;
514 default:
515 break;
516 }
518 }
519
520
521 template <int dim, int spacedim>
522 unsigned int
523 middle_vertex_index(
525 {
526 switch (static_cast<unsigned char>(hex->refinement_case()))
527 {
529 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
530 break;
532 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
533 break;
535 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
536 break;
538 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
539 break;
541 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
542 break;
544 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
545 break;
547 return hex->child(0)->vertex_index(7);
548 break;
549 default:
550 break;
551 }
553 }
554
555
568 template <class TRIANGULATION>
569 inline typename TRIANGULATION::DistortedCellList
570 collect_distorted_coarse_cells(const TRIANGULATION &)
571 {
572 return typename TRIANGULATION::DistortedCellList();
573 }
574
575
576
585 template <int dim>
587 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
588 {
589 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
590 for (const auto &cell : triangulation.cell_iterators_on_level(0))
591 {
593 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
594 vertices[i] = cell->vertex(i);
595
598
599 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
600 if (determinants[i] <= 1e-9 * std::pow(cell->diameter(), 1. * dim))
601 {
602 distorted_cells.distorted_cells.push_back(cell);
603 break;
604 }
605 }
606
607 return distorted_cells;
608 }
609
610
617 template <int dim>
618 bool
619 has_distorted_children(
620 const typename Triangulation<dim, dim>::cell_iterator &cell)
621 {
622 Assert(cell->has_children(), ExcInternalError());
623
624 for (unsigned int c = 0; c < cell->n_children(); ++c)
625 {
627 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
628 vertices[i] = cell->child(c)->vertex(i);
629
632
633 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
634 if (determinants[i] <=
635 1e-9 * std::pow(cell->child(c)->diameter(), 1. * dim))
636 return true;
637 }
638
639 return false;
640 }
641
642
650 template <int dim, int spacedim>
651 bool
652 has_distorted_children(
654 {
655 return false;
656 }
657
658
659 template <int dim, int spacedim>
660 void
661 update_periodic_face_map_recursively(
662 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
663 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
664 unsigned int n_face_1,
665 unsigned int n_face_2,
666 const std::bitset<3> & orientation,
667 typename std::map<
669 unsigned int>,
670 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
671 unsigned int>,
672 std::bitset<3>>> &periodic_face_map)
673 {
674 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
675 const FaceIterator face_1 = cell_1->face(n_face_1);
676 const FaceIterator face_2 = cell_2->face(n_face_2);
677
678 const bool face_orientation = orientation[0];
679 const bool face_flip = orientation[1];
680 const bool face_rotation = orientation[2];
681
682 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
683 face_rotation == false),
684 ExcMessage("The supplied orientation "
685 "(face_orientation, face_flip, face_rotation) "
686 "is invalid for 1d"));
687
688 Assert((dim != 2) || (face_orientation == true && face_rotation == false),
689 ExcMessage("The supplied orientation "
690 "(face_orientation, face_flip, face_rotation) "
691 "is invalid for 2d"));
692
693 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
694
695 Assert(face_1->at_boundary() && face_2->at_boundary(),
696 ExcMessage("Periodic faces must be on the boundary"));
697
698 // Check if the requirement that each edge can only have at most one hanging
699 // node, and as a consequence neighboring cells can differ by at most
700 // one refinement level is enforced. In 1d, there are no hanging nodes and
701 // so neighboring cells can differ by more than one refinement level.
702 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
704
705 // insert periodic face pair for both cells
706 using CellFace =
707 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
708 unsigned int>;
709 const CellFace cell_face_1(cell_1, n_face_1);
710 const CellFace cell_face_2(cell_2, n_face_2);
711 const std::pair<CellFace, std::bitset<3>> cell_face_orientation_2(
712 cell_face_2, orientation);
713
714 const std::pair<CellFace, std::pair<CellFace, std::bitset<3>>>
715 periodic_faces(cell_face_1, cell_face_orientation_2);
716
717 // Only one periodic neighbor is allowed
718 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
719 periodic_face_map.insert(periodic_faces);
720
721 if (dim == 1)
722 {
723 if (cell_1->has_children())
724 {
725 if (cell_2->has_children())
726 {
727 update_periodic_face_map_recursively<dim, spacedim>(
728 cell_1->child(n_face_1),
729 cell_2->child(n_face_2),
730 n_face_1,
731 n_face_2,
732 orientation,
733 periodic_face_map);
734 }
735 else // only face_1 has children
736 {
737 update_periodic_face_map_recursively<dim, spacedim>(
738 cell_1->child(n_face_1),
739 cell_2,
740 n_face_1,
741 n_face_2,
742 orientation,
743 periodic_face_map);
744 }
745 }
746 }
747 else // dim == 2 || dim == 3
748 {
749 // A lookup table on how to go through the child cells depending on the
750 // orientation:
751 // see Documentation of GeometryInfo for details
752
753 static const int lookup_table_2d[2][2] =
754 // flip:
755 {
756 {0, 1}, // false
757 {1, 0} // true
758 };
759
760 static const int lookup_table_3d[2][2][2][4] =
761 // orientation flip rotation
762 {{{
763 {0, 2, 1, 3}, // false false false
764 {2, 3, 0, 1} // false false true
765 },
766 {
767 {3, 1, 2, 0}, // false true false
768 {1, 0, 3, 2} // false true true
769 }},
770 {{
771 {0, 1, 2, 3}, // true false false
772 {1, 3, 0, 2} // true false true
773 },
774 {
775 {3, 2, 1, 0}, // true true false
776 {2, 0, 3, 1} // true true true
777 }}};
778
779 if (cell_1->has_children())
780 {
781 if (cell_2->has_children())
782 {
783 // In the case that both faces have children, we loop over all
784 // children and apply update_periodic_face_map_recursively
785 // recursively:
786
787 Assert(face_1->n_children() ==
789 face_2->n_children() ==
792
793 for (unsigned int i = 0;
794 i < GeometryInfo<dim>::max_children_per_face;
795 ++i)
796 {
797 // Lookup the index for the second face
798 unsigned int j = 0;
799 switch (dim)
800 {
801 case 2:
802 j = lookup_table_2d[face_flip][i];
803 break;
804 case 3:
805 j = lookup_table_3d[face_orientation][face_flip]
806 [face_rotation][i];
807 break;
808 default:
810 }
811
812 // find subcell ids that belong to the subface indices
813 unsigned int child_cell_1 =
815 cell_1->refinement_case(),
816 n_face_1,
817 i,
818 cell_1->face_orientation(n_face_1),
819 cell_1->face_flip(n_face_1),
820 cell_1->face_rotation(n_face_1),
821 face_1->refinement_case());
822 unsigned int child_cell_2 =
824 cell_2->refinement_case(),
825 n_face_2,
826 j,
827 cell_2->face_orientation(n_face_2),
828 cell_2->face_flip(n_face_2),
829 cell_2->face_rotation(n_face_2),
830 face_2->refinement_case());
831
832 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
833 face_1->child(i),
835 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
836 face_2->child(j),
838
839 // precondition: subcell has the same orientation as cell
840 // (so that the face numbers coincide) recursive call
841 update_periodic_face_map_recursively<dim, spacedim>(
842 cell_1->child(child_cell_1),
843 cell_2->child(child_cell_2),
844 n_face_1,
845 n_face_2,
846 orientation,
847 periodic_face_map);
848 }
849 }
850 else // only face_1 has children
851 {
852 for (unsigned int i = 0;
853 i < GeometryInfo<dim>::max_children_per_face;
854 ++i)
855 {
856 // find subcell ids that belong to the subface indices
857 unsigned int child_cell_1 =
859 cell_1->refinement_case(),
860 n_face_1,
861 i,
862 cell_1->face_orientation(n_face_1),
863 cell_1->face_flip(n_face_1),
864 cell_1->face_rotation(n_face_1),
865 face_1->refinement_case());
866
867 // recursive call
868 update_periodic_face_map_recursively<dim, spacedim>(
869 cell_1->child(child_cell_1),
870 cell_2,
871 n_face_1,
872 n_face_2,
873 orientation,
874 periodic_face_map);
875 }
876 }
877 }
878 }
879 }
880
881
882} // end of anonymous namespace
883
884
885namespace internal
886{
887 namespace TriangulationImplementation
888 {
889 // make sure that if in the following we
890 // write Triangulation<dim,spacedim>
891 // we mean the *class*
892 // ::Triangulation, not the
893 // enclosing namespace
894 // internal::TriangulationImplementation
895 using ::Triangulation;
896
902 int,
903 << "Something went wrong upon construction of cell "
904 << arg1);
915 int,
916 << "Cell " << arg1
917 << " has negative measure. This typically "
918 << "indicates some distortion in the cell, or a mistakenly "
919 << "swapped pair of vertices in the input to "
920 << "Triangulation::create_triangulation().");
929 int,
930 int,
931 int,
932 << "Error while creating cell " << arg1
933 << ": the vertex index " << arg2 << " must be between 0 and "
934 << arg3 << '.');
940 int,
941 int,
942 << "While trying to assign a boundary indicator to a line: "
943 << "the line with end vertices " << arg1 << " and " << arg2
944 << " does not exist.");
950 int,
951 int,
952 int,
953 int,
954 << "While trying to assign a boundary indicator to a quad: "
955 << "the quad with bounding lines " << arg1 << ", " << arg2
956 << ", " << arg3 << ", " << arg4 << " does not exist.");
963 int,
964 int,
966 << "The input data for creating a triangulation contained "
967 << "information about a line with indices " << arg1 << " and " << arg2
968 << " that is described to have boundary indicator "
969 << static_cast<int>(arg3)
970 << ". However, this is an internal line not located on the "
971 << "boundary. You cannot assign a boundary indicator to it." << std::endl
972 << std::endl
973 << "If this happened at a place where you call "
974 << "Triangulation::create_triangulation() yourself, you need "
975 << "to check the SubCellData object you pass to this function."
976 << std::endl
977 << std::endl
978 << "If this happened in a place where you are reading a mesh "
979 << "from a file, then you need to investigate why such a line "
980 << "ended up in the input file. A typical case is a geometry "
981 << "that consisted of multiple parts and for which the mesh "
982 << "generator program assumes that the interface between "
983 << "two parts is a boundary when that isn't supposed to be "
984 << "the case, or where the mesh generator simply assigns "
985 << "'geometry indicators' to lines at the perimeter of "
986 << "a part that are not supposed to be interpreted as "
987 << "'boundary indicators'.");
994 int,
995 int,
996 int,
997 int,
999 << "The input data for creating a triangulation contained "
1000 << "information about a quad with indices " << arg1 << ", " << arg2
1001 << ", " << arg3 << ", and " << arg4
1002 << " that is described to have boundary indicator "
1003 << static_cast<int>(arg5)
1004 << ". However, this is an internal quad not located on the "
1005 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1006 << std::endl
1007 << "If this happened at a place where you call "
1008 << "Triangulation::create_triangulation() yourself, you need "
1009 << "to check the SubCellData object you pass to this function."
1010 << std::endl
1011 << std::endl
1012 << "If this happened in a place where you are reading a mesh "
1013 << "from a file, then you need to investigate why such a quad "
1014 << "ended up in the input file. A typical case is a geometry "
1015 << "that consisted of multiple parts and for which the mesh "
1016 << "generator program assumes that the interface between "
1017 << "two parts is a boundary when that isn't supposed to be "
1018 << "the case, or where the mesh generator simply assigns "
1019 << "'geometry indicators' to quads at the surface of "
1020 << "a part that are not supposed to be interpreted as "
1021 << "'boundary indicators'.");
1028 int,
1029 int,
1030 << "In SubCellData the line info of the line with vertex indices " << arg1
1031 << " and " << arg2 << " appears more than once. "
1032 << "This is not allowed.");
1039 int,
1040 int,
1041 std::string,
1042 << "In SubCellData the line info of the line with vertex indices " << arg1
1043 << " and " << arg2 << " appears multiple times with different (valid) "
1044 << arg3 << ". This is not allowed.");
1051 int,
1052 int,
1053 int,
1054 int,
1055 std::string,
1056 << "In SubCellData the quad info of the quad with line indices " << arg1
1057 << ", " << arg2 << ", " << arg3 << " and " << arg4
1058 << " appears multiple times with different (valid) " << arg5
1059 << ". This is not allowed.");
1060
1061 /*
1062 * Reserve space for TriaFaces. Details:
1063 *
1064 * Reserve space for line_orientations.
1065 *
1066 * @note Used only for dim=3.
1067 */
1068 void
1070 const unsigned int new_quads_in_pairs,
1071 const unsigned int new_quads_single)
1072 {
1073 AssertDimension(tria_faces.dim, 3);
1074
1075 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
1076
1077 unsigned int next_free_single = 0;
1078 unsigned int next_free_pair = 0;
1079
1080 // count the number of objects, of unused single objects and of
1081 // unused pairs of objects
1082 unsigned int n_quads = 0;
1083 unsigned int n_unused_pairs = 0;
1084 unsigned int n_unused_singles = 0;
1085 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
1086 {
1087 if (tria_faces.quads.used[i])
1088 ++n_quads;
1089 else if (i + 1 < tria_faces.quads.used.size())
1090 {
1091 if (tria_faces.quads.used[i + 1])
1092 {
1093 ++n_unused_singles;
1094 if (next_free_single == 0)
1095 next_free_single = i;
1096 }
1097 else
1098 {
1099 ++n_unused_pairs;
1100 if (next_free_pair == 0)
1101 next_free_pair = i;
1102 ++i;
1103 }
1104 }
1105 else
1106 ++n_unused_singles;
1107 }
1108 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
1109 tria_faces.quads.used.size(),
1111 (void)n_quads;
1112
1113 // how many single quads are needed in addition to n_unused_quads?
1114 const int additional_single_quads = new_quads_single - n_unused_singles;
1115
1116 unsigned int new_size =
1117 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
1118 if (additional_single_quads > 0)
1119 new_size += additional_single_quads;
1120
1121 // see above...
1122 if (new_size > tria_faces.quads.n_objects())
1123 {
1124 // reserve the field of the derived class
1125 tria_faces.quads_line_orientations.resize(
1126 new_size * GeometryInfo<3>::lines_per_face, true);
1127
1128 auto &q_is_q = tria_faces.quad_is_quadrilateral;
1129 q_is_q.reserve(new_size);
1130 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
1131 }
1132 }
1133
1134
1135
1149 void
1151 const unsigned int total_cells,
1152 const unsigned int dimension,
1153 const unsigned int space_dimension)
1154 {
1155 // we need space for total_cells cells. Maybe we have more already
1156 // with those cells which are unused, so only allocate new space if
1157 // needed.
1158 //
1159 // note that all arrays should have equal sizes (checked by
1160 // @p{monitor_memory}
1161 if (total_cells > tria_level.refine_flags.size())
1162 {
1163 tria_level.refine_flags.reserve(total_cells);
1164 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
1165 total_cells -
1166 tria_level.refine_flags.size(),
1167 /*RefinementCase::no_refinement=*/0);
1168
1169 tria_level.coarsen_flags.reserve(total_cells);
1170 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
1171 total_cells -
1172 tria_level.coarsen_flags.size(),
1173 false);
1174
1175 tria_level.active_cell_indices.reserve(total_cells);
1176 tria_level.active_cell_indices.insert(
1177 tria_level.active_cell_indices.end(),
1178 total_cells - tria_level.active_cell_indices.size(),
1180
1181 tria_level.subdomain_ids.reserve(total_cells);
1182 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
1183 total_cells -
1184 tria_level.subdomain_ids.size(),
1185 0);
1186
1187 tria_level.level_subdomain_ids.reserve(total_cells);
1188 tria_level.level_subdomain_ids.insert(
1189 tria_level.level_subdomain_ids.end(),
1190 total_cells - tria_level.level_subdomain_ids.size(),
1191 0);
1192
1193 tria_level.global_active_cell_indices.reserve(total_cells);
1194 tria_level.global_active_cell_indices.insert(
1195 tria_level.global_active_cell_indices.end(),
1196 total_cells - tria_level.global_active_cell_indices.size(),
1198
1199 tria_level.global_level_cell_indices.reserve(total_cells);
1200 tria_level.global_level_cell_indices.insert(
1201 tria_level.global_level_cell_indices.end(),
1202 total_cells - tria_level.global_level_cell_indices.size(),
1204
1205 if (dimension < space_dimension)
1206 {
1207 tria_level.direction_flags.reserve(total_cells);
1208 tria_level.direction_flags.insert(
1209 tria_level.direction_flags.end(),
1210 total_cells - tria_level.direction_flags.size(),
1211 true);
1212 }
1213 else
1214 tria_level.direction_flags.clear();
1215
1216 tria_level.parents.reserve((total_cells + 1) / 2);
1217 tria_level.parents.insert(tria_level.parents.end(),
1218 (total_cells + 1) / 2 -
1219 tria_level.parents.size(),
1220 -1);
1221
1222 tria_level.neighbors.reserve(total_cells * (2 * dimension));
1223 tria_level.neighbors.insert(tria_level.neighbors.end(),
1224 total_cells * (2 * dimension) -
1225 tria_level.neighbors.size(),
1226 std::make_pair(-1, -1));
1227
1228 if (tria_level.dim == 2 || tria_level.dim == 3)
1229 {
1230 const unsigned int max_faces_per_cell = 2 * dimension;
1231 tria_level.face_orientations.resize(total_cells *
1232 max_faces_per_cell);
1233
1234 tria_level.reference_cell.reserve(total_cells);
1235 tria_level.reference_cell.insert(
1236 tria_level.reference_cell.end(),
1237 total_cells - tria_level.reference_cell.size(),
1238 tria_level.dim == 2 ? ReferenceCells::Quadrilateral :
1240 }
1241 }
1242 }
1243
1244
1245
1250 int,
1251 int,
1252 << "The containers have sizes " << arg1 << " and " << arg2
1253 << ", which is not as expected.");
1254
1260 void
1261 monitor_memory(const TriaLevel & tria_level,
1262 const unsigned int true_dimension)
1263 {
1264 (void)tria_level;
1265 (void)true_dimension;
1266 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
1267 tria_level.neighbors.size(),
1268 ExcMemoryInexact(tria_level.refine_flags.size(),
1269 tria_level.neighbors.size()));
1270 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
1271 tria_level.neighbors.size(),
1272 ExcMemoryInexact(tria_level.coarsen_flags.size(),
1273 tria_level.neighbors.size()));
1274 }
1275
1276
1277
1290 void
1292 const unsigned int new_objects_in_pairs,
1293 const unsigned int new_objects_single = 0)
1294 {
1295 if (tria_objects.structdim <= 2)
1296 {
1297 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
1298
1299 tria_objects.next_free_single = 0;
1300 tria_objects.next_free_pair = 0;
1301 tria_objects.reverse_order_next_free_single = false;
1302
1303 // count the number of objects, of unused single objects and of
1304 // unused pairs of objects
1305 unsigned int n_objects = 0;
1306 unsigned int n_unused_pairs = 0;
1307 unsigned int n_unused_singles = 0;
1308 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
1309 {
1310 if (tria_objects.used[i])
1311 ++n_objects;
1312 else if (i + 1 < tria_objects.used.size())
1313 {
1314 if (tria_objects.used[i + 1])
1315 {
1316 ++n_unused_singles;
1317 if (tria_objects.next_free_single == 0)
1318 tria_objects.next_free_single = i;
1319 }
1320 else
1321 {
1322 ++n_unused_pairs;
1323 if (tria_objects.next_free_pair == 0)
1324 tria_objects.next_free_pair = i;
1325 ++i;
1326 }
1327 }
1328 else
1329 ++n_unused_singles;
1330 }
1331 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
1332 tria_objects.used.size(),
1334 (void)n_objects;
1335
1336 // how many single objects are needed in addition to
1337 // n_unused_objects?
1338 const int additional_single_objects =
1339 new_objects_single - n_unused_singles;
1340
1341 unsigned int new_size = tria_objects.used.size() +
1342 new_objects_in_pairs - 2 * n_unused_pairs;
1343 if (additional_single_objects > 0)
1344 new_size += additional_single_objects;
1345
1346 // only allocate space if necessary
1347 if (new_size > tria_objects.n_objects())
1348 {
1349 const unsigned int max_faces_per_cell =
1350 2 * tria_objects.structdim;
1351 const unsigned int max_children_per_cell =
1352 1 << tria_objects.structdim;
1353
1354 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1355 tria_objects.cells.insert(tria_objects.cells.end(),
1356 (new_size - tria_objects.n_objects()) *
1357 max_faces_per_cell,
1358 -1);
1359
1360 tria_objects.used.reserve(new_size);
1361 tria_objects.used.insert(tria_objects.used.end(),
1362 new_size - tria_objects.used.size(),
1363 false);
1364
1365 tria_objects.user_flags.reserve(new_size);
1366 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1367 new_size -
1368 tria_objects.user_flags.size(),
1369 false);
1370
1371 const unsigned int factor = max_children_per_cell / 2;
1372 tria_objects.children.reserve(factor * new_size);
1373 tria_objects.children.insert(tria_objects.children.end(),
1374 factor * new_size -
1375 tria_objects.children.size(),
1376 -1);
1377
1378 if (tria_objects.structdim > 1)
1379 {
1380 tria_objects.refinement_cases.reserve(new_size);
1381 tria_objects.refinement_cases.insert(
1382 tria_objects.refinement_cases.end(),
1383 new_size - tria_objects.refinement_cases.size(),
1384 /*RefinementCase::no_refinement=*/0);
1385 }
1386
1387 // first reserve, then resize. Otherwise the std library can
1388 // decide to allocate more entries.
1389 tria_objects.boundary_or_material_id.reserve(new_size);
1390 tria_objects.boundary_or_material_id.resize(new_size);
1391
1392 tria_objects.user_data.reserve(new_size);
1393 tria_objects.user_data.resize(new_size);
1394
1395 tria_objects.manifold_id.reserve(new_size);
1396 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1397 new_size -
1398 tria_objects.manifold_id.size(),
1400 }
1401
1402 if (n_unused_singles == 0)
1403 {
1404 tria_objects.next_free_single = new_size - 1;
1405 tria_objects.reverse_order_next_free_single = true;
1406 }
1407 }
1408 else
1409 {
1410 const unsigned int new_hexes = new_objects_in_pairs;
1411
1412 const unsigned int new_size =
1413 new_hexes + std::count(tria_objects.used.begin(),
1414 tria_objects.used.end(),
1415 true);
1416
1417 // see above...
1418 if (new_size > tria_objects.n_objects())
1419 {
1420 const unsigned int max_faces_per_cell =
1421 2 * tria_objects.structdim;
1422
1423 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1424 tria_objects.cells.insert(tria_objects.cells.end(),
1425 (new_size - tria_objects.n_objects()) *
1426 max_faces_per_cell,
1427 -1);
1428
1429 tria_objects.used.reserve(new_size);
1430 tria_objects.used.insert(tria_objects.used.end(),
1431 new_size - tria_objects.used.size(),
1432 false);
1433
1434 tria_objects.user_flags.reserve(new_size);
1435 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1436 new_size -
1437 tria_objects.user_flags.size(),
1438 false);
1439
1440 tria_objects.children.reserve(4 * new_size);
1441 tria_objects.children.insert(tria_objects.children.end(),
1442 4 * new_size -
1443 tria_objects.children.size(),
1444 -1);
1445
1446 // for the following fields, we know exactly how many elements
1447 // we need, so first reserve then resize (resize itself, at least
1448 // with some compiler libraries, appears to round up the size it
1449 // actually reserves)
1450 tria_objects.boundary_or_material_id.reserve(new_size);
1451 tria_objects.boundary_or_material_id.resize(new_size);
1452
1453 tria_objects.manifold_id.reserve(new_size);
1454 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1455 new_size -
1456 tria_objects.manifold_id.size(),
1458
1459 tria_objects.user_data.reserve(new_size);
1460 tria_objects.user_data.resize(new_size);
1461
1462 tria_objects.refinement_cases.reserve(new_size);
1463 tria_objects.refinement_cases.insert(
1464 tria_objects.refinement_cases.end(),
1465 new_size - tria_objects.refinement_cases.size(),
1466 /*RefinementCase::no_refinement=*/0);
1467 }
1468 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
1469 }
1470 }
1471
1472
1473
1479 void
1480 monitor_memory(const TriaObjects &tria_object, const unsigned int)
1481 {
1482 Assert(tria_object.n_objects() == tria_object.used.size(),
1483 ExcMemoryInexact(tria_object.n_objects(),
1484 tria_object.used.size()));
1485 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
1486 ExcMemoryInexact(tria_object.n_objects(),
1487 tria_object.user_flags.size()));
1488 Assert(tria_object.n_objects() ==
1489 tria_object.boundary_or_material_id.size(),
1490 ExcMemoryInexact(tria_object.n_objects(),
1491 tria_object.boundary_or_material_id.size()));
1492 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
1493 ExcMemoryInexact(tria_object.n_objects(),
1494 tria_object.manifold_id.size()));
1495 Assert(tria_object.n_objects() == tria_object.user_data.size(),
1496 ExcMemoryInexact(tria_object.n_objects(),
1497 tria_object.user_data.size()));
1498
1499 if (tria_object.structdim == 1)
1500 {
1501 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
1502 ExcMemoryInexact(tria_object.n_objects(),
1503 tria_object.children.size()));
1504 }
1505 else if (tria_object.structdim == 2)
1506 {
1507 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
1508 ExcMemoryInexact(tria_object.n_objects(),
1509 tria_object.children.size()));
1510 }
1511 else if (tria_object.structdim == 3)
1512 {
1513 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
1514 ExcMemoryInexact(tria_object.n_objects(),
1515 tria_object.children.size()));
1516 }
1517 }
1518
1519
1520
1525 template <int dim, int spacedim>
1527 {
1528 public:
1532 virtual ~Policy() = default;
1533
1537 virtual void
1539
1543 virtual void
1547 std::vector<unsigned int> & line_cell_count,
1548 std::vector<unsigned int> &quad_cell_count) = 0;
1549
1555 const bool check_for_distorted_cells) = 0;
1556
1560 virtual void
1563
1567 virtual void
1570
1574 virtual bool
1576 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
1577
1584 virtual std::unique_ptr<Policy<dim, spacedim>>
1585 clone() = 0;
1586 };
1587
1588
1589
1595 template <int dim, int spacedim, typename T>
1596 class PolicyWrapper : public Policy<dim, spacedim>
1597 {
1598 public:
1599 void
1601 {
1602 T::update_neighbors(tria);
1603 }
1604
1605 void
1609 std::vector<unsigned int> & line_cell_count,
1610 std::vector<unsigned int> &quad_cell_count) override
1611 {
1612 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
1613 }
1614
1617 const bool check_for_distorted_cells) override
1618 {
1619 return T::execute_refinement(triangulation, check_for_distorted_cells);
1620 }
1621
1622 void
1625 {
1626 T::prevent_distorted_boundary_cells(triangulation);
1627 }
1628
1629 void
1632 {
1633 T::prepare_refinement_dim_dependent(triangulation);
1634 }
1635
1636 bool
1639 override
1640 {
1641 return T::template coarsening_allowed<dim, spacedim>(cell);
1642 }
1643
1644 std::unique_ptr<Policy<dim, spacedim>>
1645 clone() override
1646 {
1647 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
1648 }
1649 };
1650
1651
1652
1749 {
1761 template <int dim, int spacedim>
1762 static void
1765 const unsigned int level_objects,
1767 {
1768 using line_iterator =
1770
1771 number_cache.n_levels = 0;
1772 if (level_objects > 0)
1773 // find the last level on which there are used cells
1774 for (unsigned int level = 0; level < level_objects; ++level)
1775 if (triangulation.begin(level) != triangulation.end(level))
1776 number_cache.n_levels = level + 1;
1777
1778 // no cells at all?
1779 Assert(number_cache.n_levels > 0, ExcInternalError());
1780
1781 //---------------------------------
1782 // update the number of lines on the different levels in the
1783 // cache
1784 number_cache.n_lines = 0;
1785 number_cache.n_active_lines = 0;
1786
1787 // for 1d, lines have levels so take count the objects per
1788 // level and globally
1789 if (dim == 1)
1790 {
1791 number_cache.n_lines_level.resize(number_cache.n_levels);
1792 number_cache.n_active_lines_level.resize(number_cache.n_levels);
1793
1794 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
1795 {
1796 // count lines on this level
1797 number_cache.n_lines_level[level] = 0;
1798 number_cache.n_active_lines_level[level] = 0;
1799
1800 line_iterator line = triangulation.begin_line(level),
1801 endc =
1802 (level == number_cache.n_levels - 1 ?
1803 line_iterator(triangulation.end_line()) :
1804 triangulation.begin_line(level + 1));
1805 for (; line != endc; ++line)
1806 {
1807 ++number_cache.n_lines_level[level];
1808 if (line->has_children() == false)
1809 ++number_cache.n_active_lines_level[level];
1810 }
1811
1812 // update total number of lines
1813 number_cache.n_lines += number_cache.n_lines_level[level];
1814 number_cache.n_active_lines +=
1815 number_cache.n_active_lines_level[level];
1816 }
1817 }
1818 else
1819 {
1820 // for dim>1, there are no levels for lines
1821 number_cache.n_lines_level.clear();
1822 number_cache.n_active_lines_level.clear();
1823
1824 line_iterator line = triangulation.begin_line(),
1825 endc = triangulation.end_line();
1826 for (; line != endc; ++line)
1827 {
1828 ++number_cache.n_lines;
1829 if (line->has_children() == false)
1830 ++number_cache.n_active_lines;
1831 }
1832 }
1833 }
1834
1849 template <int dim, int spacedim>
1850 static void
1853 const unsigned int level_objects,
1855 {
1856 // update lines and n_levels in number_cache. since we don't
1857 // access any of these numbers, we can do this in the
1858 // background
1860 static_cast<
1861 void (*)(const Triangulation<dim, spacedim> &,
1862 const unsigned int,
1864 &compute_number_cache_dim<dim, spacedim>),
1866 level_objects,
1868 number_cache));
1869
1870 using quad_iterator =
1872
1873 //---------------------------------
1874 // update the number of quads on the different levels in the
1875 // cache
1876 number_cache.n_quads = 0;
1877 number_cache.n_active_quads = 0;
1878
1879 // for 2d, quads have levels so take count the objects per
1880 // level and globally
1881 if (dim == 2)
1882 {
1883 // count the number of levels; the function we called above
1884 // on a separate Task for lines also does this and puts it into
1885 // number_cache.n_levels, but this datum may not yet be
1886 // available as we call the function on a separate task
1887 unsigned int n_levels = 0;
1888 if (level_objects > 0)
1889 // find the last level on which there are used cells
1890 for (unsigned int level = 0; level < level_objects; ++level)
1891 if (triangulation.begin(level) != triangulation.end(level))
1892 n_levels = level + 1;
1893
1894 number_cache.n_quads_level.resize(n_levels);
1895 number_cache.n_active_quads_level.resize(n_levels);
1896
1897 for (unsigned int level = 0; level < n_levels; ++level)
1898 {
1899 // count quads on this level
1900 number_cache.n_quads_level[level] = 0;
1901 number_cache.n_active_quads_level[level] = 0;
1902
1903 quad_iterator quad = triangulation.begin_quad(level),
1904 endc =
1905 (level == n_levels - 1 ?
1906 quad_iterator(triangulation.end_quad()) :
1907 triangulation.begin_quad(level + 1));
1908 for (; quad != endc; ++quad)
1909 {
1910 ++number_cache.n_quads_level[level];
1911 if (quad->has_children() == false)
1912 ++number_cache.n_active_quads_level[level];
1913 }
1914
1915 // update total number of quads
1916 number_cache.n_quads += number_cache.n_quads_level[level];
1917 number_cache.n_active_quads +=
1918 number_cache.n_active_quads_level[level];
1919 }
1920 }
1921 else
1922 {
1923 // for dim>2, there are no levels for quads
1924 number_cache.n_quads_level.clear();
1925 number_cache.n_active_quads_level.clear();
1926
1927 quad_iterator quad = triangulation.begin_quad(),
1928 endc = triangulation.end_quad();
1929 for (; quad != endc; ++quad)
1930 {
1931 ++number_cache.n_quads;
1932 if (quad->has_children() == false)
1933 ++number_cache.n_active_quads;
1934 }
1935 }
1936
1937 // wait for the background computation for lines
1938 update_lines.join();
1939 }
1940
1956 template <int dim, int spacedim>
1957 static void
1960 const unsigned int level_objects,
1962 {
1963 // update quads, lines and n_levels in number_cache. since we
1964 // don't access any of these numbers, we can do this in the
1965 // background
1966 Threads::Task<void> update_quads_and_lines = Threads::new_task(
1967 static_cast<
1968 void (*)(const Triangulation<dim, spacedim> &,
1969 const unsigned int,
1971 &compute_number_cache_dim<dim, spacedim>),
1973 level_objects,
1975 number_cache));
1976
1977 using hex_iterator =
1979
1980 //---------------------------------
1981 // update the number of hexes on the different levels in the
1982 // cache
1983 number_cache.n_hexes = 0;
1984 number_cache.n_active_hexes = 0;
1985
1986 // for 3d, hexes have levels so take count the objects per
1987 // level and globally
1988 if (dim == 3)
1989 {
1990 // count the number of levels; the function we called
1991 // above on a separate Task for quads (recursively, via
1992 // the lines function) also does this and puts it into
1993 // number_cache.n_levels, but this datum may not yet be
1994 // available as we call the function on a separate task
1995 unsigned int n_levels = 0;
1996 if (level_objects > 0)
1997 // find the last level on which there are used cells
1998 for (unsigned int level = 0; level < level_objects; ++level)
1999 if (triangulation.begin(level) != triangulation.end(level))
2000 n_levels = level + 1;
2001
2002 number_cache.n_hexes_level.resize(n_levels);
2003 number_cache.n_active_hexes_level.resize(n_levels);
2004
2005 for (unsigned int level = 0; level < n_levels; ++level)
2006 {
2007 // count hexes on this level
2008 number_cache.n_hexes_level[level] = 0;
2009 number_cache.n_active_hexes_level[level] = 0;
2010
2011 hex_iterator hex = triangulation.begin_hex(level),
2012 endc = (level == n_levels - 1 ?
2013 hex_iterator(triangulation.end_hex()) :
2014 triangulation.begin_hex(level + 1));
2015 for (; hex != endc; ++hex)
2016 {
2017 ++number_cache.n_hexes_level[level];
2018 if (hex->has_children() == false)
2019 ++number_cache.n_active_hexes_level[level];
2020 }
2021
2022 // update total number of hexes
2023 number_cache.n_hexes += number_cache.n_hexes_level[level];
2024 number_cache.n_active_hexes +=
2025 number_cache.n_active_hexes_level[level];
2026 }
2027 }
2028 else
2029 {
2030 // for dim>3, there are no levels for hexes
2031 number_cache.n_hexes_level.clear();
2032 number_cache.n_active_hexes_level.clear();
2033
2034 hex_iterator hex = triangulation.begin_hex(),
2035 endc = triangulation.end_hex();
2036 for (; hex != endc; ++hex)
2037 {
2038 ++number_cache.n_hexes;
2039 if (hex->has_children() == false)
2040 ++number_cache.n_active_hexes;
2041 }
2042 }
2043
2044 // wait for the background computation for quads
2045 update_quads_and_lines.join();
2046 }
2047
2048
2049 template <int dim, int spacedim>
2050 static void
2053 const unsigned int level_objects,
2055 {
2056 compute_number_cache_dim(triangulation, level_objects, number_cache);
2057
2058 number_cache.active_cell_index_partitioner =
2059 std::make_shared<const Utilities::MPI::Partitioner>(
2060 triangulation.n_active_cells());
2061
2062 number_cache.level_cell_index_partitioners.resize(
2063 triangulation.n_levels());
2064 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
2065 number_cache.level_cell_index_partitioners[level] =
2066 std::make_shared<const Utilities::MPI::Partitioner>(
2067 triangulation.n_cells(level));
2068 }
2069
2070
2071 template <int spacedim>
2072 static void
2074 {}
2075
2076
2077 template <int dim, int spacedim>
2078 static void
2080 {
2081 // each face can be neighbored on two sides
2082 // by cells. according to the face's
2083 // intrinsic normal we define the left
2084 // neighbor as the one for which the face
2085 // normal points outward, and store that
2086 // one first; the second one is then
2087 // the right neighbor for which the
2088 // face normal points inward. This
2089 // information depends on the type of cell
2090 // and local number of face for the
2091 // 'standard ordering and orientation' of
2092 // faces and then on the face_orientation
2093 // information for the real mesh. Set up a
2094 // table to have fast access to those
2095 // offsets (0 for left and 1 for
2096 // right). Some of the values are invalid
2097 // as they reference too large face
2098 // numbers, but we just leave them at a
2099 // zero value.
2100 //
2101 // Note, that in 2d for lines as faces the
2102 // normal direction given in the
2103 // GeometryInfo class is not consistent. We
2104 // thus define here that the normal for a
2105 // line points to the right if the line
2106 // points upwards.
2107 //
2108 // There is one more point to
2109 // consider, however: if we have
2110 // dim<spacedim, then we may have
2111 // cases where cells are
2112 // inverted. In effect, both
2113 // cells think they are the left
2114 // neighbor of an edge, for
2115 // example, which leads us to
2116 // forget neighborship
2117 // information (a case that shows
2118 // this is
2119 // codim_one/hanging_nodes_02). We
2120 // store whether a cell is
2121 // inverted using the
2122 // direction_flag, so if a cell
2123 // has a false direction_flag,
2124 // then we need to invert our
2125 // selection whether we are a
2126 // left or right neighbor in all
2127 // following computations.
2128 //
2129 // first index: dimension (minus 2)
2130 // second index: local face index
2131 // third index: face_orientation (false and true)
2132 static const unsigned int left_right_offset[2][6][2] = {
2133 // quadrilateral
2134 {{0, 1}, // face 0, face_orientation = false and true
2135 {1, 0}, // face 1, face_orientation = false and true
2136 {1, 0}, // face 2, face_orientation = false and true
2137 {0, 1}, // face 3, face_orientation = false and true
2138 {0, 0}, // face 4, invalid face
2139 {0, 0}}, // face 5, invalid face
2140 // hexahedron
2141 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
2142
2143 // now create a vector of the two active
2144 // neighbors (left and right) for each face
2145 // and fill it by looping over all cells. For
2146 // cases with anisotropic refinement and more
2147 // then one cell neighboring at a given side
2148 // of the face we will automatically get the
2149 // active one on the highest level as we loop
2150 // over cells from lower levels first.
2152 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
2153 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
2154
2155 for (const auto &cell : triangulation.cell_iterators())
2156 for (auto f : cell->face_indices())
2157 {
2159 cell->face(f);
2160
2161 const unsigned int offset =
2162 (cell->direction_flag() ?
2163 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2164 1 -
2165 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2166
2167 adjacent_cells[2 * face->index() + offset] = cell;
2168
2169 // if this cell is not refined, but the
2170 // face is, then we'll have to set our
2171 // cell as neighbor for the child faces
2172 // as well. Fortunately the normal
2173 // orientation of children will be just
2174 // the same.
2175 if (dim == 2)
2176 {
2177 if (cell->is_active() && face->has_children())
2178 {
2179 adjacent_cells[2 * face->child(0)->index() + offset] =
2180 cell;
2181 adjacent_cells[2 * face->child(1)->index() + offset] =
2182 cell;
2183 }
2184 }
2185 else // -> dim == 3
2186 {
2187 // We need the same as in 2d
2188 // here. Furthermore, if the face is
2189 // refined with cut_x or cut_y then
2190 // those children again in the other
2191 // direction, and if this cell is
2192 // refined isotropically (along the
2193 // face) then the neighbor will
2194 // (probably) be refined as cut_x or
2195 // cut_y along the face. For those
2196 // neighboring children cells, their
2197 // neighbor will be the current,
2198 // inactive cell, as our children are
2199 // too fine to be neighbors. Catch that
2200 // case by also acting on inactive
2201 // cells with isotropic refinement
2202 // along the face. If the situation
2203 // described is not present, the data
2204 // will be overwritten later on when we
2205 // visit cells on finer levels, so no
2206 // harm will be done.
2207 if (face->has_children() &&
2208 (cell->is_active() ||
2210 cell->refinement_case(), f) ==
2211 RefinementCase<dim - 1>::isotropic_refinement))
2212 {
2213 for (unsigned int c = 0; c < face->n_children(); ++c)
2214 adjacent_cells[2 * face->child(c)->index() + offset] =
2215 cell;
2216 if (face->child(0)->has_children())
2217 {
2218 adjacent_cells[2 * face->child(0)->child(0)->index() +
2219 offset] = cell;
2220 adjacent_cells[2 * face->child(0)->child(1)->index() +
2221 offset] = cell;
2222 }
2223 if (face->child(1)->has_children())
2224 {
2225 adjacent_cells[2 * face->child(1)->child(0)->index() +
2226 offset] = cell;
2227 adjacent_cells[2 * face->child(1)->child(1)->index() +
2228 offset] = cell;
2229 }
2230 } // if cell active and face refined
2231 } // else -> dim==3
2232 } // for all faces of all cells
2233
2234 // now loop again over all cells and set the
2235 // corresponding neighbor cell. Note, that we
2236 // have to use the opposite of the
2237 // left_right_offset in this case as we want
2238 // the offset of the neighbor, not our own.
2239 for (const auto &cell : triangulation.cell_iterators())
2240 for (auto f : cell->face_indices())
2241 {
2242 const unsigned int offset =
2243 (cell->direction_flag() ?
2244 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2245 1 -
2246 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2247 cell->set_neighbor(
2248 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
2249 }
2250 }
2251
2252
2256 template <int dim, int spacedim>
2257 static void
2259 const std::vector<CellData<dim>> & cells,
2260 const SubCellData & subcelldata,
2262 {
2263 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
2264 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
2265
2266 // Check that all cells have positive volume.
2267#ifndef _MSC_VER
2268 // TODO: The following code does not compile with MSVC. Find a way
2269 // around it
2270 if (dim == spacedim)
2271 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
2272 {
2273 // If we should check for distorted cells, then we permit them
2274 // to exist. If a cell has negative measure, then it must be
2275 // distorted (the converse is not necessarily true); hence
2276 // throw an exception if no such cells should exist.
2278 {
2279 const double cell_measure = GridTools::cell_measure<spacedim>(
2280 vertices,
2281 ArrayView<const unsigned int>(cells[cell_no].vertices));
2282 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
2283 }
2284 }
2285#endif
2286
2287 // clear old content
2288 tria.levels.clear();
2289 tria.levels.push_back(
2290 std::make_unique<
2292
2293 if (dim > 1)
2294 tria.faces = std::make_unique<
2296
2297 // copy vertices
2299 tria.vertices_used.assign(vertices.size(), true);
2300
2301 // compute connectivity
2302 const auto connectivity = build_connectivity<unsigned int>(cells);
2303 const unsigned int n_cell = cells.size();
2304
2305 // TriaObjects: lines
2306 if (dim >= 2)
2307 {
2308 auto &lines_0 = tria.faces->lines; // data structure to be filled
2309
2310 // get connectivity between quads and lines
2311 const auto & crs = connectivity.entity_to_entities(1, 0);
2312 const unsigned int n_lines = crs.ptr.size() - 1;
2313
2314 // allocate memory
2315 reserve_space_(lines_0, n_lines);
2316
2317 // loop over lines
2318 for (unsigned int line = 0; line < n_lines; ++line)
2319 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
2320 ++i, ++j)
2321 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
2322 crs.col[i]; // set vertex indices
2323 }
2324
2325 // TriaObjects: quads
2326 if (dim == 3)
2327 {
2328 auto &quads_0 = tria.faces->quads; // data structures to be filled
2329 auto &faces = *tria.faces;
2330
2331 // get connectivity between quads and lines
2332 const auto & crs = connectivity.entity_to_entities(2, 1);
2333 const unsigned int n_quads = crs.ptr.size() - 1;
2334
2335 // allocate memory
2336 reserve_space_(quads_0, n_quads);
2337 reserve_space_(faces, 2 /*structdim*/, n_quads);
2338
2339 // loop over all quads -> entity type, line indices/orientations
2340 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
2341 {
2342 // set entity type of quads
2343 faces.set_quad_type(q, connectivity.entity_types(2)[q]);
2344
2345 // loop over all its lines
2346 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
2347 ++i, ++j, ++k)
2348 {
2349 // set line index
2350 quads_0.cells[q * GeometryInfo<3>::lines_per_face + j] =
2351 crs.col[i];
2352
2353 // set line orientations
2354 const unsigned char combined_orientation =
2355 connectivity.entity_orientations(1)
2356 .get_combined_orientation(k);
2357 // it doesn't make sense to set any flags except
2358 // orientation for a line
2359 Assert(
2360 combined_orientation ==
2362 combined_orientation ==
2365 faces.quads_line_orientations
2367 combined_orientation ==
2369 }
2370 }
2371 }
2372
2373 // TriaObjects/TriaLevel: cell
2374 {
2375 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
2376 auto &level = *tria.levels[0];
2377
2378 // get connectivity between cells/faces and cells/cells
2379 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2380 const auto &nei = connectivity.entity_to_entities(dim, dim);
2381
2382 // in 2d optional: since in in pure QUAD meshes same line
2383 // orientations can be guaranteed
2384 bool orientation_needed = false;
2385 if (dim == 3)
2386 orientation_needed = true;
2387 else if (dim == 2)
2388 {
2389 const auto &orientations = connectivity.entity_orientations(1);
2390 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
2391 if (orientations.get_combined_orientation(i) !=
2393 {
2394 orientation_needed = true;
2395 break;
2396 }
2397 }
2398
2399 // allocate memory
2400 reserve_space_(cells_0, n_cell);
2401 reserve_space_(level, spacedim, n_cell, orientation_needed);
2402
2403 // loop over all cells
2404 for (unsigned int cell = 0; cell < n_cell; ++cell)
2405 {
2406 // set material ids
2407 cells_0.boundary_or_material_id[cell].material_id =
2408 cells[cell].material_id;
2409
2410 // set manifold ids
2411 cells_0.manifold_id[cell] = cells[cell].manifold_id;
2412
2413 // set entity types
2414 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
2415
2416 // loop over faces
2417 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2418 ++i, ++j)
2419 {
2420 // set neighbor if not at boundary
2421 if (nei.col[i] != static_cast<unsigned int>(-1))
2422 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
2423 j] = {0, nei.col[i]};
2424
2425 // set face indices
2426 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
2427 crs.col[i];
2428
2429 // set face orientation if needed
2430 if (orientation_needed)
2431 {
2432 level.face_orientations.set_combined_orientation(
2434 connectivity.entity_orientations(dim - 1)
2435 .get_combined_orientation(i));
2436 }
2437 }
2438 }
2439 }
2440
2441 // TriaFaces: boundary id of boundary faces
2442 if (dim > 1)
2443 {
2444 auto &bids_face = dim == 3 ?
2445 tria.faces->quads.boundary_or_material_id :
2446 tria.faces->lines.boundary_or_material_id;
2447
2448 // count number of cells a face is belonging to
2449 std::vector<unsigned int> count(bids_face.size(), 0);
2450
2451 // get connectivity between cells/faces
2452 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2453
2454 // count how many cells are adjacent to the same face
2455 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2456 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
2457 count[crs.col[i]]++;
2458
2459 // loop over all faces
2460 for (unsigned int face = 0; face < count.size(); ++face)
2461 {
2462 if (count[face] != 1) // inner face
2463 continue;
2464
2465 // boundary faces ...
2466 bids_face[face].boundary_id = 0;
2467
2468 if (dim != 3)
2469 continue;
2470
2471 // ... and the lines of quads in 3d
2472 const auto &crs = connectivity.entity_to_entities(2, 1);
2473 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
2474 tria.faces->lines.boundary_or_material_id[crs.col[i]]
2475 .boundary_id = 0;
2476 }
2477 }
2478 else // 1d
2479 {
2480 static const unsigned int t_tba = static_cast<unsigned int>(-1);
2481 static const unsigned int t_inner = static_cast<unsigned int>(-2);
2482
2483 std::vector<unsigned int> type(vertices.size(), t_tba);
2484
2485 const auto &crs = connectivity.entity_to_entities(1, 0);
2486
2487 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2488 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2489 ++i, ++j)
2490 if (type[crs.col[i]] != t_inner)
2491 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
2492
2493 for (unsigned int face = 0; face < type.size(); ++face)
2494 {
2495 // note: we also treat manifolds here!?
2498 if (type[face] != t_inner && type[face] != t_tba)
2499 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
2500 }
2501 }
2502
2503 // SubCellData: line
2504 if (dim >= 2)
2505 process_subcelldata(connectivity.entity_to_entities(1, 0),
2506 tria.faces->lines,
2507 subcelldata.boundary_lines,
2508 vertices);
2509
2510 // SubCellData: quad
2511 if (dim == 3)
2512 process_subcelldata(connectivity.entity_to_entities(2, 0),
2513 tria.faces->quads,
2514 subcelldata.boundary_quads,
2515 vertices);
2516 }
2517
2518
2519 template <int structdim, int spacedim, typename T>
2520 static void
2522 const CRS<T> & crs,
2523 TriaObjects & obj,
2524 const std::vector<CellData<structdim>> &boundary_objects_in,
2525 const std::vector<Point<spacedim>> & vertex_locations)
2526 {
2527 AssertDimension(obj.structdim, structdim);
2528
2529 if (boundary_objects_in.size() == 0)
2530 return; // empty subcelldata -> nothing to do
2531
2532 // pre-sort subcelldata
2533 auto boundary_objects = boundary_objects_in;
2534
2535 // ... sort vertices
2536 for (auto &boundary_object : boundary_objects)
2537 std::sort(boundary_object.vertices.begin(),
2538 boundary_object.vertices.end());
2539
2540 // ... sort cells
2541 std::sort(boundary_objects.begin(),
2542 boundary_objects.end(),
2543 [](const auto &a, const auto &b) {
2544 return a.vertices < b.vertices;
2545 });
2546
2547 unsigned int counter = 0;
2548
2549 std::vector<unsigned int> key;
2551
2552 for (unsigned int o = 0; o < obj.n_objects(); ++o)
2553 {
2554 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
2555 auto &manifold_id = obj.manifold_id[o];
2556
2557 // assert that object has not been visited yet and its value
2558 // has not been modified yet
2559 AssertThrow(boundary_id == 0 ||
2564
2565 // create key
2566 key.assign(crs.col.data() + crs.ptr[o],
2567 crs.col.data() + crs.ptr[o + 1]);
2568 std::sort(key.begin(), key.end());
2569
2570 // is subcelldata provided? -> binary search
2571 const auto subcell_object =
2572 std::lower_bound(boundary_objects.begin(),
2573 boundary_objects.end(),
2574 key,
2575 [&](const auto &cell, const auto &key) {
2576 return cell.vertices < key;
2577 });
2578
2579 // no subcelldata provided for this object
2580 if (subcell_object == boundary_objects.end() ||
2581 subcell_object->vertices != key)
2582 continue;
2583
2584 counter++;
2585
2586 // set manifold id
2587 manifold_id = subcell_object->manifold_id;
2588
2589 // set boundary id
2590 if (subcell_object->boundary_id !=
2592 {
2593 (void)vertex_locations;
2596 ExcMessage(
2597 "The input arguments for creating a triangulation "
2598 "specified a boundary id for an internal face. This "
2599 "is not allowed."
2600 "\n\n"
2601 "The object in question has vertex indices " +
2602 [subcell_object]() {
2603 std::string s;
2604 for (const auto v : subcell_object->vertices)
2605 s += std::to_string(v) + ',';
2606 return s;
2607 }() +
2608 " which are located at positions " +
2609 [vertex_locations, subcell_object]() {
2610 std::ostringstream s;
2611 for (const auto v : subcell_object->vertices)
2612 s << '(' << vertex_locations[v] << ')';
2613 return s.str();
2614 }() +
2615 "."));
2616 boundary_id = subcell_object->boundary_id;
2617 }
2618 }
2619
2620 // make sure that all subcelldata entries have been processed
2621 // TODO: this is not guaranteed, why?
2622 // AssertDimension(counter, boundary_objects_in.size());
2623 (void)counter;
2624 }
2625
2626
2627
2628 static void
2630 const unsigned structdim,
2631 const unsigned int size)
2632 {
2633 const unsigned int dim = faces.dim;
2634
2635 const unsigned int max_lines_per_face = 2 * structdim;
2636
2637 if (dim == 3 && structdim == 2)
2638 {
2639 // quad entity types
2640 faces.quad_is_quadrilateral.assign(size, true);
2641
2642 // quad line orientations
2643 faces.quads_line_orientations.assign(size * max_lines_per_face,
2644 true);
2645 }
2646 }
2647
2648
2649
2650 static void
2652 const unsigned int spacedim,
2653 const unsigned int size,
2654 const bool orientation_needed)
2655 {
2656 const unsigned int dim = level.dim;
2657
2658 const unsigned int max_faces_per_cell = 2 * dim;
2659
2660 level.active_cell_indices.assign(size, -1);
2661 level.subdomain_ids.assign(size, 0);
2662 level.level_subdomain_ids.assign(size, 0);
2663
2664 level.refine_flags.assign(size, 0u);
2665 level.coarsen_flags.assign(size, false);
2666
2667 level.parents.assign((size + 1) / 2, -1);
2668
2669 if (dim < spacedim)
2670 level.direction_flags.assign(size, true);
2671
2672 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
2673
2674 level.reference_cell.assign(size, ReferenceCells::Invalid);
2675
2676 if (orientation_needed)
2677 level.face_orientations.reinit(size * max_faces_per_cell);
2678
2679
2680 level.global_active_cell_indices.assign(size,
2682 level.global_level_cell_indices.assign(size,
2684 }
2685
2686
2687
2688 static void
2689 reserve_space_(TriaObjects &obj, const unsigned int size)
2690 {
2691 const unsigned int structdim = obj.structdim;
2692
2693 const unsigned int max_children_per_cell = 1 << structdim;
2694 const unsigned int max_faces_per_cell = 2 * structdim;
2695
2696 obj.used.assign(size, true);
2697 obj.boundary_or_material_id.assign(
2698 size,
2700 BoundaryOrMaterialId());
2701 obj.manifold_id.assign(size, -1);
2702 obj.user_flags.assign(size, false);
2703 obj.user_data.resize(size);
2704
2705 if (structdim > 1) // TODO: why?
2706 obj.refinement_cases.assign(size, 0);
2707
2708 obj.children.assign(max_children_per_cell / 2 * size, -1);
2709
2710 obj.cells.assign(max_faces_per_cell * size, -1);
2711
2712 if (structdim <= 2)
2713 {
2714 obj.next_free_single = size - 1;
2715 obj.next_free_pair = 0;
2717 }
2718 else
2719 {
2720 obj.next_free_single = obj.next_free_pair = 0;
2721 }
2722 }
2723
2724
2740 template <int spacedim>
2741 static void
2744 std::vector<unsigned int> &,
2745 std::vector<unsigned int> &)
2746 {
2747 const unsigned int dim = 1;
2748
2749 // first we need to reset the
2750 // neighbor pointers of the
2751 // neighbors of this cell's
2752 // children to this cell. This is
2753 // different for one dimension,
2754 // since there neighbors can have a
2755 // refinement level differing from
2756 // that of this cell's children by
2757 // more than one level.
2758
2759 Assert(!cell->child(0)->has_children() &&
2760 !cell->child(1)->has_children(),
2762
2763 // first do it for the cells to the
2764 // left
2765 if (cell->neighbor(0).state() == IteratorState::valid)
2766 if (cell->neighbor(0)->has_children())
2767 {
2769 cell->neighbor(0);
2770 Assert(neighbor->level() == cell->level(), ExcInternalError());
2771
2772 // right child
2773 neighbor = neighbor->child(1);
2774 while (true)
2775 {
2776 Assert(neighbor->neighbor(1) == cell->child(0),
2778 neighbor->set_neighbor(1, cell);
2779
2780 // move on to further
2781 // children on the
2782 // boundary between this
2783 // cell and its neighbor
2784 if (neighbor->has_children())
2785 neighbor = neighbor->child(1);
2786 else
2787 break;
2788 }
2789 }
2790
2791 // now do it for the cells to the
2792 // left
2793 if (cell->neighbor(1).state() == IteratorState::valid)
2794 if (cell->neighbor(1)->has_children())
2795 {
2797 cell->neighbor(1);
2798 Assert(neighbor->level() == cell->level(), ExcInternalError());
2799
2800 // left child
2801 neighbor = neighbor->child(0);
2802 while (true)
2803 {
2804 Assert(neighbor->neighbor(0) == cell->child(1),
2806 neighbor->set_neighbor(0, cell);
2807
2808 // move on to further
2809 // children on the
2810 // boundary between this
2811 // cell and its neighbor
2812 if (neighbor->has_children())
2813 neighbor = neighbor->child(0);
2814 else
2815 break;
2816 }
2817 }
2818
2819
2820 // delete the vertex which will not
2821 // be needed anymore. This vertex
2822 // is the second of the first child
2823 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
2824
2825 // invalidate children. clear user
2826 // pointers, to avoid that they may
2827 // appear at unwanted places later
2828 // on...
2829 for (unsigned int child = 0; child < cell->n_children(); ++child)
2830 {
2831 cell->child(child)->clear_user_data();
2832 cell->child(child)->clear_user_flag();
2833 cell->child(child)->clear_used_flag();
2834 }
2835
2836
2837 // delete pointer to children
2838 cell->clear_children();
2839 cell->clear_user_flag();
2840 }
2841
2842
2843
2844 template <int spacedim>
2845 static void
2848 std::vector<unsigned int> &line_cell_count,
2849 std::vector<unsigned int> &)
2850 {
2851 const unsigned int dim = 2;
2852 const RefinementCase<dim> ref_case = cell->refinement_case();
2853
2854 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2856
2857 // vectors to hold all lines which
2858 // may be deleted
2859 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2860 lines_to_delete(0);
2861
2862 lines_to_delete.reserve(4 * 2 + 4);
2863
2864 // now we decrease the counters for
2865 // lines contained in the child
2866 // cells
2867 for (unsigned int c = 0; c < cell->n_children(); ++c)
2868 {
2870 cell->child(c);
2871 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
2872 --line_cell_count[child->line_index(l)];
2873 }
2874
2875
2876 // delete the vertex which will not
2877 // be needed anymore. This vertex
2878 // is the second of the second line
2879 // of the first child, if the cell
2880 // is refined with cut_xy, else there
2881 // is no inner vertex.
2882 // additionally delete unneeded inner
2883 // lines
2884 if (ref_case == RefinementCase<dim>::cut_xy)
2885 {
2887 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
2888
2889 lines_to_delete.push_back(cell->child(0)->line(1));
2890 lines_to_delete.push_back(cell->child(0)->line(3));
2891 lines_to_delete.push_back(cell->child(3)->line(0));
2892 lines_to_delete.push_back(cell->child(3)->line(2));
2893 }
2894 else
2895 {
2896 unsigned int inner_face_no =
2897 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
2898
2899 // the inner line will not be
2900 // used any more
2901 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
2902 }
2903
2904 // invalidate children
2905 for (unsigned int child = 0; child < cell->n_children(); ++child)
2906 {
2907 cell->child(child)->clear_user_data();
2908 cell->child(child)->clear_user_flag();
2909 cell->child(child)->clear_used_flag();
2910 }
2911
2912
2913 // delete pointer to children
2914 cell->clear_children();
2915 cell->clear_refinement_case();
2916 cell->clear_user_flag();
2917
2918 // look at the refinement of outer
2919 // lines. if nobody needs those
2920 // anymore we can add them to the
2921 // list of lines to be deleted.
2922 for (unsigned int line_no = 0;
2923 line_no < GeometryInfo<dim>::lines_per_cell;
2924 ++line_no)
2925 {
2927 cell->line(line_no);
2928
2929 if (line->has_children())
2930 {
2931 // if one of the cell counters is
2932 // zero, the other has to be as well
2933
2934 Assert((line_cell_count[line->child_index(0)] == 0 &&
2935 line_cell_count[line->child_index(1)] == 0) ||
2936 (line_cell_count[line->child_index(0)] > 0 &&
2937 line_cell_count[line->child_index(1)] > 0),
2939
2940 if (line_cell_count[line->child_index(0)] == 0)
2941 {
2942 for (unsigned int c = 0; c < 2; ++c)
2943 Assert(!line->child(c)->has_children(),
2945
2946 // we may delete the line's
2947 // children and the middle vertex
2948 // as no cell references them
2949 // anymore
2951 .vertices_used[line->child(0)->vertex_index(1)] = false;
2952
2953 lines_to_delete.push_back(line->child(0));
2954 lines_to_delete.push_back(line->child(1));
2955
2956 line->clear_children();
2957 }
2958 }
2959 }
2960
2961 // finally, delete unneeded lines
2962
2963 // clear user pointers, to avoid that
2964 // they may appear at unwanted places
2965 // later on...
2966 // same for user flags, then finally
2967 // delete the lines
2968 typename std::vector<
2970 line = lines_to_delete.begin(),
2971 endline = lines_to_delete.end();
2972 for (; line != endline; ++line)
2973 {
2974 (*line)->clear_user_data();
2975 (*line)->clear_user_flag();
2976 (*line)->clear_used_flag();
2977 }
2978 }
2979
2980
2981
2982 template <int spacedim>
2983 static void
2986 std::vector<unsigned int> &line_cell_count,
2987 std::vector<unsigned int> &quad_cell_count)
2988 {
2989 const unsigned int dim = 3;
2990
2991 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2993 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
2995
2996 // first of all, we store the RefineCase of
2997 // this cell
2998 const RefinementCase<dim> ref_case = cell->refinement_case();
2999 // vectors to hold all lines and quads which
3000 // may be deleted
3001 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3002 lines_to_delete(0);
3003 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3004 quads_to_delete(0);
3005
3006 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3007 quads_to_delete.reserve(6 * 4 + 12);
3008
3009 // now we decrease the counters for lines and
3010 // quads contained in the child cells
3011 for (unsigned int c = 0; c < cell->n_children(); ++c)
3012 {
3014 cell->child(c);
3015 const auto line_indices = TriaAccessorImplementation::
3016 Implementation::get_line_indices_of_cell(*child);
3017 for (const unsigned int l : cell->line_indices())
3018 --line_cell_count[line_indices[l]];
3019 for (auto f : GeometryInfo<dim>::face_indices())
3020 --quad_cell_count[child->quad_index(f)];
3021 }
3022
3023 //-------------------------------------
3024 // delete interior quads and lines and the
3025 // interior vertex, depending on the
3026 // refinement case of the cell
3027 //
3028 // for append quads and lines: only append
3029 // them to the list of objects to be deleted
3030
3031 switch (ref_case)
3032 {
3034 quads_to_delete.push_back(cell->child(0)->face(1));
3035 break;
3037 quads_to_delete.push_back(cell->child(0)->face(3));
3038 break;
3040 quads_to_delete.push_back(cell->child(0)->face(5));
3041 break;
3043 quads_to_delete.push_back(cell->child(0)->face(1));
3044 quads_to_delete.push_back(cell->child(0)->face(3));
3045 quads_to_delete.push_back(cell->child(3)->face(0));
3046 quads_to_delete.push_back(cell->child(3)->face(2));
3047
3048 lines_to_delete.push_back(cell->child(0)->line(11));
3049 break;
3051 quads_to_delete.push_back(cell->child(0)->face(1));
3052 quads_to_delete.push_back(cell->child(0)->face(5));
3053 quads_to_delete.push_back(cell->child(3)->face(0));
3054 quads_to_delete.push_back(cell->child(3)->face(4));
3055
3056 lines_to_delete.push_back(cell->child(0)->line(5));
3057 break;
3059 quads_to_delete.push_back(cell->child(0)->face(3));
3060 quads_to_delete.push_back(cell->child(0)->face(5));
3061 quads_to_delete.push_back(cell->child(3)->face(2));
3062 quads_to_delete.push_back(cell->child(3)->face(4));
3063
3064 lines_to_delete.push_back(cell->child(0)->line(7));
3065 break;
3067 quads_to_delete.push_back(cell->child(0)->face(1));
3068 quads_to_delete.push_back(cell->child(2)->face(1));
3069 quads_to_delete.push_back(cell->child(4)->face(1));
3070 quads_to_delete.push_back(cell->child(6)->face(1));
3071
3072 quads_to_delete.push_back(cell->child(0)->face(3));
3073 quads_to_delete.push_back(cell->child(1)->face(3));
3074 quads_to_delete.push_back(cell->child(4)->face(3));
3075 quads_to_delete.push_back(cell->child(5)->face(3));
3076
3077 quads_to_delete.push_back(cell->child(0)->face(5));
3078 quads_to_delete.push_back(cell->child(1)->face(5));
3079 quads_to_delete.push_back(cell->child(2)->face(5));
3080 quads_to_delete.push_back(cell->child(3)->face(5));
3081
3082 lines_to_delete.push_back(cell->child(0)->line(5));
3083 lines_to_delete.push_back(cell->child(0)->line(7));
3084 lines_to_delete.push_back(cell->child(0)->line(11));
3085 lines_to_delete.push_back(cell->child(7)->line(0));
3086 lines_to_delete.push_back(cell->child(7)->line(2));
3087 lines_to_delete.push_back(cell->child(7)->line(8));
3088 // delete the vertex which will not
3089 // be needed anymore. This vertex
3090 // is the vertex at the heart of
3091 // this cell, which is the sixth of
3092 // the first child
3093 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
3094 false;
3095 break;
3096 default:
3097 // only remaining case is
3098 // no_refinement, thus an error
3099 Assert(false, ExcInternalError());
3100 break;
3101 }
3102
3103
3104 // invalidate children
3105 for (unsigned int child = 0; child < cell->n_children(); ++child)
3106 {
3107 cell->child(child)->clear_user_data();
3108 cell->child(child)->clear_user_flag();
3109
3110 for (auto f : GeometryInfo<dim>::face_indices())
3111 // set flags denoting deviations from standard orientation of
3112 // faces back to initialization values
3113 cell->child(child)->set_combined_face_orientation(
3115
3116 cell->child(child)->clear_used_flag();
3117 }
3118
3119
3120 // delete pointer to children
3121 cell->clear_children();
3122 cell->clear_refinement_case();
3123 cell->clear_user_flag();
3124
3125 // so far we only looked at inner quads,
3126 // lines and vertices. Now we have to
3127 // consider outer ones as well. here, we have
3128 // to check, whether there are other cells
3129 // still needing these objects. otherwise we
3130 // can delete them. first for quads (and
3131 // their inner lines).
3132
3133 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
3134 {
3136 cell->face(quad_no);
3137
3138 Assert(
3139 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
3140 quad->has_children()) ||
3141 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
3144
3145 switch (quad->refinement_case())
3146 {
3147 case RefinementCase<dim - 1>::no_refinement:
3148 // nothing to do as the quad
3149 // is not refined
3150 break;
3151 case RefinementCase<dim - 1>::cut_x:
3152 case RefinementCase<dim - 1>::cut_y:
3153 {
3154 // if one of the cell counters is
3155 // zero, the other has to be as
3156 // well
3157 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3158 quad_cell_count[quad->child_index(1)] == 0) ||
3159 (quad_cell_count[quad->child_index(0)] > 0 &&
3160 quad_cell_count[quad->child_index(1)] > 0),
3162 // it might be, that the quad is
3163 // refined twice anisotropically,
3164 // first check, whether we may
3165 // delete possible grand_children
3166 unsigned int deleted_grandchildren = 0;
3167 unsigned int number_of_child_refinements = 0;
3168
3169 for (unsigned int c = 0; c < 2; ++c)
3170 if (quad->child(c)->has_children())
3171 {
3172 ++number_of_child_refinements;
3173 // if one of the cell counters is
3174 // zero, the other has to be as
3175 // well
3176 Assert(
3177 (quad_cell_count[quad->child(c)->child_index(0)] ==
3178 0 &&
3179 quad_cell_count[quad->child(c)->child_index(1)] ==
3180 0) ||
3181 (quad_cell_count[quad->child(c)->child_index(0)] >
3182 0 &&
3183 quad_cell_count[quad->child(c)->child_index(1)] >
3184 0),
3186 if (quad_cell_count[quad->child(c)->child_index(0)] ==
3187 0)
3188 {
3189 // Assert, that the two
3190 // anisotropic
3191 // refinements add up to
3192 // isotropic refinement
3193 Assert(quad->refinement_case() +
3194 quad->child(c)->refinement_case() ==
3197 // we may delete the
3198 // quad's children and
3199 // the inner line as no
3200 // cell references them
3201 // anymore
3202 quads_to_delete.push_back(
3203 quad->child(c)->child(0));
3204 quads_to_delete.push_back(
3205 quad->child(c)->child(1));
3206 if (quad->child(c)->refinement_case() ==
3208 lines_to_delete.push_back(
3209 quad->child(c)->child(0)->line(1));
3210 else
3211 lines_to_delete.push_back(
3212 quad->child(c)->child(0)->line(3));
3213 quad->child(c)->clear_children();
3214 quad->child(c)->clear_refinement_case();
3215 ++deleted_grandchildren;
3216 }
3217 }
3218 // if no grandchildren are left, we
3219 // may as well delete the
3220 // refinement of the inner line
3221 // between our children and the
3222 // corresponding vertex
3223 if (number_of_child_refinements > 0 &&
3224 deleted_grandchildren == number_of_child_refinements)
3225 {
3227 middle_line;
3228 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3229 middle_line = quad->child(0)->line(1);
3230 else
3231 middle_line = quad->child(0)->line(3);
3232
3233 lines_to_delete.push_back(middle_line->child(0));
3234 lines_to_delete.push_back(middle_line->child(1));
3236 .vertices_used[middle_vertex_index<dim, spacedim>(
3237 middle_line)] = false;
3238 middle_line->clear_children();
3239 }
3240
3241 // now consider the direct children
3242 // of the given quad
3243 if (quad_cell_count[quad->child_index(0)] == 0)
3244 {
3245 // we may delete the quad's
3246 // children and the inner line
3247 // as no cell references them
3248 // anymore
3249 quads_to_delete.push_back(quad->child(0));
3250 quads_to_delete.push_back(quad->child(1));
3251 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3252 lines_to_delete.push_back(quad->child(0)->line(1));
3253 else
3254 lines_to_delete.push_back(quad->child(0)->line(3));
3255
3256 // if the counters just dropped
3257 // to zero, otherwise the
3258 // children would have been
3259 // deleted earlier, then this
3260 // cell's children must have
3261 // contained the anisotropic
3262 // quad children. thus, if
3263 // those have again anisotropic
3264 // children, which are in
3265 // effect isotropic children of
3266 // the original quad, those are
3267 // still needed by a
3268 // neighboring cell and we
3269 // cannot delete them. instead,
3270 // we have to reset this quad's
3271 // refine case to isotropic and
3272 // set the children
3273 // accordingly.
3274 if (quad->child(0)->has_children())
3275 if (quad->refinement_case() ==
3277 {
3278 // now evereything is
3279 // quite complicated. we
3280 // have the children
3281 // numbered according to
3282 //
3283 // *---*---*
3284 // |n+1|m+1|
3285 // *---*---*
3286 // | n | m |
3287 // *---*---*
3288 //
3289 // from the original
3290 // anisotropic
3291 // refinement. we have to
3292 // reorder them as
3293 //
3294 // *---*---*
3295 // | m |m+1|
3296 // *---*---*
3297 // | n |n+1|
3298 // *---*---*
3299 //
3300 // for isotropic refinement.
3301 //
3302 // this is a bit ugly, of
3303 // course: loop over all
3304 // cells on all levels
3305 // and look for faces n+1
3306 // (switch_1) and m
3307 // (switch_2).
3308 const typename Triangulation<dim, spacedim>::
3309 quad_iterator switch_1 =
3310 quad->child(0)->child(1),
3311 switch_2 =
3312 quad->child(1)->child(0);
3313
3314 Assert(!switch_1->has_children(),
3316 Assert(!switch_2->has_children(),
3318
3319 const int switch_1_index = switch_1->index();
3320 const int switch_2_index = switch_2->index();
3321 for (unsigned int l = 0;
3322 l < triangulation.levels.size();
3323 ++l)
3324 for (unsigned int h = 0;
3325 h <
3326 triangulation.levels[l]->cells.n_objects();
3327 ++h)
3328 for (const unsigned int q :
3330 {
3331 const int index =
3332 triangulation.levels[l]
3333 ->cells.get_bounding_object_indices(
3334 h)[q];
3335 if (index == switch_1_index)
3336 triangulation.levels[l]
3337 ->cells.get_bounding_object_indices(
3338 h)[q] = switch_2_index;
3339 else if (index == switch_2_index)
3340 triangulation.levels[l]
3341 ->cells.get_bounding_object_indices(
3342 h)[q] = switch_1_index;
3343 }
3344 // now we have to copy
3345 // all information of the
3346 // two quads
3347 const int switch_1_lines[4] = {
3348 static_cast<signed int>(
3349 switch_1->line_index(0)),
3350 static_cast<signed int>(
3351 switch_1->line_index(1)),
3352 static_cast<signed int>(
3353 switch_1->line_index(2)),
3354 static_cast<signed int>(
3355 switch_1->line_index(3))};
3356 const bool switch_1_line_orientations[4] = {
3357 switch_1->line_orientation(0),
3358 switch_1->line_orientation(1),
3359 switch_1->line_orientation(2),
3360 switch_1->line_orientation(3)};
3361 const types::boundary_id switch_1_boundary_id =
3362 switch_1->boundary_id();
3363 const unsigned int switch_1_user_index =
3364 switch_1->user_index();
3365 const bool switch_1_user_flag =
3366 switch_1->user_flag_set();
3367
3368 switch_1->set_bounding_object_indices(
3369 {switch_2->line_index(0),
3370 switch_2->line_index(1),
3371 switch_2->line_index(2),
3372 switch_2->line_index(3)});
3373 switch_1->set_line_orientation(
3374 0, switch_2->line_orientation(0));
3375 switch_1->set_line_orientation(
3376 1, switch_2->line_orientation(1));
3377 switch_1->set_line_orientation(
3378 2, switch_2->line_orientation(2));
3379 switch_1->set_line_orientation(
3380 3, switch_2->line_orientation(3));
3381 switch_1->set_boundary_id_internal(
3382 switch_2->boundary_id());
3383 switch_1->set_manifold_id(
3384 switch_2->manifold_id());
3385 switch_1->set_user_index(switch_2->user_index());
3386 if (switch_2->user_flag_set())
3387 switch_1->set_user_flag();
3388 else
3389 switch_1->clear_user_flag();
3390
3391 switch_2->set_bounding_object_indices(
3392 {switch_1_lines[0],
3393 switch_1_lines[1],
3394 switch_1_lines[2],
3395 switch_1_lines[3]});
3396 switch_2->set_line_orientation(
3397 0, switch_1_line_orientations[0]);
3398 switch_2->set_line_orientation(
3399 1, switch_1_line_orientations[1]);
3400 switch_2->set_line_orientation(
3401 2, switch_1_line_orientations[2]);
3402 switch_2->set_line_orientation(
3403 3, switch_1_line_orientations[3]);
3404 switch_2->set_boundary_id_internal(
3405 switch_1_boundary_id);
3406 switch_2->set_manifold_id(
3407 switch_1->manifold_id());
3408 switch_2->set_user_index(switch_1_user_index);
3409 if (switch_1_user_flag)
3410 switch_2->set_user_flag();
3411 else
3412 switch_2->clear_user_flag();
3413
3414 const unsigned int child_0 =
3415 quad->child(0)->child_index(0);
3416 const unsigned int child_2 =
3417 quad->child(1)->child_index(0);
3418 quad->clear_children();
3419 quad->clear_refinement_case();
3420 quad->set_refinement_case(
3422 quad->set_children(0, child_0);
3423 quad->set_children(2, child_2);
3424 std::swap(quad_cell_count[child_0 + 1],
3425 quad_cell_count[child_2]);
3426 }
3427 else
3428 {
3429 // the face was refined
3430 // with cut_y, thus the
3431 // children are already
3432 // in correct order. we
3433 // only have to set them
3434 // correctly, deleting
3435 // the indirection of two
3436 // anisotropic refinement
3437 // and going directly
3438 // from the quad to
3439 // isotropic children
3440 const unsigned int child_0 =
3441 quad->child(0)->child_index(0);
3442 const unsigned int child_2 =
3443 quad->child(1)->child_index(0);
3444 quad->clear_children();
3445 quad->clear_refinement_case();
3446 quad->set_refinement_case(
3448 quad->set_children(0, child_0);
3449 quad->set_children(2, child_2);
3450 }
3451 else
3452 {
3453 quad->clear_children();
3454 quad->clear_refinement_case();
3455 }
3456 }
3457 break;
3458 }
3459 case RefinementCase<dim - 1>::cut_xy:
3460 {
3461 // if one of the cell counters is
3462 // zero, the others have to be as
3463 // well
3464
3465 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3466 quad_cell_count[quad->child_index(1)] == 0 &&
3467 quad_cell_count[quad->child_index(2)] == 0 &&
3468 quad_cell_count[quad->child_index(3)] == 0) ||
3469 (quad_cell_count[quad->child_index(0)] > 0 &&
3470 quad_cell_count[quad->child_index(1)] > 0 &&
3471 quad_cell_count[quad->child_index(2)] > 0 &&
3472 quad_cell_count[quad->child_index(3)] > 0),
3474
3475 if (quad_cell_count[quad->child_index(0)] == 0)
3476 {
3477 // we may delete the quad's
3478 // children, the inner lines
3479 // and the middle vertex as no
3480 // cell references them anymore
3481 lines_to_delete.push_back(quad->child(0)->line(1));
3482 lines_to_delete.push_back(quad->child(3)->line(0));
3483 lines_to_delete.push_back(quad->child(0)->line(3));
3484 lines_to_delete.push_back(quad->child(3)->line(2));
3485
3486 for (unsigned int child = 0; child < quad->n_children();
3487 ++child)
3488 quads_to_delete.push_back(quad->child(child));
3489
3491 .vertices_used[quad->child(0)->vertex_index(3)] =
3492 false;
3493
3494 quad->clear_children();
3495 quad->clear_refinement_case();
3496 }
3497 }
3498 break;
3499
3500 default:
3501 Assert(false, ExcInternalError());
3502 break;
3503 }
3504 }
3505
3506 // now we repeat a similar procedure
3507 // for the outer lines of this cell.
3508
3509 // if in debug mode: check that each
3510 // of the lines for which we consider
3511 // deleting the children in fact has
3512 // children (the bits/coarsening_3d
3513 // test tripped over this initially)
3514 for (unsigned int line_no = 0;
3515 line_no < GeometryInfo<dim>::lines_per_cell;
3516 ++line_no)
3517 {
3519 cell->line(line_no);
3520
3521 Assert(
3522 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
3523 line->has_children()) ||
3524 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
3527
3528 if (line->has_children())
3529 {
3530 // if one of the cell counters is
3531 // zero, the other has to be as well
3532
3533 Assert((line_cell_count[line->child_index(0)] == 0 &&
3534 line_cell_count[line->child_index(1)] == 0) ||
3535 (line_cell_count[line->child_index(0)] > 0 &&
3536 line_cell_count[line->child_index(1)] > 0),
3538
3539 if (line_cell_count[line->child_index(0)] == 0)
3540 {
3541 for (unsigned int c = 0; c < 2; ++c)
3542 Assert(!line->child(c)->has_children(),
3544
3545 // we may delete the line's
3546 // children and the middle vertex
3547 // as no cell references them
3548 // anymore
3550 .vertices_used[line->child(0)->vertex_index(1)] = false;
3551
3552 lines_to_delete.push_back(line->child(0));
3553 lines_to_delete.push_back(line->child(1));
3554
3555 line->clear_children();
3556 }
3557 }
3558 }
3559
3560 // finally, delete unneeded quads and lines
3561
3562 // clear user pointers, to avoid that
3563 // they may appear at unwanted places
3564 // later on...
3565 // same for user flags, then finally
3566 // delete the quads and lines
3567 typename std::vector<
3569 line = lines_to_delete.begin(),
3570 endline = lines_to_delete.end();
3571 for (; line != endline; ++line)
3572 {
3573 (*line)->clear_user_data();
3574 (*line)->clear_user_flag();
3575 (*line)->clear_used_flag();
3576 }
3577
3578 typename std::vector<
3580 quad = quads_to_delete.begin(),
3581 endquad = quads_to_delete.end();
3582 for (; quad != endquad; ++quad)
3583 {
3584 (*quad)->clear_user_data();
3585 (*quad)->clear_children();
3586 (*quad)->clear_refinement_case();
3587 (*quad)->clear_user_flag();
3588 (*quad)->clear_used_flag();
3589 }
3590 }
3591
3592
3610 template <int spacedim>
3611 static void
3614 unsigned int & next_unused_vertex,
3616 &next_unused_line,
3618 &next_unused_cell,
3619 const typename Triangulation<2, spacedim>::cell_iterator &cell)
3620 {
3621 const unsigned int dim = 2;
3622 // clear refinement flag
3623 const RefinementCase<dim> ref_case = cell->refine_flag_set();
3624 cell->clear_refine_flag();
3625
3626 /* For the refinement process: since we go the levels up from the
3627 lowest, there are (unlike above) only two possibilities: a neighbor
3628 cell is on the same level or one level up (in both cases, it may or
3629 may not be refined later on, but we don't care here).
3630
3631 First:
3632 Set up an array of the 3x3 vertices, which are distributed on the
3633 cell (the array consists of indices into the @p{vertices} std::vector
3634
3635 2--7--3
3636 | | |
3637 4--8--5
3638 | | |
3639 0--6--1
3640
3641 note: in case of cut_x or cut_y not all these vertices are needed for
3642 the new cells
3643
3644 Second:
3645 Set up an array of the new lines (the array consists of iterator
3646 pointers into the lines arrays)
3647
3648 .-6-.-7-. The directions are: .->-.->-.
3649 1 9 3 ^ ^ ^
3650 .-10.11-. .->-.->-.
3651 0 8 2 ^ ^ ^
3652 .-4-.-5-. .->-.->-.
3653
3654 cut_x:
3655 .-4-.-5-.
3656 | | |
3657 0 6 1
3658 | | |
3659 .-2-.-3-.
3660
3661 cut_y:
3662 .---5---.
3663 1 3
3664 .---6---.
3665 0 2
3666 .---4---.
3667
3668
3669 Third:
3670 Set up an array of neighbors:
3671
3672 6 7
3673 .--.--.
3674 1| | |3
3675 .--.--.
3676 0| | |2
3677 .--.--.
3678 4 5
3679
3680 We need this array for two reasons: first to get the lines which will
3681 bound the four subcells (if the neighboring cell is refined, these
3682 lines already exist), and second to update neighborship information.
3683 Since if a neighbor is not refined, its neighborship record only
3684 points to the present, unrefined, cell rather than the children we
3685 are presently creating, we only need the neighborship information
3686 if the neighbor cells are refined. In all other cases, we store
3687 the unrefined neighbor address
3688
3689 We also need for every neighbor (if refined) which number among its
3690 neighbors the present (unrefined) cell has, since that number is to
3691 be replaced and because that also is the number of the subline which
3692 will be the interface between that neighbor and the to be created
3693 cell. We will store this number (between 0 and 3) in the field
3694 @p{neighbors_neighbor}.
3695
3696 It would be sufficient to use the children of the common line to the
3697 neighbor, if we only wanted to get the new sublines and the new
3698 vertex, but because we need to update the neighborship information of
3699 the two refined subcells of the neighbor, we need to search these
3700 anyway.
3701
3702 Convention:
3703 The created children are numbered like this:
3704
3705 .--.--.
3706 |2 . 3|
3707 .--.--.
3708 |0 | 1|
3709 .--.--.
3710 */
3711 // collect the indices of the eight surrounding vertices
3712 // 2--7--3
3713 // | | |
3714 // 4--8--5
3715 // | | |
3716 // 0--6--1
3717 int new_vertices[9];
3718 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
3719 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
3720 for (unsigned int line_no = 0; line_no < 4; ++line_no)
3721 if (cell->line(line_no)->has_children())
3722 new_vertices[4 + line_no] =
3723 cell->line(line_no)->child(0)->vertex_index(1);
3724
3725 if (ref_case == RefinementCase<dim>::cut_xy)
3726 {
3727 // find the next
3728 // unused vertex and
3729 // allocate it for
3730 // the new vertex we
3731 // need here
3732 while (triangulation.vertices_used[next_unused_vertex] == true)
3733 ++next_unused_vertex;
3734 Assert(next_unused_vertex < triangulation.vertices.size(),
3735 ExcMessage(
3736 "Internal error: During refinement, the triangulation "
3737 "wants to access an element of the 'vertices' array "
3738 "but it turns out that the array is not large enough."));
3739 triangulation.vertices_used[next_unused_vertex] = true;
3740
3741 new_vertices[8] = next_unused_vertex;
3742
3743 // determine middle vertex by transfinite interpolation to be
3744 // consistent with what happens to quads in a
3745 // Triangulation<3,3> when they are refined
3746 triangulation.vertices[next_unused_vertex] =
3747 cell->center(true, true);
3748 }
3749
3750
3751 // Now the lines:
3753 unsigned int lmin = 8;
3754 unsigned int lmax = 12;
3755 if (ref_case != RefinementCase<dim>::cut_xy)
3756 {
3757 lmin = 6;
3758 lmax = 7;
3759 }
3760
3761 for (unsigned int l = lmin; l < lmax; ++l)
3762 {
3763 while (next_unused_line->used() == true)
3764 ++next_unused_line;
3765 new_lines[l] = next_unused_line;
3766 ++next_unused_line;
3767
3768 AssertIsNotUsed(new_lines[l]);
3769 }
3770
3771 if (ref_case == RefinementCase<dim>::cut_xy)
3772 {
3773 // .-6-.-7-.
3774 // 1 9 3
3775 // .-10.11-.
3776 // 0 8 2
3777 // .-4-.-5-.
3778
3779 // lines 0-7 already exist, create only the four interior
3780 // lines 8-11
3781 unsigned int l = 0;
3782 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
3783 for (unsigned int c = 0; c < 2; ++c, ++l)
3784 new_lines[l] = cell->line(face_no)->child(c);
3785 Assert(l == 8, ExcInternalError());
3786
3787 new_lines[8]->set_bounding_object_indices(
3788 {new_vertices[6], new_vertices[8]});
3789 new_lines[9]->set_bounding_object_indices(
3790 {new_vertices[8], new_vertices[7]});
3791 new_lines[10]->set_bounding_object_indices(
3792 {new_vertices[4], new_vertices[8]});
3793 new_lines[11]->set_bounding_object_indices(
3794 {new_vertices[8], new_vertices[5]});
3795 }
3796 else if (ref_case == RefinementCase<dim>::cut_x)
3797 {
3798 // .-4-.-5-.
3799 // | | |
3800 // 0 6 1
3801 // | | |
3802 // .-2-.-3-.
3803 new_lines[0] = cell->line(0);
3804 new_lines[1] = cell->line(1);
3805 new_lines[2] = cell->line(2)->child(0);
3806 new_lines[3] = cell->line(2)->child(1);
3807 new_lines[4] = cell->line(3)->child(0);
3808 new_lines[5] = cell->line(3)->child(1);
3809 new_lines[6]->set_bounding_object_indices(
3810 {new_vertices[6], new_vertices[7]});
3811 }
3812 else
3813 {
3815 // .---5---.
3816 // 1 3
3817 // .---6---.
3818 // 0 2
3819 // .---4---.
3820 new_lines[0] = cell->line(0)->child(0);
3821 new_lines[1] = cell->line(0)->child(1);
3822 new_lines[2] = cell->line(1)->child(0);
3823 new_lines[3] = cell->line(1)->child(1);
3824 new_lines[4] = cell->line(2);
3825 new_lines[5] = cell->line(3);
3826 new_lines[6]->set_bounding_object_indices(
3827 {new_vertices[4], new_vertices[5]});
3828 }
3829
3830 for (unsigned int l = lmin; l < lmax; ++l)
3831 {
3832 new_lines[l]->set_used_flag();
3833 new_lines[l]->clear_user_flag();
3834 new_lines[l]->clear_user_data();
3835 new_lines[l]->clear_children();
3836 // interior line
3837 new_lines[l]->set_boundary_id_internal(
3839 new_lines[l]->set_manifold_id(cell->manifold_id());
3840 }
3841
3842 // Now add the four (two)
3843 // new cells!
3846 while (next_unused_cell->used() == true)
3847 ++next_unused_cell;
3848
3849 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
3850 for (unsigned int i = 0; i < n_children; ++i)
3851 {
3852 AssertIsNotUsed(next_unused_cell);
3853 subcells[i] = next_unused_cell;
3854 ++next_unused_cell;
3855 if (i % 2 == 1 && i < n_children - 1)
3856 while (next_unused_cell->used() == true)
3857 ++next_unused_cell;
3858 }
3859
3860 if (ref_case == RefinementCase<dim>::cut_xy)
3861 {
3862 // children:
3863 // .--.--.
3864 // |2 . 3|
3865 // .--.--.
3866 // |0 | 1|
3867 // .--.--.
3868 // lines:
3869 // .-6-.-7-.
3870 // 1 9 3
3871 // .-10.11-.
3872 // 0 8 2
3873 // .-4-.-5-.
3874 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3875 new_lines[8]->index(),
3876 new_lines[4]->index(),
3877 new_lines[10]->index()});
3878 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
3879 new_lines[2]->index(),
3880 new_lines[5]->index(),
3881 new_lines[11]->index()});
3882 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
3883 new_lines[9]->index(),
3884 new_lines[10]->index(),
3885 new_lines[6]->index()});
3886 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
3887 new_lines[3]->index(),
3888 new_lines[11]->index(),
3889 new_lines[7]->index()});
3890 }
3891 else if (ref_case == RefinementCase<dim>::cut_x)
3892 {
3893 // children:
3894 // .--.--.
3895 // | . |
3896 // .0 . 1.
3897 // | | |
3898 // .--.--.
3899 // lines:
3900 // .-4-.-5-.
3901 // | | |
3902 // 0 6 1
3903 // | | |
3904 // .-2-.-3-.
3905 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3906 new_lines[6]->index(),
3907 new_lines[2]->index(),
3908 new_lines[4]->index()});
3909 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
3910 new_lines[1]->index(),
3911 new_lines[3]->index(),
3912 new_lines[5]->index()});
3913 }
3914 else
3915 {
3917 // children:
3918 // .-----.
3919 // | 1 |
3920 // .-----.
3921 // | 0 |
3922 // .-----.
3923 // lines:
3924 // .---5---.
3925 // 1 3
3926 // .---6---.
3927 // 0 2
3928 // .---4---.
3929 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3930 new_lines[2]->index(),
3931 new_lines[4]->index(),
3932 new_lines[6]->index()});
3933 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
3934 new_lines[3]->index(),
3935 new_lines[6]->index(),
3936 new_lines[5]->index()});
3937 }
3938
3939 types::subdomain_id subdomainid = cell->subdomain_id();
3940
3941 for (unsigned int i = 0; i < n_children; ++i)
3942 {
3943 subcells[i]->set_used_flag();
3944 subcells[i]->clear_refine_flag();
3945 subcells[i]->clear_user_flag();
3946 subcells[i]->clear_user_data();
3947 subcells[i]->clear_children();
3948 // inherit material properties
3949 subcells[i]->set_material_id(cell->material_id());
3950 subcells[i]->set_manifold_id(cell->manifold_id());
3951 subcells[i]->set_subdomain_id(subdomainid);
3952
3953 if (i % 2 == 0)
3954 subcells[i]->set_parent(cell->index());
3955 }
3956
3957
3958
3959 // set child index for even children i=0,2 (0)
3960 for (unsigned int i = 0; i < n_children / 2; ++i)
3961 cell->set_children(2 * i, subcells[2 * i]->index());
3962 // set the refine case
3963 cell->set_refinement_case(ref_case);
3964
3965 // note that the
3966 // refinement flag was
3967 // already cleared at the
3968 // beginning of this function
3969
3970 if (dim < spacedim)
3971 for (unsigned int c = 0; c < n_children; ++c)
3972 cell->child(c)->set_direction_flag(cell->direction_flag());
3973 }
3974
3975
3976
3977 template <int dim, int spacedim>
3980 const bool check_for_distorted_cells)
3981 {
3982 AssertDimension(dim, 2);
3983
3984 // Check whether a new level is needed. We have to check for
3985 // this on the highest level only
3986 for (const auto &cell : triangulation.active_cell_iterators_on_level(
3987 triangulation.levels.size() - 1))
3988 if (cell->refine_flag_set())
3989 {
3990 triangulation.levels.push_back(
3991 std::make_unique<
3993 break;
3994 }
3995
3997 triangulation.begin_line();
3998 line != triangulation.end_line();
3999 ++line)
4000 {
4001 line->clear_user_flag();
4002 line->clear_user_data();
4003 }
4004
4005 unsigned int n_single_lines = 0;
4006 unsigned int n_lines_in_pairs = 0;
4007 unsigned int needed_vertices = 0;
4008
4009 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4010 {
4011 // count number of flagged cells on this level and compute
4012 // how many new vertices and new lines will be needed
4013 unsigned int needed_cells = 0;
4014
4015 for (const auto &cell :
4016 triangulation.active_cell_iterators_on_level(level))
4017 if (cell->refine_flag_set())
4018 {
4019 if (cell->reference_cell() == ReferenceCells::Triangle)
4020 {
4021 needed_cells += 4;
4022 needed_vertices += 0;
4023 n_single_lines += 3;
4024 }
4025 else if (cell->reference_cell() ==
4027 {
4028 needed_cells += 4;
4029 needed_vertices += 1;
4030 n_single_lines += 4;
4031 }
4032 else
4033 {
4035 }
4036
4037 for (const auto line_no : cell->face_indices())
4038 {
4039 auto line = cell->line(line_no);
4040 if (line->has_children() == false)
4041 line->set_user_flag();
4042 }
4043 }
4044
4045
4046 const unsigned int used_cells =
4047 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4048 triangulation.levels[level + 1]->cells.used.end(),
4049 true);
4050
4051
4052 reserve_space(*triangulation.levels[level + 1],
4053 used_cells + needed_cells,
4054 2,
4055 spacedim);
4056
4057 reserve_space(triangulation.levels[level + 1]->cells,
4058 needed_cells,
4059 0);
4060 }
4061
4062 for (auto line = triangulation.begin_line();
4063 line != triangulation.end_line();
4064 ++line)
4065 if (line->user_flag_set())
4066 {
4067 Assert(line->has_children() == false, ExcInternalError());
4068 n_lines_in_pairs += 2;
4069 needed_vertices += 1;
4070 }
4071
4072 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4073
4074 needed_vertices += std::count(triangulation.vertices_used.begin(),
4075 triangulation.vertices_used.end(),
4076 true);
4077
4078 if (needed_vertices > triangulation.vertices.size())
4079 {
4080 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4081 triangulation.vertices_used.resize(needed_vertices, false);
4082 }
4083
4084 unsigned int next_unused_vertex = 0;
4085
4086 {
4088 line = triangulation.begin_active_line(),
4089 endl = triangulation.end_line();
4091 next_unused_line = triangulation.begin_raw_line();
4092
4093 for (; line != endl; ++line)
4094 if (line->user_flag_set())
4095 {
4096 // this line needs to be refined
4097
4098 // find the next unused vertex and set it
4099 // appropriately
4100 while (triangulation.vertices_used[next_unused_vertex] == true)
4101 ++next_unused_vertex;
4102 Assert(
4103 next_unused_vertex < triangulation.vertices.size(),
4104 ExcMessage(
4105 "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."));
4106 triangulation.vertices_used[next_unused_vertex] = true;
4107
4108 triangulation.vertices[next_unused_vertex] = line->center(true);
4109
4110 bool pair_found = false;
4111 (void)pair_found;
4112 for (; next_unused_line != endl; ++next_unused_line)
4113 if (!next_unused_line->used() &&
4114 !(++next_unused_line)->used())
4115 {
4116 --next_unused_line;
4117 pair_found = true;
4118 break;
4119 }
4120 Assert(pair_found, ExcInternalError());
4121
4122 line->set_children(0, next_unused_line->index());
4123
4125 children[2] = {next_unused_line, ++next_unused_line};
4126
4127 AssertIsNotUsed(children[0]);
4128 AssertIsNotUsed(children[1]);
4129
4130 children[0]->set_bounding_object_indices(
4131 {line->vertex_index(0), next_unused_vertex});
4132 children[1]->set_bounding_object_indices(
4133 {next_unused_vertex, line->vertex_index(1)});
4134
4135 children[0]->set_used_flag();
4136 children[1]->set_used_flag();
4137 children[0]->clear_children();
4138 children[1]->clear_children();
4139 children[0]->clear_user_data();
4140 children[1]->clear_user_data();
4141 children[0]->clear_user_flag();
4142 children[1]->clear_user_flag();
4143
4144
4145 children[0]->set_boundary_id_internal(line->boundary_id());
4146 children[1]->set_boundary_id_internal(line->boundary_id());
4147
4148 children[0]->set_manifold_id(line->manifold_id());
4149 children[1]->set_manifold_id(line->manifold_id());
4150
4151 line->clear_user_flag();
4152 }
4153 }
4154
4155 reserve_space(triangulation.faces->lines, 0, n_single_lines);
4156
4158 cells_with_distorted_children;
4159
4161 next_unused_line = triangulation.begin_raw_line();
4162
4163 const auto create_children = [](auto & triangulation,
4164 unsigned int &next_unused_vertex,
4165 auto & next_unused_line,
4166 auto & next_unused_cell,
4167 const auto & cell) {
4168 const auto ref_case = cell->refine_flag_set();
4169 cell->clear_refine_flag();
4170
4171 unsigned int n_new_vertices = 0;
4172
4173 if (cell->reference_cell() == ReferenceCells::Triangle)
4174 n_new_vertices = 6;
4175 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
4176 n_new_vertices = 9;
4177 else
4179
4180 std::vector<unsigned int> new_vertices(n_new_vertices,
4182 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
4183 ++vertex_no)
4184 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4185 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
4186 if (cell->line(line_no)->has_children())
4187 new_vertices[cell->n_vertices() + line_no] =
4188 cell->line(line_no)->child(0)->vertex_index(1);
4189
4190 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
4191 {
4192 while (triangulation.vertices_used[next_unused_vertex] == true)
4193 ++next_unused_vertex;
4194 Assert(
4195 next_unused_vertex < triangulation.vertices.size(),
4196 ExcMessage(
4197 "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."));
4198 triangulation.vertices_used[next_unused_vertex] = true;
4199
4200 new_vertices[8] = next_unused_vertex;
4201
4202 triangulation.vertices[next_unused_vertex] =
4203 cell->center(true, true);
4204 }
4205
4206 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
4207 12>
4208 new_lines;
4209 unsigned int lmin = 0;
4210 unsigned int lmax = 0;
4211
4212 if (cell->reference_cell() == ReferenceCells::Triangle)
4213 {
4214 lmin = 6;
4215 lmax = 9;
4216 }
4217 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
4218 {
4219 lmin = 8;
4220 lmax = 12;
4221 }
4222 else
4223 {
4225 }
4226
4227 for (unsigned int l = lmin; l < lmax; ++l)
4228 {
4229 while (next_unused_line->used() == true)
4230 ++next_unused_line;
4231 new_lines[l] = next_unused_line;
4232 ++next_unused_line;
4233
4234 AssertIsNotUsed(new_lines[l]);
4235 }
4236
4237 if (cell->reference_cell() == ReferenceCells::Triangle)
4238 {
4239 // add lines in the order implied by their orientation. Here,
4240 // face_no is the cell (not subcell) face number and vertex_no is
4241 // the first vertex on that face in the standard orientation.
4242 const auto ref = [&](const unsigned int face_no,
4243 const unsigned int vertex_no) {
4244 auto l = cell->line(face_no);
4245 // if the vertex is on the first child then add the first child
4246 // first
4247 if (l->child(0)->vertex_index(0) == new_vertices[vertex_no] ||
4248 l->child(0)->vertex_index(1) == new_vertices[vertex_no])
4249 {
4250 new_lines[2 * face_no + 0] = l->child(0);
4251 new_lines[2 * face_no + 1] = l->child(1);
4252 }
4253 else
4254 {
4255 new_lines[2 * face_no + 0] = l->child(1);
4256 new_lines[2 * face_no + 1] = l->child(0);
4257 }
4258 };
4259
4260 ref(0, 0);
4261 ref(1, 1);
4262 ref(2, 2);
4263
4264 // set up lines which do not have parents:
4265 new_lines[6]->set_bounding_object_indices(
4266 {new_vertices[3], new_vertices[4]});
4267 new_lines[7]->set_bounding_object_indices(
4268 {new_vertices[4], new_vertices[5]});
4269 new_lines[8]->set_bounding_object_indices(
4270 {new_vertices[5], new_vertices[3]});
4271 }
4272 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
4273 {
4274 unsigned int l = 0;
4275 for (const unsigned int face_no : cell->face_indices())
4276 for (unsigned int c = 0; c < 2; ++c, ++l)
4277 new_lines[l] = cell->line(face_no)->child(c);
4278
4279 new_lines[8]->set_bounding_object_indices(
4280 {new_vertices[6], new_vertices[8]});
4281 new_lines[9]->set_bounding_object_indices(
4282 {new_vertices[8], new_vertices[7]});
4283 new_lines[10]->set_bounding_object_indices(
4284 {new_vertices[4], new_vertices[8]});
4285 new_lines[11]->set_bounding_object_indices(
4286 {new_vertices[8], new_vertices[5]});
4287 }
4288 else
4289 {
4291 }
4292
4293 for (unsigned int l = lmin; l < lmax; ++l)
4294 {
4295 new_lines[l]->set_used_flag();
4296 new_lines[l]->clear_user_flag();
4297 new_lines[l]->clear_user_data();
4298 new_lines[l]->clear_children();
4299 // interior line
4300 new_lines[l]->set_boundary_id_internal(
4302 new_lines[l]->set_manifold_id(cell->manifold_id());
4303 }
4304
4307 while (next_unused_cell->used() == true)
4308 ++next_unused_cell;
4309
4310 unsigned int n_children = 0;
4311
4312 if (cell->reference_cell() == ReferenceCells::Triangle)
4313 n_children = 4;
4314 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
4315 n_children = 4;
4316 else
4318
4319 for (unsigned int i = 0; i < n_children; ++i)
4320 {
4321 AssertIsNotUsed(next_unused_cell);
4322 subcells[i] = next_unused_cell;
4323 ++next_unused_cell;
4324 if (i % 2 == 1 && i < n_children - 1)
4325 while (next_unused_cell->used() == true)
4326 ++next_unused_cell;
4327 }
4328
4329 if ((dim == 2) &&
4330 (cell->reference_cell() == ReferenceCells::Triangle))
4331 {
4332 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4333 new_lines[8]->index(),
4334 new_lines[5]->index()});
4335 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4336 new_lines[2]->index(),
4337 new_lines[6]->index()});
4338 subcells[2]->set_bounding_object_indices({new_lines[7]->index(),
4339 new_lines[3]->index(),
4340 new_lines[4]->index()});
4341 subcells[3]->set_bounding_object_indices({new_lines[6]->index(),
4342 new_lines[7]->index(),
4343 new_lines[8]->index()});
4344
4345 // Set subcell line orientations by checking the line's second
4346 // vertex (from the subcell's perspective) to the line's actual
4347 // second vertex.
4348 const auto fix_line_orientation =
4349 [&](const unsigned int line_no,
4350 const unsigned int vertex_no,
4351 const unsigned int subcell_no,
4352 const unsigned int subcell_line_no) {
4353 if (new_lines[line_no]->vertex_index(1) !=
4354 new_vertices[vertex_no])
4355 triangulation.levels[subcells[subcell_no]->level()]
4356 ->face_orientations.set_combined_orientation(
4357 subcells[subcell_no]->index() *
4359 subcell_line_no,
4360 0u);
4361 };
4362
4363 fix_line_orientation(0, 3, 0, 0);
4364 fix_line_orientation(8, 5, 0, 1);
4365 fix_line_orientation(5, 0, 0, 2);
4366
4367 fix_line_orientation(1, 1, 1, 0);
4368 fix_line_orientation(2, 4, 1, 1);
4369 fix_line_orientation(6, 3, 1, 2);
4370
4371 fix_line_orientation(7, 4, 2, 0);
4372 fix_line_orientation(3, 2, 2, 1);
4373 fix_line_orientation(4, 5, 2, 2);
4374
4375 // all lines of the new interior cell are oriented backwards so
4376 // that it has positive area.
4377 fix_line_orientation(6, 4, 3, 0);
4378 fix_line_orientation(7, 5, 3, 1);
4379 fix_line_orientation(8, 3, 3, 2);
4380 }
4381 else if ((dim == 2) &&
4382 (cell->reference_cell() == ReferenceCells::Quadrilateral))
4383 {
4384 subcells[0]->set_bounding_object_indices(
4385 {new_lines[0]->index(),
4386 new_lines[8]->index(),
4387 new_lines[4]->index(),
4388 new_lines[10]->index()});
4389 subcells[1]->set_bounding_object_indices(
4390 {new_lines[8]->index(),
4391 new_lines[2]->index(),
4392 new_lines[5]->index(),
4393 new_lines[11]->index()});
4394 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4395 new_lines[9]->index(),
4396 new_lines[10]->index(),
4397 new_lines[6]->index()});
4398 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4399 new_lines[3]->index(),
4400 new_lines[11]->index(),
4401 new_lines[7]->index()});
4402 }
4403 else
4404 {
4406 }
4407
4408 types::subdomain_id subdomainid = cell->subdomain_id();
4409
4410 for (unsigned int i = 0; i < n_children; ++i)
4411 {
4412 subcells[i]->set_used_flag();
4413 subcells[i]->clear_refine_flag();
4414 subcells[i]->clear_user_flag();
4415 subcells[i]->clear_user_data();
4416 subcells[i]->clear_children();
4417 // inherit material
4418 // properties
4419 subcells[i]->set_material_id(cell->material_id());
4420 subcells[i]->set_manifold_id(cell->manifold_id());
4421 subcells[i]->set_subdomain_id(subdomainid);
4422
4423 // TODO: here we assume that all children have the same reference
4424 // cell type as the parent! This is justified for 2d.
4425 triangulation.levels[subcells[i]->level()]
4426 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
4427
4428 if (i % 2 == 0)
4429 subcells[i]->set_parent(cell->index());
4430 }
4431
4432 for (unsigned int i = 0; i < n_children / 2; ++i)
4433 cell->set_children(2 * i, subcells[2 * i]->index());
4434
4435 cell->set_refinement_case(ref_case);
4436
4437 if (dim < spacedim)
4438 for (unsigned int c = 0; c < n_children; ++c)
4439 cell->child(c)->set_direction_flag(cell->direction_flag());
4440 };
4441
4442 for (int level = 0;
4443 level < static_cast<int>(triangulation.levels.size()) - 1;
4444 ++level)
4445 {
4447 next_unused_cell = triangulation.begin_raw(level + 1);
4448
4449 for (const auto &cell :
4450 triangulation.active_cell_iterators_on_level(level))
4451 if (cell->refine_flag_set())
4452 {
4453 create_children(triangulation,
4454 next_unused_vertex,
4455 next_unused_line,
4456 next_unused_cell,
4457 cell);
4458
4459 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
4460 check_for_distorted_cells &&
4461 has_distorted_children<dim, spacedim>(cell))
4462 cells_with_distorted_children.distorted_cells.push_back(
4463 cell);
4464
4465 triangulation.signals.post_refinement_on_cell(cell);
4466 }
4467 }
4468
4469 return cells_with_distorted_children;
4470 }
4471
4472
4473
4478 template <int spacedim>
4481 const bool /*check_for_distorted_cells*/)
4482 {
4483 const unsigned int dim = 1;
4484
4485 // Check whether a new level is needed. We have to check for
4486 // this on the highest level only
4487 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4488 triangulation.levels.size() - 1))
4489 if (cell->refine_flag_set())
4490 {
4491 triangulation.levels.push_back(
4492 std::make_unique<
4494 break;
4495 }
4496
4497
4498 // check how much space is needed on every level. We need not
4499 // check the highest level since either - on the highest level
4500 // no cells are flagged for refinement - there are, but
4501 // prepare_refinement added another empty level
4502 unsigned int needed_vertices = 0;
4503 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4504 {
4505 // count number of flagged
4506 // cells on this level
4507 unsigned int flagged_cells = 0;
4508
4509 for (const auto &acell :
4510 triangulation.active_cell_iterators_on_level(level))
4511 if (acell->refine_flag_set())
4512 ++flagged_cells;
4513
4514 // count number of used cells
4515 // on the next higher level
4516 const unsigned int used_cells =
4517 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4518 triangulation.levels[level + 1]->cells.used.end(),
4519 true);
4520
4521 // reserve space for the used_cells cells already existing
4522 // on the next higher level as well as for the
4523 // 2*flagged_cells that will be created on that level
4524 reserve_space(*triangulation.levels[level + 1],
4526 flagged_cells,
4527 1,
4528 spacedim);
4529 // reserve space for 2*flagged_cells new lines on the next
4530 // higher level
4531 reserve_space(triangulation.levels[level + 1]->cells,
4533 flagged_cells,
4534 0);
4535
4536 needed_vertices += flagged_cells;
4537 }
4538
4539 // add to needed vertices how many
4540 // vertices are already in use
4541 needed_vertices += std::count(triangulation.vertices_used.begin(),
4542 triangulation.vertices_used.end(),
4543 true);
4544 // if we need more vertices: create them, if not: leave the
4545 // array as is, since shrinking is not really possible because
4546 // some of the vertices at the end may be in use
4547 if (needed_vertices > triangulation.vertices.size())
4548 {
4549 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4550 triangulation.vertices_used.resize(needed_vertices, false);
4551 }
4552
4553
4554 // Do REFINEMENT on every level; exclude highest level as
4555 // above
4556
4557 // index of next unused vertex
4558 unsigned int next_unused_vertex = 0;
4559
4560 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4561 {
4563 next_unused_cell = triangulation.begin_raw(level + 1);
4564
4565 for (const auto &cell :
4566 triangulation.active_cell_iterators_on_level(level))
4567 if (cell->refine_flag_set())
4568 {
4569 // clear refinement flag
4570 cell->clear_refine_flag();
4571
4572 // search for next unused
4573 // vertex
4574 while (triangulation.vertices_used[next_unused_vertex] ==
4575 true)
4576 ++next_unused_vertex;
4577 Assert(
4578 next_unused_vertex < triangulation.vertices.size(),
4579 ExcMessage(
4580 "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."));
4581
4582 // Now we always ask the cell itself where to put
4583 // the new point. The cell in turn will query the
4584 // manifold object internally.
4585 triangulation.vertices[next_unused_vertex] =
4586 cell->center(true);
4587
4588 triangulation.vertices_used[next_unused_vertex] = true;
4589
4590 // search for next two unused cell (++ takes care of
4591 // the end of the vector)
4593 first_child,
4594 second_child;
4595 while (next_unused_cell->used() == true)
4596 ++next_unused_cell;
4597 first_child = next_unused_cell;
4598 first_child->set_used_flag();
4599 first_child->clear_user_data();
4600 ++next_unused_cell;
4601 AssertIsNotUsed(next_unused_cell);
4602 second_child = next_unused_cell;
4603 second_child->set_used_flag();
4604 second_child->clear_user_data();
4605
4606 types::subdomain_id subdomainid = cell->subdomain_id();
4607
4608 // insert first child
4609 cell->set_children(0, first_child->index());
4610 first_child->clear_children();
4611 first_child->set_bounding_object_indices(
4612 {cell->vertex_index(0), next_unused_vertex});
4613 first_child->set_material_id(cell->material_id());
4614 first_child->set_manifold_id(cell->manifold_id());
4615 first_child->set_subdomain_id(subdomainid);
4616 first_child->set_direction_flag(cell->direction_flag());
4617
4618 first_child->set_parent(cell->index());
4619
4620 // Set manifold id of the right face. Only do this
4621 // on the first child.
4622 first_child->face(1)->set_manifold_id(cell->manifold_id());
4623
4624 // reset neighborship info (refer to
4625 // internal::TriangulationImplementation::TriaLevel<0> for
4626 // details)
4627 first_child->set_neighbor(1, second_child);
4628 if (cell->neighbor(0).state() != IteratorState::valid)
4629 first_child->set_neighbor(0, cell->neighbor(0));
4630 else if (cell->neighbor(0)->is_active())
4631 {
4632 // since the neighbors level is always <=level,
4633 // if the cell is active, then there are no
4634 // cells to the left which may want to know
4635 // about this new child cell.
4636 Assert(cell->neighbor(0)->level() <= cell->level(),
4638 first_child->set_neighbor(0, cell->neighbor(0));
4639 }
4640 else
4641 // left neighbor is refined
4642 {
4643 // set neighbor to cell on same level
4644 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
4645 first_child->set_neighbor(0,
4646 cell->neighbor(0)->child(nbnb));
4647
4648 // reset neighbor info of all right descendant
4649 // of the left neighbor of cell
4651 left_neighbor = cell->neighbor(0);
4652 while (left_neighbor->has_children())
4653 {
4654 left_neighbor = left_neighbor->child(nbnb);
4655 left_neighbor->set_neighbor(nbnb, first_child);
4656 }
4657 }
4658
4659 // insert second child
4660 second_child->clear_children();
4661 second_child->set_bounding_object_indices(
4662 {next_unused_vertex, cell->vertex_index(1)});
4663 second_child->set_neighbor(0, first_child);
4664 second_child->set_material_id(cell->material_id());
4665 second_child->set_manifold_id(cell->manifold_id());
4666 second_child->set_subdomain_id(subdomainid);
4667 second_child->set_direction_flag(cell->direction_flag());
4668
4669 if (cell->neighbor(1).state() != IteratorState::valid)
4670 second_child->set_neighbor(1, cell->neighbor(1));
4671 else if (cell->neighbor(1)->is_active())
4672 {
4673 Assert(cell->neighbor(1)->level() <= cell->level(),
4675 second_child->set_neighbor(1, cell->neighbor(1));
4676 }
4677 else
4678 // right neighbor is refined same as above
4679 {
4680 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
4681 second_child->set_neighbor(
4682 1, cell->neighbor(1)->child(nbnb));
4683
4685 right_neighbor = cell->neighbor(1);
4686 while (right_neighbor->has_children())
4687 {
4688 right_neighbor = right_neighbor->child(nbnb);
4689 right_neighbor->set_neighbor(nbnb, second_child);
4690 }
4691 }
4692 // inform all listeners that cell refinement is done
4693 triangulation.signals.post_refinement_on_cell(cell);
4694 }
4695 }
4696
4697 // in 1d, we can not have distorted children unless the parent
4698 // was already distorted (that is because we don't use
4699 // boundary information for 1d triangulations). so return an
4700 // empty list
4702 }
4703
4704
4709 template <int spacedim>
4712 const bool check_for_distorted_cells)
4713 {
4714 const unsigned int dim = 2;
4715
4716
4717 // First check whether we can get away with isotropic refinement, or
4718 // whether we need to run through the full anisotropic algorithm
4719 {
4720 bool do_isotropic_refinement = true;
4721 for (const auto &cell : triangulation.active_cell_iterators())
4722 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
4723 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
4724 {
4725 do_isotropic_refinement = false;
4726 break;
4727 }
4728
4729 if (do_isotropic_refinement)
4730 return execute_refinement_isotropic(triangulation,
4731 check_for_distorted_cells);
4732 }
4733
4734 // Check whether a new level is needed. We have to check for
4735 // this on the highest level only
4736 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4737 triangulation.levels.size() - 1))
4738 if (cell->refine_flag_set())
4739 {
4740 triangulation.levels.push_back(
4741 std::make_unique<
4743 break;
4744 }
4745
4746 // TODO[WB]: we clear user flags and pointers of lines; we're going
4747 // to use them to flag which lines need refinement
4749 triangulation.begin_line();
4750 line != triangulation.end_line();
4751 ++line)
4752 {
4753 line->clear_user_flag();
4754 line->clear_user_data();
4755 }
4756 // running over all cells and lines count the number
4757 // n_single_lines of lines which can be stored as single
4758 // lines, e.g. inner lines
4759 unsigned int n_single_lines = 0;
4760
4761 // New lines to be created: number lines which are stored in
4762 // pairs (the children of lines must be stored in pairs)
4763 unsigned int n_lines_in_pairs = 0;
4764
4765 // check how much space is needed on every level. We need not
4766 // check the highest level since either - on the highest level
4767 // no cells are flagged for refinement - there are, but
4768 // prepare_refinement added another empty level
4769 unsigned int needed_vertices = 0;
4770 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4771 {
4772 // count number of flagged cells on this level and compute
4773 // how many new vertices and new lines will be needed
4774 unsigned int needed_cells = 0;
4775
4776 for (const auto &cell :
4777 triangulation.active_cell_iterators_on_level(level))
4778 if (cell->refine_flag_set())
4779 {
4780 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
4781 {
4782 needed_cells += 4;
4783
4784 // new vertex at center of cell is needed in any
4785 // case
4786 ++needed_vertices;
4787
4788 // the four inner lines can be stored as singles
4789 n_single_lines += 4;
4790 }
4791 else // cut_x || cut_y
4792 {
4793 // set the flag showing that anisotropic
4794 // refinement is used for at least one cell
4795 triangulation.anisotropic_refinement = true;
4796
4797 needed_cells += 2;
4798 // no vertex at center
4799
4800 // the inner line can be stored as single
4801 n_single_lines += 1;
4802 }
4803
4804 // mark all faces (lines) for refinement; checking
4805 // locally whether the neighbor would also like to
4806 // refine them is rather difficult for lines so we
4807 // only flag them and after visiting all cells, we
4808 // decide which lines need refinement;
4809 for (const unsigned int line_no :
4811 {
4813 cell->refine_flag_set(), line_no) ==
4815 {
4817 line = cell->line(line_no);
4818 if (line->has_children() == false)
4819 line->set_user_flag();
4820 }
4821 }
4822 }
4823
4824
4825 // count number of used cells on the next higher level
4826 const unsigned int used_cells =
4827 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4828 triangulation.levels[level + 1]->cells.used.end(),
4829 true);
4830
4831
4832 // reserve space for the used_cells cells already existing
4833 // on the next higher level as well as for the
4834 // needed_cells that will be created on that level
4835 reserve_space(*triangulation.levels[level + 1],
4836 used_cells + needed_cells,
4837 2,
4838 spacedim);
4839
4840 // reserve space for needed_cells new quads on the next
4841 // higher level
4842 reserve_space(triangulation.levels[level + 1]->cells,
4843 needed_cells,
4844 0);
4845 }
4846
4847 // now count the lines which were flagged for refinement
4849 triangulation.begin_line();
4850 line != triangulation.end_line();
4851 ++line)
4852 if (line->user_flag_set())
4853 {
4854 Assert(line->has_children() == false, ExcInternalError());
4855 n_lines_in_pairs += 2;
4856 needed_vertices += 1;
4857 }
4858 // reserve space for n_lines_in_pairs new lines. note, that
4859 // we can't reserve space for the single lines here as well,
4860 // as all the space reserved for lines in pairs would be
4861 // counted as unused and we would end up with too little space
4862 // to store all lines. memory reservation for n_single_lines
4863 // can only be done AFTER we refined the lines of the current
4864 // cells
4865 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4866
4867 // add to needed vertices how many vertices are already in use
4868 needed_vertices += std::count(triangulation.vertices_used.begin(),
4869 triangulation.vertices_used.end(),
4870 true);
4871 // if we need more vertices: create them, if not: leave the
4872 // array as is, since shrinking is not really possible because
4873 // some of the vertices at the end may be in use
4874 if (needed_vertices > triangulation.vertices.size())
4875 {
4876 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4877 triangulation.vertices_used.resize(needed_vertices, false);
4878 }
4879
4880
4881 // Do REFINEMENT on every level; exclude highest level as
4882 // above
4883
4884 // index of next unused vertex
4885 unsigned int next_unused_vertex = 0;
4886
4887 // first the refinement of lines. children are stored
4888 // pairwise
4889 {
4890 // only active objects can be refined further
4892 line = triangulation.begin_active_line(),
4893 endl = triangulation.end_line();
4895 next_unused_line = triangulation.begin_raw_line();
4896
4897 for (; line != endl; ++line)
4898 if (line->user_flag_set())
4899 {
4900 // this line needs to be refined
4901
4902 // find the next unused vertex and set it
4903 // appropriately
4904 while (triangulation.vertices_used[next_unused_vertex] == true)
4905 ++next_unused_vertex;
4906 Assert(
4907 next_unused_vertex < triangulation.vertices.size(),
4908 ExcMessage(
4909 "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."));
4910 triangulation.vertices_used[next_unused_vertex] = true;
4911
4912 triangulation.vertices[next_unused_vertex] = line->center(true);
4913
4914 // now that we created the right point, make up the
4915 // two child lines. To this end, find a pair of
4916 // unused lines
4917 bool pair_found = false;
4918 (void)pair_found;
4919 for (; next_unused_line != endl; ++next_unused_line)
4920 if (!next_unused_line->used() &&
4921 !(++next_unused_line)->used())
4922 {
4923 // go back to the first of the two unused
4924 // lines
4925 --next_unused_line;
4926 pair_found = true;
4927 break;
4928 }
4929 Assert(pair_found, ExcInternalError());
4930
4931 // there are now two consecutive unused lines, such
4932 // that the children of a line will be consecutive.
4933 // then set the child pointer of the present line
4934 line->set_children(0, next_unused_line->index());
4935
4936 // set the two new lines
4938 children[2] = {next_unused_line, ++next_unused_line};
4939 // some tests; if any of the iterators should be
4940 // invalid, then already dereferencing will fail
4941 AssertIsNotUsed(children[0]);
4942 AssertIsNotUsed(children[1]);
4943
4944 children[0]->set_bounding_object_indices(
4945 {line->vertex_index(0), next_unused_vertex});
4946 children[1]->set_bounding_object_indices(
4947 {next_unused_vertex, line->vertex_index(1)});
4948
4949 children[0]->set_used_flag();
4950 children[1]->set_used_flag();
4951 children[0]->clear_children();
4952 children[1]->clear_children();
4953 children[0]->clear_user_data();
4954 children[1]->clear_user_data();
4955 children[0]->clear_user_flag();
4956 children[1]->clear_user_flag();
4957
4958
4959 children[0]->set_boundary_id_internal(line->boundary_id());
4960 children[1]->set_boundary_id_internal(line->boundary_id());
4961
4962 children[0]->set_manifold_id(line->manifold_id());
4963 children[1]->set_manifold_id(line->manifold_id());
4964
4965 // finally clear flag indicating the need for
4966 // refinement
4967 line->clear_user_flag();
4968 }
4969 }
4970
4971
4972 // Now set up the new cells
4973
4974 // reserve space for inner lines (can be stored as single
4975 // lines)
4976 reserve_space(triangulation.faces->lines, 0, n_single_lines);
4977
4979 cells_with_distorted_children;
4980
4981 // reset next_unused_line, as now also single empty places in
4982 // the vector can be used
4984 next_unused_line = triangulation.begin_raw_line();
4985
4986 for (int level = 0;
4987 level < static_cast<int>(triangulation.levels.size()) - 1;
4988 ++level)
4989 {
4991 next_unused_cell = triangulation.begin_raw(level + 1);
4992
4993 for (const auto &cell :
4994 triangulation.active_cell_iterators_on_level(level))
4995 if (cell->refine_flag_set())
4996 {
4997 // actually set up the children and update neighbor
4998 // information
4999 create_children(triangulation,
5000 next_unused_vertex,
5001 next_unused_line,
5002 next_unused_cell,
5003 cell);
5004
5005 if (check_for_distorted_cells &&
5006 has_distorted_children<dim, spacedim>(cell))
5007 cells_with_distorted_children.distorted_cells.push_back(
5008 cell);
5009 // inform all listeners that cell refinement is done
5010 triangulation.signals.post_refinement_on_cell(cell);
5011 }
5012 }
5013
5014 return cells_with_distorted_children;
5015 }
5016
5017
5018 template <int spacedim>
5021 const bool check_for_distorted_cells)
5022 {
5023 static const int dim = 3;
5024 static const unsigned int X = numbers::invalid_unsigned_int;
5025 using raw_line_iterator =
5027 using raw_quad_iterator =
5029
5030 Assert(spacedim == 3, ExcNotImplemented());
5031
5032 Assert(triangulation.vertices.size() ==
5033 triangulation.vertices_used.size(),
5035
5036 // Check whether a new level is needed. We have to check for
5037 // this on the highest level only
5038 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5039 triangulation.levels.size() - 1))
5040 if (cell->refine_flag_set())
5041 {
5042 triangulation.levels.push_back(
5043 std::make_unique<
5045 break;
5046 }
5047
5048 // first clear user flags for quads and lines; we're going to
5049 // use them to flag which lines and quads need refinement
5050 triangulation.faces->quads.clear_user_data();
5051 triangulation.faces->lines.clear_user_flags();
5052 triangulation.faces->quads.clear_user_flags();
5053
5054 // check how much space is needed on every level. We need not
5055 // check the highest level since either
5056 // - on the highest level no cells are flagged for refinement
5057 // - there are, but prepare_refinement added another empty
5058 // level which then is the highest level
5059
5060 // variables to hold the number of newly to be created
5061 // vertices, lines and quads. as these are stored globally,
5062 // declare them outside the loop over al levels. we need lines
5063 // and quads in pairs for refinement of old ones and lines and
5064 // quads, that can be stored as single ones, as they are newly
5065 // created in the inside of an existing cell
5066 unsigned int needed_vertices = 0;
5067 unsigned int needed_lines_single = 0;
5068 unsigned int needed_quads_single = 0;
5069 unsigned int needed_lines_pair = 0;
5070 unsigned int needed_quads_pair = 0;
5071 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5072 {
5073 unsigned int new_cells = 0;
5074
5075 for (const auto &cell :
5076 triangulation.active_cell_iterators_on_level(level))
5077 if (cell->refine_flag_set())
5078 {
5079 // Only support isotropic refinement
5080 Assert(cell->refine_flag_set() ==
5083
5084 // Now count up how many new cells, faces, edges, and vertices
5085 // we will need to allocate to do this refinement.
5086 new_cells += cell->reference_cell().n_isotropic_children();
5087
5088 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5089 {
5090 ++needed_vertices;
5091 needed_lines_single += 6;
5092 needed_quads_single += 12;
5093 }
5094 else if (cell->reference_cell() ==
5096 {
5097 needed_lines_single += 1;
5098 needed_quads_single += 8;
5099 }
5100 else
5101 {
5102 Assert(false, ExcInternalError());
5103 }
5104
5105 // Also check whether we have to refine any of the faces and
5106 // edges that bound this cell. They may of course already be
5107 // refined, so we only *mark* them for refinement by setting
5108 // the user flags
5109 for (const auto face : cell->face_indices())
5110 if (cell->face(face)->n_children() == 0)
5111 cell->face(face)->set_user_flag();
5112 else
5113 Assert(cell->face(face)->n_children() ==
5114 cell->reference_cell()
5115 .face_reference_cell(face)
5116 .n_isotropic_children(),
5118
5119 for (const auto line : cell->line_indices())
5120 if (cell->line(line)->has_children() == false)
5121 cell->line(line)->set_user_flag();
5122 else
5123 Assert(cell->line(line)->n_children() == 2,
5125 }
5126
5127 const unsigned int used_cells =
5128 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5129 triangulation.levels[level + 1]->cells.used.end(),
5130 true);
5131
5132 reserve_space(*triangulation.levels[level + 1],
5133 used_cells + new_cells,
5134 3,
5135 spacedim);
5136
5137 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
5138 }
5139
5140 // now count the quads and lines which were flagged for
5141 // refinement
5143 triangulation.begin_quad();
5144 quad != triangulation.end_quad();
5145 ++quad)
5146 {
5147 if (quad->user_flag_set() == false)
5148 continue;
5149
5150 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
5151 {
5152 needed_quads_pair += 4;
5153 needed_lines_pair += 4;
5154 needed_vertices += 1;
5155 }
5156 else if (quad->reference_cell() == ReferenceCells::Triangle)
5157 {
5158 needed_quads_pair += 4;
5159 needed_lines_single += 3;
5160 }
5161 else
5162 {
5163 Assert(false, ExcInternalError());
5164 }
5165 }
5166
5168 triangulation.begin_line();
5169 line != triangulation.end_line();
5170 ++line)
5171 {
5172 if (line->user_flag_set() == false)
5173 continue;
5174
5175 needed_lines_pair += 2;
5176 needed_vertices += 1;
5177 }
5178
5179 reserve_space(triangulation.faces->lines,
5180 needed_lines_pair,
5181 needed_lines_single);
5183 needed_quads_pair,
5184 needed_quads_single);
5185 reserve_space(triangulation.faces->quads,
5186 needed_quads_pair,
5187 needed_quads_single);
5188
5189
5190 // add to needed vertices how many vertices are already in use
5191 needed_vertices += std::count(triangulation.vertices_used.begin(),
5192 triangulation.vertices_used.end(),
5193 true);
5194
5195 if (needed_vertices > triangulation.vertices.size())
5196 {
5197 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5198 triangulation.vertices_used.resize(needed_vertices, false);
5199 }
5200
5201 //-----------------------------------------
5202 // Before we start with the actual refinement, we do some
5203 // sanity checks if in debug mode. especially, we try to catch
5204 // the notorious problem with lines being twice refined,
5205 // i.e. there are cells adjacent at one line ("around the
5206 // edge", but not at a face), with two cells differing by more
5207 // than one refinement level
5208 //
5209 // this check is very simple to implement here, since we have
5210 // all lines flagged if they shall be refined
5211#ifdef DEBUG
5212 for (const auto &cell : triangulation.active_cell_iterators())
5213 if (!cell->refine_flag_set())
5214 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
5215 if (cell->line(line_n)->has_children())
5216 for (unsigned int c = 0; c < 2; ++c)
5217 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
5219#endif
5220
5221 unsigned int current_vertex = 0;
5222
5223 // helper function - find the next available vertex number and mark it
5224 // as used.
5225 auto get_next_unused_vertex = [](const unsigned int current_vertex,
5226 std::vector<bool> &vertices_used) {
5227 unsigned int next_vertex = current_vertex;
5228 while (next_vertex < vertices_used.size() &&
5229 vertices_used[next_vertex] == true)
5230 ++next_vertex;
5231 Assert(next_vertex < vertices_used.size(), ExcInternalError());
5232 vertices_used[next_vertex] = true;
5233
5234 return next_vertex;
5235 };
5236
5237 // LINES
5238 {
5240 line = triangulation.begin_active_line(),
5241 endl = triangulation.end_line();
5242 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
5243
5244 for (; line != endl; ++line)
5245 {
5246 if (line->user_flag_set() == false)
5247 continue;
5248
5249 next_unused_line =
5250 triangulation.faces->lines.template next_free_pair_object<1>(
5252 Assert(next_unused_line.state() == IteratorState::valid,
5254
5255 // now we found two consecutive unused lines, such
5256 // that the children of a line will be consecutive.
5257 // then set the child pointer of the present line
5258 line->set_children(0, next_unused_line->index());
5259
5260 const std::array<raw_line_iterator, 2> children{
5261 {next_unused_line, ++next_unused_line}};
5262
5263 AssertIsNotUsed(children[0]);
5264 AssertIsNotUsed(children[1]);
5265
5266 current_vertex =
5267 get_next_unused_vertex(current_vertex,
5268 triangulation.vertices_used);
5269 triangulation.vertices[current_vertex] = line->center(true);
5270
5271 children[0]->set_bounding_object_indices(
5272 {line->vertex_index(0), current_vertex});
5273 children[1]->set_bounding_object_indices(
5274 {current_vertex, line->vertex_index(1)});
5275
5276 const auto manifold_id = line->manifold_id();
5277 const auto boundary_id = line->boundary_id();
5278 for (const auto &child : children)
5279 {
5280 child->set_used_flag();
5281 child->clear_children();
5282 child->clear_user_data();
5283 child->clear_user_flag();
5284 child->set_boundary_id_internal(boundary_id);
5285 child->set_manifold_id(manifold_id);
5286 }
5287
5288 line->clear_user_flag();
5289 }
5290 }
5291
5292 // QUADS
5293 {
5295 quad = triangulation.begin_quad(),
5296 endq = triangulation.end_quad();
5297
5298 for (; quad != endq; ++quad)
5299 {
5300 if (quad->user_flag_set() == false)
5301 continue;
5302
5303 const auto reference_face_type = quad->reference_cell();
5304
5305 // 1) create new lines (property is set later)
5306 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
5307 std::array<raw_line_iterator, 4> new_lines;
5308 if (reference_face_type == ReferenceCells::Quadrilateral)
5309 {
5310 for (unsigned int l = 0; l < 2; ++l)
5311 {
5312 auto next_unused_line =
5313 triangulation.faces->lines
5314 .template next_free_pair_object<1>(triangulation);
5315 new_lines[2 * l] = next_unused_line;
5316 new_lines[2 * l + 1] = ++next_unused_line;
5317 }
5318 }
5319 else if (reference_face_type == ReferenceCells::Triangle)
5320 {
5321 for (unsigned int l = 0; l < 3; ++l)
5322 new_lines[l] =
5323 triangulation.faces->lines
5324 .template next_free_single_object<1>(triangulation);
5325 }
5326 else
5327 {
5328 Assert(false, ExcNotImplemented());
5329 }
5330
5331 for (const unsigned int line : quad->line_indices())
5332 {
5333 AssertIsNotUsed(new_lines[line]);
5334 (void)line;
5335 }
5336
5337 // 2) create new quads (properties are set below). Both triangles
5338 // and quads are divided in four.
5339 std::array<raw_quad_iterator, 4> new_quads;
5340 for (unsigned int q = 0; q < 2; ++q)
5341 {
5342 auto next_unused_quad =
5343 triangulation.faces->quads
5344 .template next_free_pair_object<2>(triangulation);
5345
5346 new_quads[2 * q] = next_unused_quad;
5347 new_quads[2 * q + 1] = ++next_unused_quad;
5348
5349 quad->set_children(2 * q, new_quads[2 * q]->index());
5350 }
5351 quad->set_refinement_case(RefinementCase<2>::cut_xy);
5352
5353 for (const auto &quad : new_quads)
5354 {
5355 AssertIsNotUsed(quad);
5356 (void)quad;
5357 }
5358
5359 // 3) set vertex indices and set new vertex
5360
5361 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
5362 // for Triangle)
5363 std::array<unsigned int, 9> vertex_indices = {};
5364 unsigned int k = 0;
5365 for (const auto i : quad->vertex_indices())
5366 vertex_indices[k++] = quad->vertex_index(i);
5367
5368 for (const auto i : quad->line_indices())
5369 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
5370
5371 if (reference_face_type == ReferenceCells::Quadrilateral)
5372 {
5373 current_vertex =
5374 get_next_unused_vertex(current_vertex,
5375 triangulation.vertices_used);
5376 vertex_indices[k++] = current_vertex;
5377
5378 triangulation.vertices[current_vertex] =
5379 quad->center(true, true);
5380 }
5381
5382 // 4) set new lines on quads and their properties
5383 std::array<raw_line_iterator, 12> lines;
5384 unsigned int n_lines = 0;
5385 for (unsigned int l = 0; l < quad->n_lines(); ++l)
5386 for (unsigned int c = 0; c < 2; ++c)
5387 {
5388 static constexpr ::ndarray<unsigned int, 2, 2> index =
5389 {{// child 0, line_orientation=false and true
5390 {{1, 0}},
5391 // child 1, line_orientation=false and true
5392 {{0, 1}}}};
5393
5394 lines[n_lines++] =
5395 quad->line(l)->child(index[c][quad->line_orientation(l)]);
5396 }
5397
5398 for (unsigned int l = 0; l < quad->n_lines(); ++l)
5399 lines[n_lines++] = new_lines[l];
5400
5401 std::array<int, 12> line_indices;
5402 for (unsigned int i = 0; i < n_lines; ++i)
5403 line_indices[i] = lines[i]->index();
5404
5405 static constexpr ::ndarray<unsigned int, 12, 2>
5406 line_vertices_quad{{{{0, 4}},
5407 {{4, 2}},
5408 {{1, 5}},
5409 {{5, 3}},
5410 {{0, 6}},
5411 {{6, 1}},
5412 {{2, 7}},
5413 {{7, 3}},
5414 {{6, 8}},
5415 {{8, 7}},
5416 {{4, 8}},
5417 {{8, 5}}}};
5418
5419 static constexpr ::ndarray<unsigned int, 4, 4>
5420 quad_lines_quad{{{{0, 8, 4, 10}},
5421 {{8, 2, 5, 11}},
5422 {{1, 9, 10, 6}},
5423 {{9, 3, 11, 7}}}};
5424
5425 static constexpr ::ndarray<unsigned int, 12, 2>
5426 line_vertices_tri{{{{0, 3}},
5427 {{3, 1}},
5428 {{1, 4}},
5429 {{4, 2}},
5430 {{2, 5}},
5431 {{5, 0}},
5432 {{3, 4}},
5433 {{4, 5}},
5434 {{3, 5}},
5435 {{X, X}},
5436 {{X, X}},
5437 {{X, X}}}};
5438
5439 static constexpr ::ndarray<unsigned int, 4, 4>
5440 quad_lines_tri{{{{0, 8, 5, X}},
5441 {{1, 2, 6, X}},
5442 {{7, 3, 4, X}},
5443 {{6, 7, 8, X}}}};
5444
5445 static constexpr ::ndarray<unsigned int, 4, 4, 2>
5446 quad_line_vertices_tri{
5447 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
5448 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
5449 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
5450 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
5451
5452 const auto &line_vertices =
5453 (reference_face_type == ReferenceCells::Quadrilateral) ?
5454 line_vertices_quad :
5455 line_vertices_tri;
5456 const auto &quad_lines =
5457 (reference_face_type == ReferenceCells::Quadrilateral) ?
5458 quad_lines_quad :
5459 quad_lines_tri;
5460
5461 for (unsigned int i = 0, j = 2 * quad->n_lines();
5462 i < quad->n_lines();
5463 ++i, ++j)
5464 {
5465 auto &new_line = new_lines[i];
5466 new_line->set_bounding_object_indices(
5467 {vertex_indices[line_vertices[j][0]],
5468 vertex_indices[line_vertices[j][1]]});
5469 new_line->set_used_flag();
5470 new_line->clear_user_flag();
5471 new_line->clear_user_data();
5472 new_line->clear_children();
5473 new_line->set_boundary_id_internal(quad->boundary_id());
5474 new_line->set_manifold_id(quad->manifold_id());
5475 }
5476
5477 // 5) set properties of quads
5478 for (unsigned int i = 0; i < new_quads.size(); ++i)
5479 {
5480 auto &new_quad = new_quads[i];
5481
5482 // TODO: we assume here that all children have the same type
5483 // as the parent
5484 triangulation.faces->set_quad_type(new_quad->index(),
5485 reference_face_type);
5486
5487 if (reference_face_type == ReferenceCells::Triangle)
5488 new_quad->set_bounding_object_indices(
5489 {line_indices[quad_lines[i][0]],
5490 line_indices[quad_lines[i][1]],
5491 line_indices[quad_lines[i][2]]});
5492 else if (reference_face_type == ReferenceCells::Quadrilateral)
5493 new_quad->set_bounding_object_indices(
5494 {line_indices[quad_lines[i][0]],
5495 line_indices[quad_lines[i][1]],
5496 line_indices[quad_lines[i][2]],
5497 line_indices[quad_lines[i][3]]});
5498 else
5499 Assert(false, ExcNotImplemented());
5500
5501 new_quad->set_used_flag();
5502 new_quad->clear_user_flag();
5503 new_quad->clear_user_data();
5504 new_quad->clear_children();
5505 new_quad->set_boundary_id_internal(quad->boundary_id());
5506 new_quad->set_manifold_id(quad->manifold_id());
5507
5508#ifdef DEBUG
5509 std::set<unsigned int> s;
5510#endif
5511
5512 // ... and fix orientation of lines of face for triangles,
5513 // using an expensive algorithm, quadrilaterals are treated
5514 // a few lines below by a cheaper algorithm
5515 if (reference_face_type == ReferenceCells::Triangle)
5516 {
5517 for (const auto f : new_quad->line_indices())
5518 {
5519 const std::array<unsigned int, 2> vertices_0 = {
5520 {lines[quad_lines[i][f]]->vertex_index(0),
5521 lines[quad_lines[i][f]]->vertex_index(1)}};
5522
5523 const std::array<unsigned int, 2> vertices_1 = {
5524 {vertex_indices[quad_line_vertices_tri[i][f][0]],
5525 vertex_indices[quad_line_vertices_tri[i][f][1]]}};
5526
5527 const auto orientation =
5529 make_array_view(vertices_0),
5530 make_array_view(vertices_1));
5531
5532#ifdef DEBUG
5533 for (const auto i : vertices_0)
5534 s.insert(i);
5535 for (const auto i : vertices_1)
5536 s.insert(i);
5537#endif
5538
5539 new_quad->set_line_orientation(f, orientation);
5540 }
5541#ifdef DEBUG
5542 AssertDimension(s.size(), 3);
5543#endif
5544 }
5545 }
5546
5547 // fix orientation of lines of faces for quadrilaterals with
5548 // cheap algorithm
5549 if (reference_face_type == ReferenceCells::Quadrilateral)
5550 {
5551 static constexpr ::ndarray<unsigned int, 4, 2>
5552 quad_child_boundary_lines{
5553 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
5554
5555 for (unsigned int i = 0; i < 4; ++i)
5556 for (unsigned int j = 0; j < 2; ++j)
5557 new_quads[quad_child_boundary_lines[i][j]]
5558 ->set_line_orientation(i, quad->line_orientation(i));
5559 }
5560
5561 quad->clear_user_flag();
5562 }
5563 }
5564
5566 cells_with_distorted_children;
5567
5569 triangulation.begin_active_hex(0);
5570 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
5571 ++level)
5572 {
5574 next_unused_hex = triangulation.begin_raw_hex(level + 1);
5575 Assert(hex == triangulation.end() ||
5576 hex->level() >= static_cast<int>(level),
5578
5579 for (; hex != triangulation.end() &&
5580 hex->level() == static_cast<int>(level);
5581 ++hex)
5582 {
5583 if (hex->refine_flag_set() ==
5585 continue;
5586
5587 const auto &reference_cell_type = hex->reference_cell();
5588
5589 const RefinementCase<dim> ref_case = hex->refine_flag_set();
5590 hex->clear_refine_flag();
5591 hex->set_refinement_case(ref_case);
5592
5593 unsigned int n_new_lines = 0;
5594 unsigned int n_new_quads = 0;
5595 unsigned int n_new_hexes = 0;
5596
5597 if (reference_cell_type == ReferenceCells::Hexahedron)
5598 {
5599 n_new_lines = 6;
5600 n_new_quads = 12;
5601 n_new_hexes = 8;
5602 }
5603 else if (reference_cell_type == ReferenceCells::Tetrahedron)
5604 {
5605 n_new_lines = 1;
5606 n_new_quads = 8;
5607 n_new_hexes = 8;
5608 }
5609 else
5610 Assert(false, ExcNotImplemented());
5611
5612 std::array<raw_line_iterator, 6> new_lines;
5613 for (unsigned int i = 0; i < n_new_lines; ++i)
5614 {
5615 new_lines[i] =
5616 triangulation.faces->lines
5617 .template next_free_single_object<1>(triangulation);
5618
5619 AssertIsNotUsed(new_lines[i]);
5620 new_lines[i]->set_used_flag();
5621 new_lines[i]->clear_user_flag();
5622 new_lines[i]->clear_user_data();
5623 new_lines[i]->clear_children();
5624 new_lines[i]->set_boundary_id_internal(
5626 new_lines[i]->set_manifold_id(hex->manifold_id());
5627 }
5628
5629 std::array<raw_quad_iterator, 12> new_quads;
5630 for (unsigned int i = 0; i < n_new_quads; ++i)
5631 {
5632 new_quads[i] =
5633 triangulation.faces->quads
5634 .template next_free_single_object<2>(triangulation);
5635
5636 auto &new_quad = new_quads[i];
5637
5638 // TODO: faces of children have the same type as the faces
5639 // of the parent
5640 triangulation.faces->set_quad_type(
5641 new_quad->index(),
5642 reference_cell_type.face_reference_cell(0));
5643
5644 AssertIsNotUsed(new_quad);
5645 new_quad->set_used_flag();
5646 new_quad->clear_user_flag();
5647 new_quad->clear_user_data();
5648 new_quad->clear_children();
5649 new_quad->set_boundary_id_internal(
5651 new_quad->set_manifold_id(hex->manifold_id());
5652 for (const auto j : new_quads[i]->line_indices())
5653 new_quad->set_line_orientation(j, true);
5654 }
5655
5656 // we always get 8 children per refined cell
5657 std::array<
5659 8>
5660 new_hexes;
5661 {
5662 for (unsigned int i = 0; i < n_new_hexes; ++i)
5663 {
5664 if (i % 2 == 0)
5665 next_unused_hex =
5666 triangulation.levels[level + 1]->cells.next_free_hex(
5667 triangulation, level + 1);
5668 else
5669 ++next_unused_hex;
5670
5671 new_hexes[i] = next_unused_hex;
5672
5673 auto &new_hex = new_hexes[i];
5674
5675 // children have the same type as the parent
5676 triangulation.levels[new_hex->level()]
5677 ->reference_cell[new_hex->index()] =
5678 reference_cell_type;
5679
5680 AssertIsNotUsed(new_hex);
5681 new_hex->set_used_flag();
5682 new_hex->clear_user_flag();
5683 new_hex->clear_user_data();
5684 new_hex->clear_children();
5685 new_hex->set_material_id(hex->material_id());
5686 new_hex->set_manifold_id(hex->manifold_id());
5687 new_hex->set_subdomain_id(hex->subdomain_id());
5688
5689 if (i % 2)
5690 new_hex->set_parent(hex->index());
5691
5692 // set the orientation flag to its default state for all
5693 // faces initially. later on go the other way round and
5694 // reset faces that are at the boundary of the mother cube
5695 for (const auto f : new_hex->face_indices())
5696 new_hex->set_combined_face_orientation(
5697 f,
5699 }
5700 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
5701 hex->set_children(2 * i, new_hexes[2 * i]->index());
5702 }
5703
5704 {
5705 // load vertex indices
5706 std::array<unsigned int, 27> vertex_indices = {};
5707
5708 {
5709 unsigned int k = 0;
5710
5711 // avoid a compiler warning by fixing the max number of
5712 // loop iterations to 8
5713 const unsigned int n_vertices =
5714 std::min(hex->n_vertices(), 8u);
5715 for (unsigned int i = 0; i < n_vertices; ++i)
5716 vertex_indices[k++] = hex->vertex_index(i);
5717
5718 const std::array<unsigned int, 12> line_indices =
5719 TriaAccessorImplementation::Implementation::
5720 get_line_indices_of_cell(*hex);
5721 // avoid a compiler warning by fixing the max number of
5722 // loop iterations to 12
5723 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
5724 for (unsigned int l = 0; l < n_lines; ++l)
5725 {
5726 raw_line_iterator line(&triangulation,
5727 0,
5728 line_indices[l]);
5729 vertex_indices[k++] = line->child(0)->vertex_index(1);
5730 }
5731
5732 if (reference_cell_type == ReferenceCells::Hexahedron)
5733 {
5734 for (const unsigned int i : hex->face_indices())
5735 vertex_indices[k++] =
5736 hex->face(i)->child(0)->vertex_index(3);
5737
5738 // Set single new vertex in the center
5739 current_vertex =
5740 get_next_unused_vertex(current_vertex,
5741 triangulation.vertices_used);
5742 vertex_indices[k++] = current_vertex;
5743
5744 triangulation.vertices[current_vertex] =
5745 hex->center(true, true);
5746 }
5747 }
5748
5749 // set up new lines
5750 {
5751 static constexpr ::ndarray<unsigned int, 6, 2>
5752 new_line_vertices_hex = {{{{22, 26}},
5753 {{26, 23}},
5754 {{20, 26}},
5755 {{26, 21}},
5756 {{24, 26}},
5757 {{26, 25}}}};
5758
5759 static constexpr ::ndarray<unsigned int, 6, 2>
5760 new_line_vertices_tet = {{{{6, 8}},
5761 {{X, X}},
5762 {{X, X}},
5763 {{X, X}},
5764 {{X, X}},
5765 {{X, X}}}};
5766
5767 const auto &new_line_vertices =
5768 (reference_cell_type == ReferenceCells::Hexahedron) ?
5769 new_line_vertices_hex :
5770 new_line_vertices_tet;
5771
5772 for (unsigned int i = 0; i < n_new_lines; ++i)
5773 new_lines[i]->set_bounding_object_indices(
5774 {vertex_indices[new_line_vertices[i][0]],
5775 vertex_indices[new_line_vertices[i][1]]});
5776 }
5777
5778 // set up new quads
5779 {
5780 boost::container::small_vector<raw_line_iterator, 30>
5781 relevant_lines;
5782
5783 if (reference_cell_type == ReferenceCells::Hexahedron)
5784 {
5785 relevant_lines.resize(30);
5786 for (unsigned int f = 0, k = 0; f < 6; ++f)
5787 for (unsigned int c = 0; c < 4; ++c, ++k)
5788 {
5789 static constexpr ::
5790 ndarray<unsigned int, 4, 2>
5791 temp = {
5792 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
5793
5794 relevant_lines[k] =
5795 hex->face(f)
5796 ->isotropic_child(
5798 standard_to_real_face_vertex(
5799 temp[c][0],
5800 hex->face_orientation(f),
5801 hex->face_flip(f),
5802 hex->face_rotation(f)))
5803 ->line(GeometryInfo<dim>::
5804 standard_to_real_face_line(
5805 temp[c][1],
5806 hex->face_orientation(f),
5807 hex->face_flip(f),
5808 hex->face_rotation(f)));
5809 }
5810
5811 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
5812 relevant_lines[k] = new_lines[i];
5813 }
5814 else if (reference_cell_type == ReferenceCells::Tetrahedron)
5815 {
5816 relevant_lines.resize(13);
5817
5818 unsigned int k = 0;
5819 for (unsigned int f = 0; f < 4; ++f)
5820 for (unsigned int l = 0; l < 3; ++l, ++k)
5821 {
5822 // TODO: add comment
5823 static const std::
5824 array<std::array<unsigned int, 3>, 6>
5825 table = {{{{1, 0, 2}}, // 0
5826 {{0, 1, 2}},
5827 {{0, 2, 1}}, // 2
5828 {{1, 2, 0}},
5829 {{2, 1, 0}}, // 4
5830 {{2, 0, 1}}}};
5831
5832 relevant_lines[k] =
5833 hex->face(f)
5834 ->child(3 /*center triangle*/)
5835 ->line(
5836 table[triangulation.levels[hex->level()]
5837 ->face_orientations
5838 .get_combined_orientation(
5839 hex->index() * GeometryInfo<dim>::
5840 faces_per_cell +
5841 f)][l]);
5842 }
5843
5844 relevant_lines[k++] = new_lines[0];
5845
5846 AssertDimension(k, 13);
5847 }
5848 else
5849 Assert(false, ExcNotImplemented());
5850
5851 boost::container::small_vector<unsigned int, 30>
5852 relevant_line_indices(relevant_lines.size());
5853 for (unsigned int i = 0; i < relevant_line_indices.size();
5854 ++i)
5855 relevant_line_indices[i] = relevant_lines[i]->index();
5856
5857 static constexpr ::ndarray<unsigned int, 12, 4>
5858 new_quad_lines_hex = {{{{10, 28, 16, 24}},
5859 {{28, 14, 17, 25}},
5860 {{11, 29, 24, 20}},
5861 {{29, 15, 25, 21}},
5862 {{18, 26, 0, 28}},
5863 {{26, 22, 1, 29}},
5864 {{19, 27, 28, 4}},
5865 {{27, 23, 29, 5}},
5866 {{2, 24, 8, 26}},
5867 {{24, 6, 9, 27}},
5868 {{3, 25, 26, 12}},
5869 {{25, 7, 27, 13}}}};
5870
5871 static constexpr ::ndarray<unsigned int, 12, 4>
5872 new_quad_lines_tet = {{{{2, 3, 8, X}},
5873 {{0, 9, 5, X}},
5874 {{1, 6, 11, X}},
5875 {{4, 10, 7, X}},
5876 {{2, 12, 5, X}},
5877 {{1, 9, 12, X}},
5878 {{4, 8, 12, X}},
5879 {{6, 12, 10, X}},
5880 {{X, X, X, X}},
5881 {{X, X, X, X}},
5882 {{X, X, X, X}},
5883 {{X, X, X, X}}}};
5884
5885 static constexpr ::ndarray<unsigned int, 12, 4, 2>
5886 table_hex = {
5887 {{{{{10, 22}}, {{24, 26}}, {{10, 24}}, {{22, 26}}}},
5888 {{{{24, 26}}, {{11, 23}}, {{24, 11}}, {{26, 23}}}},
5889 {{{{22, 14}}, {{26, 25}}, {{22, 26}}, {{14, 25}}}},
5890 {{{{26, 25}}, {{23, 15}}, {{26, 23}}, {{25, 15}}}},
5891 {{{{8, 24}}, {{20, 26}}, {{8, 20}}, {{24, 26}}}},
5892 {{{{20, 26}}, {{12, 25}}, {{20, 12}}, {{26, 25}}}},
5893 {{{{24, 9}}, {{26, 21}}, {{24, 26}}, {{9, 21}}}},
5894 {{{{26, 21}}, {{25, 13}}, {{26, 25}}, {{21, 13}}}},
5895 {{{{16, 20}}, {{22, 26}}, {{16, 22}}, {{20, 26}}}},
5896 {{{{22, 26}}, {{17, 21}}, {{22, 17}}, {{26, 21}}}},
5897 {{{{20, 18}}, {{26, 23}}, {{20, 26}}, {{18, 23}}}},
5898 {{{{26, 23}}, {{21, 19}}, {{26, 21}}, {{23, 19}}}}}};
5899
5900 static constexpr ::ndarray<unsigned int, 12, 4, 2>
5901 table_tet = {
5902 {{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
5903 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
5904 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
5905 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
5906 {{{{4, 6}}, {{6, 8}}, {{8, 4}}, {{X, X}}}},
5907 {{{{6, 5}}, {{5, 8}}, {{8, 6}}, {{X, X}}}},
5908 {{{{8, 7}}, {{7, 6}}, {{6, 8}}, {{X, X}}}},
5909 {{{{9, 6}}, {{6, 8}}, {{8, 9}}, {{X, X}}}},
5910 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5911 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5912 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5913 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}};
5914
5915 const auto &new_quad_lines =
5916 (reference_cell_type == ReferenceCells::Hexahedron) ?
5917 new_quad_lines_hex :
5918 new_quad_lines_tet;
5919
5920 const auto &table =
5921 (reference_cell_type == ReferenceCells::Hexahedron) ?
5922 table_hex :
5923 table_tet;
5924
5925 static constexpr ::ndarray<unsigned int, 4, 2>
5926 representative_lines{
5927 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
5928
5929 for (unsigned int q = 0; q < n_new_quads; ++q)
5930 {
5931 auto &new_quad = new_quads[q];
5932
5933 if (new_quad->n_lines() == 3)
5934 new_quad->set_bounding_object_indices(
5935 {relevant_line_indices[new_quad_lines[q][0]],
5936 relevant_line_indices[new_quad_lines[q][1]],
5937 relevant_line_indices[new_quad_lines[q][2]]});
5938 else if (new_quad->n_lines() == 4)
5939 new_quad->set_bounding_object_indices(
5940 {relevant_line_indices[new_quad_lines[q][0]],
5941 relevant_line_indices[new_quad_lines[q][1]],
5942 relevant_line_indices[new_quad_lines[q][2]],
5943 relevant_line_indices[new_quad_lines[q][3]]});
5944 else
5945 Assert(false, ExcNotImplemented());
5946
5947 // On hexes, we must only determine a single line
5948 // according to the representative_lines array above
5949 // (this saves expensive operations), for tets we do
5950 // all lines manually
5951 const unsigned int n_compute_lines =
5952 reference_cell_type == ReferenceCells::Hexahedron ?
5953 1 :
5954 new_quad->n_lines();
5955 for (unsigned int line = 0; line < n_compute_lines;
5956 ++line)
5957 {
5958 const unsigned int l =
5959 (reference_cell_type ==
5961 representative_lines[q % 4][0] :
5962 line;
5963
5964 const std::array<unsigned int, 2> vertices_0 = {
5965 {relevant_lines[new_quad_lines[q][l]]
5966 ->vertex_index(0),
5967 relevant_lines[new_quad_lines[q][l]]
5968 ->vertex_index(1)}};
5969
5970 const std::array<unsigned int, 2> vertices_1 = {
5971 {vertex_indices[table[q][l][0]],
5972 vertex_indices[table[q][l][1]]}};
5973
5974 const auto orientation =
5976 make_array_view(vertices_0),
5977 make_array_view(vertices_1));
5978
5979 new_quad->set_line_orientation(l, orientation);
5980
5981 // on a hex, inject the status of the current line
5982 // also to the line on the other quad along the
5983 // same direction
5984 if (reference_cell_type ==
5986 new_quads[representative_lines[q % 4][1] + q -
5987 (q % 4)]
5988 ->set_line_orientation(l, orientation);
5989 }
5990 }
5991 }
5992
5993 // set up new hex
5994 {
5995 std::array<int, 36> quad_indices;
5996
5997 if (reference_cell_type == ReferenceCells::Hexahedron)
5998 {
5999 for (unsigned int i = 0; i < n_new_quads; ++i)
6000 quad_indices[i] = new_quads[i]->index();
6001
6002 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6003 for (unsigned int c = 0; c < 4; ++c, ++k)
6004 quad_indices[k] =
6005 hex->face(f)->isotropic_child_index(
6007 c,
6008 hex->face_orientation(f),
6009 hex->face_flip(f),
6010 hex->face_rotation(f)));
6011 }
6012 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6013 {
6014 for (unsigned int i = 0; i < n_new_quads; ++i)
6015 quad_indices[i] = new_quads[i]->index();
6016
6017 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6018 for (unsigned int c = 0; c < 4; ++c, ++k)
6019 {
6020 quad_indices[k] = hex->face(f)->child_index(
6021 (c == 3) ?
6022 3 :
6023 reference_cell_type
6024 .standard_to_real_face_vertex(
6025 c,
6026 f,
6027 triangulation.levels[hex->level()]
6028 ->face_orientations
6029 .get_combined_orientation(
6030 hex->index() *
6032 f)));
6033 }
6034 }
6035 else
6036 {
6037 Assert(false, ExcNotImplemented());
6038 }
6039
6040 static constexpr ::ndarray<unsigned int, 8, 6>
6041 cell_quads_hex = {{
6042 {{12, 0, 20, 4, 28, 8}}, // bottom children
6043 {{0, 16, 22, 6, 29, 9}}, //
6044 {{13, 1, 4, 24, 30, 10}}, //
6045 {{1, 17, 6, 26, 31, 11}}, //
6046 {{14, 2, 21, 5, 8, 32}}, // top children
6047 {{2, 18, 23, 7, 9, 33}}, //
6048 {{15, 3, 5, 25, 10, 34}}, //
6049 {{3, 19, 7, 27, 11, 35}} //
6050 }};
6051
6052 static constexpr ::ndarray<unsigned int, 8, 6>
6053 cell_quads_tet{{{{8, 13, 16, 0, X, X}},
6054 {{9, 12, 1, 21, X, X}},
6055 {{10, 2, 17, 20, X, X}},
6056 {{3, 14, 18, 22, X, X}},
6057 {{11, 1, 4, 5, X, X}},
6058 {{15, 0, 4, 6, X, X}},
6059 {{19, 7, 6, 3, X, X}},
6060 {{23, 5, 2, 7, X, X}}}};
6061
6062 static constexpr ::ndarray<unsigned int, 8, 6, 4>
6063 cell_face_vertices_tet{{{{{{0, 4, 6, X}},
6064 {{4, 0, 7, X}},
6065 {{0, 6, 7, X}},
6066 {{6, 4, 7, X}},
6067 {{X, X, X, X}},
6068 {{X, X, X, X}}}},
6069 {{{{4, 1, 5, X}},
6070 {{1, 4, 8, X}},
6071 {{4, 5, 8, X}},
6072 {{5, 1, 8, X}},
6073 {{X, X, X, X}},
6074 {{X, X, X, X}}}},
6075 {{{{6, 5, 2, X}},
6076 {{5, 6, 9, X}},
6077 {{6, 2, 9, X}},
6078 {{2, 5, 9, X}},
6079 {{X, X, X, X}},
6080 {{X, X, X, X}}}},
6081 {{{{7, 8, 9, X}},
6082 {{8, 7, 3, X}},
6083 {{7, 9, 3, X}},
6084 {{9, 8, 3, X}},
6085 {{X, X, X, X}},
6086 {{X, X, X, X}}}},
6087 {{{{4, 5, 6, X}},
6088 {{5, 4, 8, X}},
6089 {{4, 6, 8, X}},
6090 {{6, 5, 8, X}},
6091 {{X, X, X, X}},
6092 {{X, X, X, X}}}},
6093 {{{{4, 7, 8, X}},
6094 {{7, 4, 6, X}},
6095 {{4, 8, 6, X}},
6096 {{8, 7, 6, X}},
6097 {{X, X, X, X}},
6098 {{X, X, X, X}}}},
6099 {{{{6, 9, 7, X}},
6100 {{9, 6, 8, X}},
6101 {{6, 7, 8, X}},
6102 {{7, 9, 8, X}},
6103 {{X, X, X, X}},
6104 {{X, X, X, X}}}},
6105 {{{{5, 8, 9, X}},
6106 {{8, 5, 6, X}},
6107 {{5, 9, 6, X}},
6108 {{9, 8, 6, X}},
6109 {{X, X, X, X}},
6110 {{X, X, X, X}}}}}};
6111
6112 const auto &cell_quads =
6113 (reference_cell_type == ReferenceCells::Hexahedron) ?
6114 cell_quads_hex :
6115 cell_quads_tet;
6116
6117 for (unsigned int c = 0;
6118 c < GeometryInfo<dim>::max_children_per_cell;
6119 ++c)
6120 {
6121 auto &new_hex = new_hexes[c];
6122
6123 if (new_hex->n_faces() == 4)
6124 {
6125 new_hex->set_bounding_object_indices(
6126 {quad_indices[cell_quads[c][0]],
6127 quad_indices[cell_quads[c][1]],
6128 quad_indices[cell_quads[c][2]],
6129 quad_indices[cell_quads[c][3]]});
6130
6131 // for tets, we need to go through the faces and
6132 // figure the orientation out the hard way
6133 for (const auto f : new_hex->face_indices())
6134 {
6135 const auto &face = new_hex->face(f);
6136
6137 Assert(face->n_vertices() == 3,
6139
6140 const std::array<unsigned int, 3> vertices_0 = {
6141 {face->vertex_index(0),
6142 face->vertex_index(1),
6143 face->vertex_index(2)}};
6144
6145 const std::array<unsigned int, 3> vertices_1 = {
6146 {
6147 vertex_indices[cell_face_vertices_tet[c][f]
6148 [0]],
6149 vertex_indices[cell_face_vertices_tet[c][f]
6150 [1]],
6151 vertex_indices[cell_face_vertices_tet[c][f]
6152 [2]],
6153 }};
6154
6155 new_hex->set_combined_face_orientation(
6156 f,
6157 face->reference_cell()
6158 .get_combined_orientation(
6159 make_array_view(vertices_1),
6160 make_array_view(vertices_0)));
6161 }
6162 }
6163 else if (new_hex->n_faces() == 6)
6164 new_hex->set_bounding_object_indices(
6165 {quad_indices[cell_quads[c][0]],
6166 quad_indices[cell_quads[c][1]],
6167 quad_indices[cell_quads[c][2]],
6168 quad_indices[cell_quads[c][3]],
6169 quad_indices[cell_quads[c][4]],
6170 quad_indices[cell_quads[c][5]]});
6171 else
6172 Assert(false, ExcNotImplemented());
6173 }
6174
6175 // for hexes, we can simply inherit the orientation values
6176 // from the parent on the outer faces; the inner faces can
6177 // be skipped as their orientation is always the default
6178 // one set above
6179 static constexpr ::ndarray<unsigned int, 6, 4>
6180 face_to_child_indices_hex{{{{0, 2, 4, 6}},
6181 {{1, 3, 5, 7}},
6182 {{0, 1, 4, 5}},
6183 {{2, 3, 6, 7}},
6184 {{0, 1, 2, 3}},
6185 {{4, 5, 6, 7}}}};
6186 if (hex->n_faces() == 6)
6187 for (const auto f : hex->face_indices())
6188 {
6189 const unsigned char combined_orientation =
6190 hex->combined_face_orientation(f);
6191 for (unsigned int c = 0; c < 4; ++c)
6192 new_hexes[face_to_child_indices_hex[f][c]]
6193 ->set_combined_face_orientation(
6194 f, combined_orientation);
6195 }
6196 }
6197 }
6198
6199 if (check_for_distorted_cells &&
6200 has_distorted_children<dim, spacedim>(hex))
6201 cells_with_distorted_children.distorted_cells.push_back(hex);
6202
6203 triangulation.signals.post_refinement_on_cell(hex);
6204 }
6205 }
6206
6207 triangulation.faces->quads.clear_user_data();
6208
6209 return cells_with_distorted_children;
6210 }
6211
6216 template <int spacedim>
6219 const bool check_for_distorted_cells)
6220 {
6221 const unsigned int dim = 3;
6222
6223 {
6224 bool flag_isotropic_mesh = true;
6226 cell = triangulation.begin(),
6227 endc = triangulation.end();
6228 for (; cell != endc; ++cell)
6229 if (cell->used())
6230 if (triangulation.get_anisotropic_refinement_flag() ||
6231 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
6232 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
6233 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
6234 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
6235 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
6236 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
6237 {
6238 flag_isotropic_mesh = false;
6239 break;
6240 }
6241
6242 if (flag_isotropic_mesh)
6243 return execute_refinement_isotropic(triangulation,
6244 check_for_distorted_cells);
6245 }
6246
6247 // this function probably also works for spacedim>3 but it
6248 // isn't tested. it will probably be necessary to pull new
6249 // vertices onto the manifold just as we do for the other
6250 // functions above.
6251 Assert(spacedim == 3, ExcNotImplemented());
6252
6253 // Check whether a new level is needed. We have to check for
6254 // this on the highest level only
6255 for (const auto &cell : triangulation.active_cell_iterators_on_level(
6256 triangulation.levels.size() - 1))
6257 if (cell->refine_flag_set())
6258 {
6259 triangulation.levels.push_back(
6260 std::make_unique<
6262 break;
6263 }
6264
6265
6266 // first clear user flags for quads and lines; we're going to
6267 // use them to flag which lines and quads need refinement
6268 triangulation.faces->quads.clear_user_data();
6269
6271 triangulation.begin_line();
6272 line != triangulation.end_line();
6273 ++line)
6274 line->clear_user_flag();
6276 triangulation.begin_quad();
6277 quad != triangulation.end_quad();
6278 ++quad)
6279 quad->clear_user_flag();
6280
6281 // create an array of face refine cases. User indices of faces
6282 // will be set to values corresponding with indices in this
6283 // array.
6284 const RefinementCase<dim - 1> face_refinement_cases[4] = {
6285 RefinementCase<dim - 1>::no_refinement,
6286 RefinementCase<dim - 1>::cut_x,
6287 RefinementCase<dim - 1>::cut_y,
6288 RefinementCase<dim - 1>::cut_xy};
6289
6290 // check how much space is needed on every level. We need not
6291 // check the highest level since either
6292 // - on the highest level no cells are flagged for refinement
6293 // - there are, but prepare_refinement added another empty
6294 // level which then is the highest level
6295
6296 // variables to hold the number of newly to be created
6297 // vertices, lines and quads. as these are stored globally,
6298 // declare them outside the loop over al levels. we need lines
6299 // and quads in pairs for refinement of old ones and lines and
6300 // quads, that can be stored as single ones, as they are newly
6301 // created in the inside of an existing cell
6302 unsigned int needed_vertices = 0;
6303 unsigned int needed_lines_single = 0;
6304 unsigned int needed_quads_single = 0;
6305 unsigned int needed_lines_pair = 0;
6306 unsigned int needed_quads_pair = 0;
6307 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
6308 {
6309 // count number of flagged cells on this level and compute
6310 // how many new vertices and new lines will be needed
6311 unsigned int new_cells = 0;
6312
6313 for (const auto &acell :
6314 triangulation.active_cell_iterators_on_level(level))
6315 if (acell->refine_flag_set())
6316 {
6317 RefinementCase<dim> ref_case = acell->refine_flag_set();
6318
6319 // now for interior vertices, lines and quads, which
6320 // are needed in any case
6321 if (ref_case == RefinementCase<dim>::cut_x ||
6322 ref_case == RefinementCase<dim>::cut_y ||
6323 ref_case == RefinementCase<dim>::cut_z)
6324 {
6325 ++needed_quads_single;
6326 new_cells += 2;
6327 triangulation.anisotropic_refinement = true;
6328 }
6329 else if (ref_case == RefinementCase<dim>::cut_xy ||
6330 ref_case == RefinementCase<dim>::cut_xz ||
6331 ref_case == RefinementCase<dim>::cut_yz)
6332 {
6333 ++needed_lines_single;
6334 needed_quads_single += 4;
6335 new_cells += 4;
6336 triangulation.anisotropic_refinement = true;
6337 }
6338 else if (ref_case == RefinementCase<dim>::cut_xyz)
6339 {
6340 ++needed_vertices;
6341 needed_lines_single += 6;
6342 needed_quads_single += 12;
6343 new_cells += 8;
6344 }
6345 else
6346 {
6347 // we should never get here
6348 Assert(false, ExcInternalError());
6349 }
6350
6351 // mark all faces for refinement; checking locally
6352 // if and how the neighbor would like to refine
6353 // these is difficult so we only flag them and after
6354 // visiting all cells, we decide which faces need
6355 // which refinement;
6356 for (const unsigned int face :
6358 {
6360 aface = acell->face(face);
6361 // get the RefineCase this faces has for the
6362 // given RefineCase of the cell
6363 RefinementCase<dim - 1> face_ref_case =
6365 ref_case,
6366 face,
6367 acell->face_orientation(face),
6368 acell->face_flip(face),
6369 acell->face_rotation(face));
6370 // only do something, if this face has to be
6371 // refined
6372 if (face_ref_case)
6373 {
6374 if (face_ref_case ==
6376 {
6377 if (aface->n_active_descendants() < 4)
6378 // we use user_flags to denote needed
6379 // isotropic refinement
6380 aface->set_user_flag();
6381 }
6382 else if (aface->refinement_case() != face_ref_case)
6383 // we use user_indices to denote needed
6384 // anisotropic refinement. note, that we
6385 // can have at most one anisotropic
6386 // refinement case for this face, as
6387 // otherwise prepare_refinement() would
6388 // have changed one of the cells to yield
6389 // isotropic refinement at this
6390 // face. therefore we set the user_index
6391 // uniquely
6392 {
6393 Assert(aface->refinement_case() ==
6395 dim - 1>::isotropic_refinement ||
6396 aface->refinement_case() ==
6399 aface->set_user_index(face_ref_case);
6400 }
6401 }
6402 } // for all faces
6403
6404 // flag all lines, that have to be refined
6405 for (unsigned int line = 0;
6406 line < GeometryInfo<dim>::lines_per_cell;
6407 ++line)
6409 line) &&
6410 !acell->line(line)->has_children())
6411 acell->line(line)->set_user_flag();
6412
6413 } // if refine_flag set and for all cells on this level
6414
6415
6416 // count number of used cells on the next higher level
6417 const unsigned int used_cells =
6418 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6419 triangulation.levels[level + 1]->cells.used.end(),
6420 true);
6421
6422
6423 // reserve space for the used_cells cells already existing
6424 // on the next higher level as well as for the
6425 // 8*flagged_cells that will be created on that level
6426 reserve_space(*triangulation.levels[level + 1],
6427 used_cells + new_cells,
6428 3,
6429 spacedim);
6430 // reserve space for 8*flagged_cells new hexes on the next
6431 // higher level
6432 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6433 } // for all levels
6434 // now count the quads and lines which were flagged for
6435 // refinement
6437 triangulation.begin_quad();
6438 quad != triangulation.end_quad();
6439 ++quad)
6440 {
6441 if (quad->user_flag_set())
6442 {
6443 // isotropic refinement: 1 interior vertex, 4 quads
6444 // and 4 interior lines. we store the interior lines
6445 // in pairs in case the face is already or will be
6446 // refined anisotropically
6447 needed_quads_pair += 4;
6448 needed_lines_pair += 4;
6449 needed_vertices += 1;
6450 }
6451 if (quad->user_index())
6452 {
6453 // anisotropic refinement: 1 interior
6454 // line and two quads
6455 needed_quads_pair += 2;
6456 needed_lines_single += 1;
6457 // there is a kind of complicated situation here which
6458 // requires our attention. if the quad is refined
6459 // isotropcally, two of the interior lines will get a
6460 // new mother line - the interior line of our
6461 // anisotropically refined quad. if those two lines
6462 // are not consecutive, we cannot do so and have to
6463 // replace them by two lines that are consecutive. we
6464 // try to avoid that situation, but it may happen
6465 // nevertheless through repeated refinement and
6466 // coarsening. thus we have to check here, as we will
6467 // need some additional space to store those new lines
6468 // in case we need them...
6469 if (quad->has_children())
6470 {
6471 Assert(quad->refinement_case() ==
6474 if ((face_refinement_cases[quad->user_index()] ==
6476 (quad->child(0)->line_index(1) + 1 !=
6477 quad->child(2)->line_index(1))) ||
6478 (face_refinement_cases[quad->user_index()] ==
6480 (quad->child(0)->line_index(3) + 1 !=
6481 quad->child(1)->line_index(3))))
6482 needed_lines_pair += 2;
6483 }
6484 }
6485 }
6486
6488 triangulation.begin_line();
6489 line != triangulation.end_line();
6490 ++line)
6491 if (line->user_flag_set())
6492 {
6493 needed_lines_pair += 2;
6494 needed_vertices += 1;
6495 }
6496
6497 // reserve space for needed_lines new lines stored in pairs
6498 reserve_space(triangulation.faces->lines,
6499 needed_lines_pair,
6500 needed_lines_single);
6501 // reserve space for needed_quads new quads stored in pairs
6503 needed_quads_pair,
6504 needed_quads_single);
6505 reserve_space(triangulation.faces->quads,
6506 needed_quads_pair,
6507 needed_quads_single);
6508
6509
6510 // add to needed vertices how many vertices are already in use
6511 needed_vertices += std::count(triangulation.vertices_used.begin(),
6512 triangulation.vertices_used.end(),
6513 true);
6514 // if we need more vertices: create them, if not: leave the
6515 // array as is, since shrinking is not really possible because
6516 // some of the vertices at the end may be in use
6517 if (needed_vertices > triangulation.vertices.size())
6518 {
6519 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6520 triangulation.vertices_used.resize(needed_vertices, false);
6521 }
6522
6523
6524 //-----------------------------------------
6525 // Before we start with the actual refinement, we do some
6526 // sanity checks if in debug mode. especially, we try to catch
6527 // the notorious problem with lines being twice refined,
6528 // i.e. there are cells adjacent at one line ("around the
6529 // edge", but not at a face), with two cells differing by more
6530 // than one refinement level
6531 //
6532 // this check is very simple to implement here, since we have
6533 // all lines flagged if they shall be refined
6534#ifdef DEBUG
6535 for (const auto &cell : triangulation.active_cell_iterators())
6536 if (!cell->refine_flag_set())
6537 for (unsigned int line = 0;
6538 line < GeometryInfo<dim>::lines_per_cell;
6539 ++line)
6540 if (cell->line(line)->has_children())
6541 for (unsigned int c = 0; c < 2; ++c)
6542 Assert(cell->line(line)->child(c)->user_flag_set() == false,
6544#endif
6545
6546 //-----------------------------------------
6547 // Do refinement on every level
6548 //
6549 // To make life a bit easier, we first refine those lines and
6550 // quads that were flagged for refinement and then compose the
6551 // newly to be created cells.
6552 //
6553 // index of next unused vertex
6554 unsigned int next_unused_vertex = 0;
6555
6556 // first for lines
6557 {
6558 // only active objects can be refined further
6560 line = triangulation.begin_active_line(),
6561 endl = triangulation.end_line();
6563 next_unused_line = triangulation.begin_raw_line();
6564
6565 for (; line != endl; ++line)
6566 if (line->user_flag_set())
6567 {
6568 // this line needs to be refined
6569
6570 // find the next unused vertex and set it
6571 // appropriately
6572 while (triangulation.vertices_used[next_unused_vertex] == true)
6573 ++next_unused_vertex;
6574 Assert(
6575 next_unused_vertex < triangulation.vertices.size(),
6576 ExcMessage(
6577 "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."));
6578 triangulation.vertices_used[next_unused_vertex] = true;
6579
6580 triangulation.vertices[next_unused_vertex] = line->center(true);
6581
6582 // now that we created the right point, make up the
6583 // two child lines (++ takes care of the end of the
6584 // vector)
6585 next_unused_line =
6586 triangulation.faces->lines.template next_free_pair_object<1>(
6588 Assert(next_unused_line.state() == IteratorState::valid,
6590
6591 // now we found two consecutive unused lines, such
6592 // that the children of a line will be consecutive.
6593 // then set the child pointer of the present line
6594 line->set_children(0, next_unused_line->index());
6595
6596 // set the two new lines
6598 children[2] = {next_unused_line, ++next_unused_line};
6599
6600 // some tests; if any of the iterators should be
6601 // invalid, then already dereferencing will fail
6602 AssertIsNotUsed(children[0]);
6603 AssertIsNotUsed(children[1]);
6604
6605 children[0]->set_bounding_object_indices(
6606 {line->vertex_index(0), next_unused_vertex});
6607 children[1]->set_bounding_object_indices(
6608 {next_unused_vertex, line->vertex_index(1)});
6609
6610 children[0]->set_used_flag();
6611 children[1]->set_used_flag();
6612 children[0]->clear_children();
6613 children[1]->clear_children();
6614 children[0]->clear_user_data();
6615 children[1]->clear_user_data();
6616 children[0]->clear_user_flag();
6617 children[1]->clear_user_flag();
6618
6619 children[0]->set_boundary_id_internal(line->boundary_id());
6620 children[1]->set_boundary_id_internal(line->boundary_id());
6621
6622 children[0]->set_manifold_id(line->manifold_id());
6623 children[1]->set_manifold_id(line->manifold_id());
6624
6625 // finally clear flag
6626 // indicating the need
6627 // for refinement
6628 line->clear_user_flag();
6629 }
6630 }
6631
6632
6633 //-------------------------------------
6634 // now refine marked quads
6635 //-------------------------------------
6636
6637 // here we encounter several cases:
6638
6639 // a) the quad is unrefined and shall be refined isotropically
6640
6641 // b) the quad is unrefined and shall be refined
6642 // anisotropically
6643
6644 // c) the quad is unrefined and shall be refined both
6645 // anisotropically and isotropically (this is reduced to case
6646 // b) and then case b) for the children again)
6647
6648 // d) the quad is refined anisotropically and shall be refined
6649 // isotropically (this is reduced to case b) for the
6650 // anisotropic children)
6651
6652 // e) the quad is refined isotropically and shall be refined
6653 // anisotropically (this is transformed to case c), however we
6654 // might have to renumber/rename children...)
6655
6656 // we need a loop in cases c) and d), as the anisotropic
6657 // children might have a lower index than the mother quad
6658 for (unsigned int loop = 0; loop < 2; ++loop)
6659 {
6660 // usually, only active objects can be refined
6661 // further. however, in cases d) and e) that is not true,
6662 // so we have to use 'normal' iterators here
6664 quad = triangulation.begin_quad(),
6665 endq = triangulation.end_quad();
6667 next_unused_line = triangulation.begin_raw_line();
6669 next_unused_quad = triangulation.begin_raw_quad();
6670
6671 for (; quad != endq; ++quad)
6672 {
6673 if (quad->user_index())
6674 {
6675 RefinementCase<dim - 1> aniso_quad_ref_case =
6676 face_refinement_cases[quad->user_index()];
6677 // there is one unlikely event here, where we
6678 // already have refind the face: if the face was
6679 // refined anisotropically and we want to refine
6680 // it isotropically, both children are flagged for
6681 // anisotropic refinement. however, if those
6682 // children were already flagged for anisotropic
6683 // refinement, they might already be processed and
6684 // refined.
6685 if (aniso_quad_ref_case == quad->refinement_case())
6686 continue;
6687
6688 Assert(quad->refinement_case() ==
6690 quad->refinement_case() ==
6693
6694 // this quad needs to be refined anisotropically
6695 Assert(quad->user_index() ==
6697 quad->user_index() ==
6700
6701 // make the new line interior to the quad
6703 new_line;
6704
6705 new_line =
6706 triangulation.faces->lines
6707 .template next_free_single_object<1>(triangulation);
6708 AssertIsNotUsed(new_line);
6709
6710 // first collect the
6711 // indices of the vertices:
6712 // *--1--*
6713 // | | |
6714 // | | | cut_x
6715 // | | |
6716 // *--0--*
6717 //
6718 // *-----*
6719 // | |
6720 // 0-----1 cut_y
6721 // | |
6722 // *-----*
6723 unsigned int vertex_indices[2];
6724 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6725 {
6726 vertex_indices[0] =
6727 quad->line(2)->child(0)->vertex_index(1);
6728 vertex_indices[1] =
6729 quad->line(3)->child(0)->vertex_index(1);
6730 }
6731 else
6732 {
6733 vertex_indices[0] =
6734 quad->line(0)->child(0)->vertex_index(1);
6735 vertex_indices[1] =
6736 quad->line(1)->child(0)->vertex_index(1);
6737 }
6738
6739 new_line->set_bounding_object_indices(
6741 new_line->set_used_flag();
6742 new_line->clear_user_flag();
6743 new_line->clear_user_data();
6744 new_line->clear_children();
6745 new_line->set_boundary_id_internal(quad->boundary_id());
6746 new_line->set_manifold_id(quad->manifold_id());
6747
6748 // child 0 and 1 of a line are switched if the
6749 // line orientation is false. set up a miniature
6750 // table, indicating which child to take for line
6751 // orientations false and true. first index: child
6752 // index in standard orientation, second index:
6753 // line orientation
6754 const unsigned int index[2][2] = {
6755 {1, 0}, // child 0, line_orientation=false and true
6756 {0, 1}}; // child 1, line_orientation=false and true
6757
6758 // find some space (consecutive) for the two newly
6759 // to be created quads.
6761 new_quads[2];
6762
6763 next_unused_quad =
6764 triangulation.faces->quads
6765 .template next_free_pair_object<2>(triangulation);
6766 new_quads[0] = next_unused_quad;
6767 AssertIsNotUsed(new_quads[0]);
6768
6769 ++next_unused_quad;
6770 new_quads[1] = next_unused_quad;
6771 AssertIsNotUsed(new_quads[1]);
6772
6773 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6774 {
6775 new_quads[0]->set_bounding_object_indices(
6776 {static_cast<int>(quad->line_index(0)),
6777 new_line->index(),
6778 quad->line(2)
6779 ->child(index[0][quad->line_orientation(2)])
6780 ->index(),
6781 quad->line(3)
6782 ->child(index[0][quad->line_orientation(3)])
6783 ->index()});
6784 new_quads[1]->set_bounding_object_indices(
6785 {new_line->index(),
6786 static_cast<int>(quad->line_index(1)),
6787 quad->line(2)
6788 ->child(index[1][quad->line_orientation(2)])
6789 ->index(),
6790 quad->line(3)
6791 ->child(index[1][quad->line_orientation(3)])
6792 ->index()});
6793 }
6794 else
6795 {
6796 new_quads[0]->set_bounding_object_indices(
6797 {quad->line(0)
6798 ->child(index[0][quad->line_orientation(0)])
6799 ->index(),
6800 quad->line(1)
6801 ->child(index[0][quad->line_orientation(1)])
6802 ->index(),
6803 static_cast<int>(quad->line_index(2)),
6804 new_line->index()});
6805 new_quads[1]->set_bounding_object_indices(
6806 {quad->line(0)
6807 ->child(index[1][quad->line_orientation(0)])
6808 ->index(),
6809 quad->line(1)
6810 ->child(index[1][quad->line_orientation(1)])
6811 ->index(),
6812 new_line->index(),
6813 static_cast<int>(quad->line_index(3))});
6814 }
6815
6816 for (const auto &new_quad : new_quads)
6817 {
6818 new_quad->set_used_flag();
6819 new_quad->clear_user_flag();
6820 new_quad->clear_user_data();
6821 new_quad->clear_children();
6822 new_quad->set_boundary_id_internal(quad->boundary_id());
6823 new_quad->set_manifold_id(quad->manifold_id());
6824 // set all line orientations to true, change
6825 // this after the loop, as we have to consider
6826 // different lines for each child
6827 for (unsigned int j = 0;
6828 j < GeometryInfo<dim>::lines_per_face;
6829 ++j)
6830 new_quad->set_line_orientation(j, true);
6831 }
6832 // now set the line orientation of children of
6833 // outer lines correctly, the lines in the
6834 // interior of the refined quad are automatically
6835 // oriented conforming to the standard
6836 new_quads[0]->set_line_orientation(
6837 0, quad->line_orientation(0));
6838 new_quads[0]->set_line_orientation(
6839 2, quad->line_orientation(2));
6840 new_quads[1]->set_line_orientation(
6841 1, quad->line_orientation(1));
6842 new_quads[1]->set_line_orientation(
6843 3, quad->line_orientation(3));
6844 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6845 {
6846 new_quads[0]->set_line_orientation(
6847 3, quad->line_orientation(3));
6848 new_quads[1]->set_line_orientation(
6849 2, quad->line_orientation(2));
6850 }
6851 else
6852 {
6853 new_quads[0]->set_line_orientation(
6854 1, quad->line_orientation(1));
6855 new_quads[1]->set_line_orientation(
6856 0, quad->line_orientation(0));
6857 }
6858
6859 // test, whether this face is refined
6860 // isotropically already. if so, set the correct
6861 // children pointers.
6862 if (quad->refinement_case() ==
6863 RefinementCase<dim - 1>::cut_xy)
6864 {
6865 // we will put a new refinemnt level of
6866 // anisotropic refinement between the
6867 // unrefined and isotropically refined quad
6868 // ending up with the same fine quads but
6869 // introducing anisotropically refined ones as
6870 // children of the unrefined quad and mother
6871 // cells of the original fine ones.
6872
6873 // this process includes the creation of a new
6874 // middle line which we will assign as the
6875 // mother line of two of the existing inner
6876 // lines. If those inner lines are not
6877 // consecutive in memory, we won't find them
6878 // later on, so we have to create new ones
6879 // instead and replace all occurrences of the
6880 // old ones with those new ones. As this is
6881 // kind of ugly, we hope we don't have to do
6882 // it often...
6884 old_child[2];
6885 if (aniso_quad_ref_case ==
6887 {
6888 old_child[0] = quad->child(0)->line(1);
6889 old_child[1] = quad->child(2)->line(1);
6890 }
6891 else
6892 {
6893 Assert(aniso_quad_ref_case ==
6896
6897 old_child[0] = quad->child(0)->line(3);
6898 old_child[1] = quad->child(1)->line(3);
6899 }
6900
6901 if (old_child[0]->index() + 1 != old_child[1]->index())
6902 {
6903 // this is exactly the ugly case we taked
6904 // about. so, no coimplaining, lets get
6905 // two new lines and copy all info
6906 typename Triangulation<dim,
6907 spacedim>::raw_line_iterator
6908 new_child[2];
6909
6910 new_child[0] = new_child[1] =
6911 triangulation.faces->lines
6912 .template next_free_pair_object<1>(
6914 ++new_child[1];
6915
6916 new_child[0]->set_used_flag();
6917 new_child[1]->set_used_flag();
6918
6919 const int old_index_0 = old_child[0]->index(),
6920 old_index_1 = old_child[1]->index(),
6921 new_index_0 = new_child[0]->index(),
6922 new_index_1 = new_child[1]->index();
6923
6924 // loop over all quads and replace the old
6925 // lines
6926 for (unsigned int q = 0;
6927 q < triangulation.faces->quads.n_objects();
6928 ++q)
6929 for (unsigned int l = 0;
6930 l < GeometryInfo<dim>::lines_per_face;
6931 ++l)
6932 {
6933 const int this_index =
6934 triangulation.faces->quads
6935 .get_bounding_object_indices(q)[l];
6936 if (this_index == old_index_0)
6937 triangulation.faces->quads
6938 .get_bounding_object_indices(q)[l] =
6939 new_index_0;
6940 else if (this_index == old_index_1)
6941 triangulation.faces->quads
6942 .get_bounding_object_indices(q)[l] =
6943 new_index_1;
6944 }
6945 // now we have to copy all information of
6946 // the two lines
6947 for (unsigned int i = 0; i < 2; ++i)
6948 {
6949 Assert(!old_child[i]->has_children(),
6951
6952 new_child[i]->set_bounding_object_indices(
6953 {old_child[i]->vertex_index(0),
6954 old_child[i]->vertex_index(1)});
6955 new_child[i]->set_boundary_id_internal(
6956 old_child[i]->boundary_id());
6957 new_child[i]->set_manifold_id(
6958 old_child[i]->manifold_id());
6959 new_child[i]->set_user_index(
6960 old_child[i]->user_index());
6961 if (old_child[i]->user_flag_set())
6962 new_child[i]->set_user_flag();
6963 else
6964 new_child[i]->clear_user_flag();
6965
6966 new_child[i]->clear_children();
6967
6968 old_child[i]->clear_user_flag();
6969 old_child[i]->clear_user_index();
6970 old_child[i]->clear_used_flag();
6971 }
6972 }
6973 // now that we cared about the lines, go on
6974 // with the quads themselves, where we might
6975 // encounter similar situations...
6976 if (aniso_quad_ref_case ==
6978 {
6979 new_line->set_children(
6980 0, quad->child(0)->line_index(1));
6981 Assert(new_line->child(1) ==
6982 quad->child(2)->line(1),
6984 // now evereything is quite
6985 // complicated. we have the children
6986 // numbered according to
6987 //
6988 // *---*---*
6989 // |n+2|n+3|
6990 // *---*---*
6991 // | n |n+1|
6992 // *---*---*
6993 //
6994 // from the original isotropic
6995 // refinement. we have to reorder them as
6996 //
6997 // *---*---*
6998 // |n+1|n+3|
6999 // *---*---*
7000 // | n |n+2|
7001 // *---*---*
7002 //
7003 // such that n and n+1 are consecutive
7004 // children of m and n+2 and n+3 are
7005 // consecutive children of m+1, where m
7006 // and m+1 are given as in
7007 //
7008 // *---*---*
7009 // | | |
7010 // | m |m+1|
7011 // | | |
7012 // *---*---*
7013 //
7014 // this is a bit ugly, of course: loop
7015 // over all cells on all levels and look
7016 // for faces n+1 (switch_1) and n+2
7017 // (switch_2).
7018 const typename Triangulation<dim, spacedim>::
7019 quad_iterator switch_1 = quad->child(1),
7020 switch_2 = quad->child(2);
7021 const int switch_1_index = switch_1->index();
7022 const int switch_2_index = switch_2->index();
7023 for (unsigned int l = 0;
7024 l < triangulation.levels.size();
7025 ++l)
7026 for (unsigned int h = 0;
7027 h <
7028 triangulation.levels[l]->cells.n_objects();
7029 ++h)
7030 for (const unsigned int q :
7032 {
7033 const int face_index =
7034 triangulation.levels[l]
7035 ->cells.get_bounding_object_indices(
7036 h)[q];
7037 if (face_index == switch_1_index)
7038 triangulation.levels[l]
7039 ->cells.get_bounding_object_indices(
7040 h)[q] = switch_2_index;
7041 else if (face_index == switch_2_index)
7042 triangulation.levels[l]
7043 ->cells.get_bounding_object_indices(
7044 h)[q] = switch_1_index;
7045 }
7046 // now we have to copy all information of
7047 // the two quads
7048 const unsigned int switch_1_lines[4] = {
7049 switch_1->line_index(0),
7050 switch_1->line_index(1),
7051 switch_1->line_index(2),
7052 switch_1->line_index(3)};
7053 const bool switch_1_line_orientations[4] = {
7054 switch_1->line_orientation(0),
7055 switch_1->line_orientation(1),
7056 switch_1->line_orientation(2),
7057 switch_1->line_orientation(3)};
7058 const types::boundary_id switch_1_boundary_id =
7059 switch_1->boundary_id();
7060 const unsigned int switch_1_user_index =
7061 switch_1->user_index();
7062 const bool switch_1_user_flag =
7063 switch_1->user_flag_set();
7064 const RefinementCase<dim - 1>
7065 switch_1_refinement_case =
7066 switch_1->refinement_case();
7067 const int switch_1_first_child_pair =
7068 (switch_1_refinement_case ?
7069 switch_1->child_index(0) :
7070 -1);
7071 const int switch_1_second_child_pair =
7072 (switch_1_refinement_case ==
7073 RefinementCase<dim - 1>::cut_xy ?
7074 switch_1->child_index(2) :
7075 -1);
7076
7077 switch_1->set_bounding_object_indices(
7078 {switch_2->line_index(0),
7079 switch_2->line_index(1),
7080 switch_2->line_index(2),
7081 switch_2->line_index(3)});
7082 switch_1->set_line_orientation(
7083 0, switch_2->line_orientation(0));
7084 switch_1->set_line_orientation(
7085 1, switch_2->line_orientation(1));
7086 switch_1->set_line_orientation(
7087 2, switch_2->line_orientation(2));
7088 switch_1->set_line_orientation(
7089 3, switch_2->line_orientation(3));
7090 switch_1->set_boundary_id_internal(
7091 switch_2->boundary_id());
7092 switch_1->set_manifold_id(switch_2->manifold_id());
7093 switch_1->set_user_index(switch_2->user_index());
7094 if (switch_2->user_flag_set())
7095 switch_1->set_user_flag();
7096 else
7097 switch_1->clear_user_flag();
7098 switch_1->clear_refinement_case();
7099 switch_1->set_refinement_case(
7100 switch_2->refinement_case());
7101 switch_1->clear_children();
7102 if (switch_2->refinement_case())
7103 switch_1->set_children(0,
7104 switch_2->child_index(0));
7105 if (switch_2->refinement_case() ==
7106 RefinementCase<dim - 1>::cut_xy)
7107 switch_1->set_children(2,
7108 switch_2->child_index(2));
7109
7110 switch_2->set_bounding_object_indices(
7111 {switch_1_lines[0],
7112 switch_1_lines[1],
7113 switch_1_lines[2],
7114 switch_1_lines[3]});
7115 switch_2->set_line_orientation(
7116 0, switch_1_line_orientations[0]);
7117 switch_2->set_line_orientation(
7118 1, switch_1_line_orientations[1]);
7119 switch_2->set_line_orientation(
7120 2, switch_1_line_orientations[2]);
7121 switch_2->set_line_orientation(
7122 3, switch_1_line_orientations[3]);
7123 switch_2->set_boundary_id_internal(
7124 switch_1_boundary_id);
7125 switch_2->set_manifold_id(switch_1->manifold_id());
7126 switch_2->set_user_index(switch_1_user_index);
7127 if (switch_1_user_flag)
7128 switch_2->set_user_flag();
7129 else
7130 switch_2->clear_user_flag();
7131 switch_2->clear_refinement_case();
7132 switch_2->set_refinement_case(
7133 switch_1_refinement_case);
7134 switch_2->clear_children();
7135 switch_2->set_children(0,
7136 switch_1_first_child_pair);
7137 switch_2->set_children(2,
7138 switch_1_second_child_pair);
7139
7140 new_quads[0]->set_refinement_case(
7142 new_quads[0]->set_children(0, quad->child_index(0));
7143 new_quads[1]->set_refinement_case(
7145 new_quads[1]->set_children(0, quad->child_index(2));
7146 }
7147 else
7148 {
7149 new_quads[0]->set_refinement_case(
7151 new_quads[0]->set_children(0, quad->child_index(0));
7152 new_quads[1]->set_refinement_case(
7154 new_quads[1]->set_children(0, quad->child_index(2));
7155 new_line->set_children(
7156 0, quad->child(0)->line_index(3));
7157 Assert(new_line->child(1) ==
7158 quad->child(1)->line(3),
7160 }
7161 quad->clear_children();
7162 }
7163
7164 // note these quads as children to the present one
7165 quad->set_children(0, new_quads[0]->index());
7166
7167 quad->set_refinement_case(aniso_quad_ref_case);
7168
7169 // finally clear flag indicating the need for
7170 // refinement
7171 quad->clear_user_data();
7172 } // if (anisotropic refinement)
7173
7174 if (quad->user_flag_set())
7175 {
7176 // this quad needs to be refined isotropically
7177
7178 // first of all: we only get here in the first run
7179 // of the loop
7180 Assert(loop == 0, ExcInternalError());
7181
7182 // find the next unused vertex. we'll need this in
7183 // any case
7184 while (triangulation.vertices_used[next_unused_vertex] ==
7185 true)
7186 ++next_unused_vertex;
7187 Assert(
7188 next_unused_vertex < triangulation.vertices.size(),
7189 ExcMessage(
7190 "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."));
7191
7192 // now: if the quad is refined anisotropically
7193 // already, set the anisotropic refinement flag
7194 // for both children. Additionally, we have to
7195 // refine the inner line, as it is an outer line
7196 // of the two (anisotropic) children
7197 const RefinementCase<dim - 1> quad_ref_case =
7198 quad->refinement_case();
7199
7200 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
7201 quad_ref_case == RefinementCase<dim - 1>::cut_y)
7202 {
7203 // set the 'opposite' refine case for children
7204 quad->child(0)->set_user_index(
7205 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
7206 quad->child(1)->set_user_index(
7207 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
7208 // refine the inner line
7210 middle_line;
7211 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
7212 middle_line = quad->child(0)->line(1);
7213 else
7214 middle_line = quad->child(0)->line(3);
7215
7216 // if the face has been refined
7217 // anisotropically in the last refinement step
7218 // it might be, that it is flagged already and
7219 // that the middle line is thus refined
7220 // already. if not create children.
7221 if (!middle_line->has_children())
7222 {
7223 // set the middle vertex
7224 // appropriately. double refinement of
7225 // quads can only happen in the interior
7226 // of the domain, so we need not care
7227 // about boundary quads here
7228 triangulation.vertices[next_unused_vertex] =
7229 middle_line->center(true);
7230 triangulation.vertices_used[next_unused_vertex] =
7231 true;
7232
7233 // now search a slot for the two
7234 // child lines
7235 next_unused_line =
7236 triangulation.faces->lines
7237 .template next_free_pair_object<1>(
7239
7240 // set the child pointer of the present
7241 // line
7242 middle_line->set_children(
7243 0, next_unused_line->index());
7244
7245 // set the two new lines
7246 const typename Triangulation<dim, spacedim>::
7247 raw_line_iterator children[2] = {
7248 next_unused_line, ++next_unused_line};
7249
7250 // some tests; if any of the iterators
7251 // should be invalid, then already
7252 // dereferencing will fail
7253 AssertIsNotUsed(children[0]);
7254 AssertIsNotUsed(children[1]);
7255
7256 children[0]->set_bounding_object_indices(
7257 {middle_line->vertex_index(0),
7258 next_unused_vertex});
7259 children[1]->set_bounding_object_indices(
7260 {next_unused_vertex,
7261 middle_line->vertex_index(1)});
7262
7263 children[0]->set_used_flag();
7264 children[1]->set_used_flag();
7265 children[0]->clear_children();
7266 children[1]->clear_children();
7267 children[0]->clear_user_data();
7268 children[1]->clear_user_data();
7269 children[0]->clear_user_flag();
7270 children[1]->clear_user_flag();
7271
7272 children[0]->set_boundary_id_internal(
7273 middle_line->boundary_id());
7274 children[1]->set_boundary_id_internal(
7275 middle_line->boundary_id());
7276
7277 children[0]->set_manifold_id(
7278 middle_line->manifold_id());
7279 children[1]->set_manifold_id(
7280 middle_line->manifold_id());
7281 }
7282 // now remove the flag from the quad and go to
7283 // the next quad, the actual refinement of the
7284 // quad takes place later on in this pass of
7285 // the loop or in the next one
7286 quad->clear_user_flag();
7287 continue;
7288 } // if (several refinement cases)
7289
7290 // if we got here, we have an unrefined quad and
7291 // have to do the usual work like in an purely
7292 // isotropic refinement
7293 Assert(quad_ref_case ==
7296
7297 // set the middle vertex appropriately: it might be that
7298 // the quad itself is not at the boundary, but that one of
7299 // its lines actually is. in this case, the newly created
7300 // vertices at the centers of the lines are not
7301 // necessarily the mean values of the adjacent vertices,
7302 // so do not compute the new vertex as the mean value of
7303 // the 4 vertices of the face, but rather as a weighted
7304 // mean value of the 8 vertices which we already have (the
7305 // four old ones, and the four ones inserted as middle
7306 // points for the four lines). summing up some more points
7307 // is generally cheaper than first asking whether one of
7308 // the lines is at the boundary
7309 //
7310 // note that the exact weights are chosen such as to
7311 // minimize the distortion of the four new quads from the
7312 // optimal shape. their description uses the formulas
7313 // underlying the TransfiniteInterpolationManifold
7314 // implementation
7315 triangulation.vertices[next_unused_vertex] =
7316 quad->center(true, true);
7317 triangulation.vertices_used[next_unused_vertex] = true;
7318
7319 // now that we created the right point, make up
7320 // the four lines interior to the quad (++ takes
7321 // care of the end of the vector)
7323 new_lines[4];
7324
7325 for (unsigned int i = 0; i < 4; ++i)
7326 {
7327 if (i % 2 == 0)
7328 // search a free pair of lines for 0. and
7329 // 2. line, so that two of them end up
7330 // together, which is necessary if later on
7331 // we want to refine the quad
7332 // anisotropically and the two lines end up
7333 // as children of new line
7334 next_unused_line =
7335 triangulation.faces->lines
7336 .template next_free_pair_object<1>(triangulation);
7337
7338 new_lines[i] = next_unused_line;
7339 ++next_unused_line;
7340
7341 AssertIsNotUsed(new_lines[i]);
7342 }
7343
7344 // set the data of the four lines. first collect
7345 // the indices of the five vertices:
7346 //
7347 // *--3--*
7348 // | | |
7349 // 0--4--1
7350 // | | |
7351 // *--2--*
7352 //
7353 // the lines are numbered as follows:
7354 //
7355 // *--*--*
7356 // | 1 |
7357 // *2-*-3*
7358 // | 0 |
7359 // *--*--*
7360
7361 const unsigned int vertex_indices[5] = {
7362 quad->line(0)->child(0)->vertex_index(1),
7363 quad->line(1)->child(0)->vertex_index(1),
7364 quad->line(2)->child(0)->vertex_index(1),
7365 quad->line(3)->child(0)->vertex_index(1),
7366 next_unused_vertex};
7367
7368 new_lines[0]->set_bounding_object_indices(
7370 new_lines[1]->set_bounding_object_indices(
7372 new_lines[2]->set_bounding_object_indices(
7374 new_lines[3]->set_bounding_object_indices(
7376
7377 for (const auto &new_line : new_lines)
7378 {
7379 new_line->set_used_flag();
7380 new_line->clear_user_flag();
7381 new_line->clear_user_data();
7382 new_line->clear_children();
7383 new_line->set_boundary_id_internal(quad->boundary_id());
7384 new_line->set_manifold_id(quad->manifold_id());
7385 }
7386
7387 // now for the quads. again, first collect some
7388 // data about the indices of the lines, with the
7389 // following numbering:
7390 //
7391 // .-6-.-7-.
7392 // 1 9 3
7393 // .-10.11-.
7394 // 0 8 2
7395 // .-4-.-5-.
7396
7397 // child 0 and 1 of a line are switched if the
7398 // line orientation is false. set up a miniature
7399 // table, indicating which child to take for line
7400 // orientations false and true. first index: child
7401 // index in standard orientation, second index:
7402 // line orientation
7403 const unsigned int index[2][2] = {
7404 {1, 0}, // child 0, line_orientation=false and true
7405 {0, 1}}; // child 1, line_orientation=false and true
7406
7407 const int line_indices[12] = {
7408 quad->line(0)
7409 ->child(index[0][quad->line_orientation(0)])
7410 ->index(),
7411 quad->line(0)
7412 ->child(index[1][quad->line_orientation(0)])
7413 ->index(),
7414 quad->line(1)
7415 ->child(index[0][quad->line_orientation(1)])
7416 ->index(),
7417 quad->line(1)
7418 ->child(index[1][quad->line_orientation(1)])
7419 ->index(),
7420 quad->line(2)
7421 ->child(index[0][quad->line_orientation(2)])
7422 ->index(),
7423 quad->line(2)
7424 ->child(index[1][quad->line_orientation(2)])
7425 ->index(),
7426 quad->line(3)
7427 ->child(index[0][quad->line_orientation(3)])
7428 ->index(),
7429 quad->line(3)
7430 ->child(index[1][quad->line_orientation(3)])
7431 ->index(),
7432 new_lines[0]->index(),
7433 new_lines[1]->index(),
7434 new_lines[2]->index(),
7435 new_lines[3]->index()};
7436
7437 // find some space (consecutive)
7438 // for the first two newly to be
7439 // created quads.
7441 new_quads[4];
7442
7443 next_unused_quad =
7444 triangulation.faces->quads
7445 .template next_free_pair_object<2>(triangulation);
7446
7447 new_quads[0] = next_unused_quad;
7448 AssertIsNotUsed(new_quads[0]);
7449
7450 ++next_unused_quad;
7451 new_quads[1] = next_unused_quad;
7452 AssertIsNotUsed(new_quads[1]);
7453
7454 next_unused_quad =
7455 triangulation.faces->quads
7456 .template next_free_pair_object<2>(triangulation);
7457 new_quads[2] = next_unused_quad;
7458 AssertIsNotUsed(new_quads[2]);
7459
7460 ++next_unused_quad;
7461 new_quads[3] = next_unused_quad;
7462 AssertIsNotUsed(new_quads[3]);
7463
7464 // note these quads as children to the present one
7465 quad->set_children(0, new_quads[0]->index());
7466 quad->set_children(2, new_quads[2]->index());
7467 quad->set_refinement_case(RefinementCase<2>::cut_xy);
7468
7469 new_quads[0]->set_bounding_object_indices(
7470 {line_indices[0],
7471 line_indices[8],
7472 line_indices[4],
7473 line_indices[10]});
7474 new_quads[1]->set_bounding_object_indices(
7475 {line_indices[8],
7476 line_indices[2],
7477 line_indices[5],
7478 line_indices[11]});
7479 new_quads[2]->set_bounding_object_indices(
7480 {line_indices[1],
7481 line_indices[9],
7482 line_indices[10],
7483 line_indices[6]});
7484 new_quads[3]->set_bounding_object_indices(
7485 {line_indices[9],
7486 line_indices[3],
7487 line_indices[11],
7488 line_indices[7]});
7489 for (const auto &new_quad : new_quads)
7490 {
7491 new_quad->set_used_flag();
7492 new_quad->clear_user_flag();
7493 new_quad->clear_user_data();
7494 new_quad->clear_children();
7495 new_quad->set_boundary_id_internal(quad->boundary_id());
7496 new_quad->set_manifold_id(quad->manifold_id());
7497 // set all line orientations to true, change
7498 // this after the loop, as we have to consider
7499 // different lines for each child
7500 for (unsigned int j = 0;
7501 j < GeometryInfo<dim>::lines_per_face;
7502 ++j)
7503 new_quad->set_line_orientation(j, true);
7504 }
7505 // now set the line orientation of children of
7506 // outer lines correctly, the lines in the
7507 // interior of the refined quad are automatically
7508 // oriented conforming to the standard
7509 new_quads[0]->set_line_orientation(
7510 0, quad->line_orientation(0));
7511 new_quads[0]->set_line_orientation(
7512 2, quad->line_orientation(2));
7513 new_quads[1]->set_line_orientation(
7514 1, quad->line_orientation(1));
7515 new_quads[1]->set_line_orientation(
7516 2, quad->line_orientation(2));
7517 new_quads[2]->set_line_orientation(
7518 0, quad->line_orientation(0));
7519 new_quads[2]->set_line_orientation(
7520 3, quad->line_orientation(3));
7521 new_quads[3]->set_line_orientation(
7522 1, quad->line_orientation(1));
7523 new_quads[3]->set_line_orientation(
7524 3, quad->line_orientation(3));
7525
7526 // finally clear flag indicating the need for
7527 // refinement
7528 quad->clear_user_flag();
7529 } // if (isotropic refinement)
7530 } // for all quads
7531 } // looped two times over all quads, all quads refined now
7532
7533 //---------------------------------
7534 // Now, finally, set up the new
7535 // cells
7536 //---------------------------------
7537
7539 cells_with_distorted_children;
7540
7541 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
7542 ++level)
7543 {
7544 // only active objects can be refined further; remember
7545 // that we won't operate on the finest level, so
7546 // triangulation.begin_*(level+1) is allowed
7548 hex = triangulation.begin_active_hex(level),
7549 endh = triangulation.begin_active_hex(level + 1);
7551 next_unused_hex = triangulation.begin_raw_hex(level + 1);
7552
7553 for (; hex != endh; ++hex)
7554 if (hex->refine_flag_set())
7555 {
7556 // this hex needs to be refined
7557
7558 // clear flag indicating the need for refinement. do
7559 // it here already, since we can't do it anymore
7560 // once the cell has children
7561 const RefinementCase<dim> ref_case = hex->refine_flag_set();
7562 hex->clear_refine_flag();
7563 hex->set_refinement_case(ref_case);
7564
7565 // depending on the refine case we might have to
7566 // create additional vertices, lines and quads
7567 // interior of the hex before the actual children
7568 // can be set up.
7569
7570 // in a first step: reserve the needed space for
7571 // lines, quads and hexes and initialize them
7572 // correctly
7573
7574 unsigned int n_new_lines = 0;
7575 unsigned int n_new_quads = 0;
7576 unsigned int n_new_hexes = 0;
7577 switch (ref_case)
7578 {
7582 n_new_lines = 0;
7583 n_new_quads = 1;
7584 n_new_hexes = 2;
7585 break;
7589 n_new_lines = 1;
7590 n_new_quads = 4;
7591 n_new_hexes = 4;
7592 break;
7594 n_new_lines = 6;
7595 n_new_quads = 12;
7596 n_new_hexes = 8;
7597 break;
7598 default:
7599 Assert(false, ExcInternalError());
7600 break;
7601 }
7602
7603 // find some space for the newly to be created
7604 // interior lines and initialize them.
7605 std::vector<
7607 new_lines(n_new_lines);
7608 for (unsigned int i = 0; i < n_new_lines; ++i)
7609 {
7610 new_lines[i] =
7611 triangulation.faces->lines
7612 .template next_free_single_object<1>(triangulation);
7613
7614 AssertIsNotUsed(new_lines[i]);
7615 new_lines[i]->set_used_flag();
7616 new_lines[i]->clear_user_flag();
7617 new_lines[i]->clear_user_data();
7618 new_lines[i]->clear_children();
7619 // interior line
7620 new_lines[i]->set_boundary_id_internal(
7622 // they inherit geometry description of the hex they
7623 // belong to
7624 new_lines[i]->set_manifold_id(hex->manifold_id());
7625 }
7626
7627 // find some space for the newly to be created
7628 // interior quads and initialize them.
7629 std::vector<
7631 new_quads(n_new_quads);
7632 for (unsigned int i = 0; i < n_new_quads; ++i)
7633 {
7634 new_quads[i] =
7635 triangulation.faces->quads
7636 .template next_free_single_object<2>(triangulation);
7637
7638 AssertIsNotUsed(new_quads[i]);
7639 new_quads[i]->set_used_flag();
7640 new_quads[i]->clear_user_flag();
7641 new_quads[i]->clear_user_data();
7642 new_quads[i]->clear_children();
7643 // interior quad
7644 new_quads[i]->set_boundary_id_internal(
7646 // they inherit geometry description of the hex they
7647 // belong to
7648 new_quads[i]->set_manifold_id(hex->manifold_id());
7649 // set all line orientation flags to true by
7650 // default, change this afterwards, if necessary
7651 for (unsigned int j = 0;
7652 j < GeometryInfo<dim>::lines_per_face;
7653 ++j)
7654 new_quads[i]->set_line_orientation(j, true);
7655 }
7656
7657 types::subdomain_id subdomainid = hex->subdomain_id();
7658
7659 // find some space for the newly to be created hexes
7660 // and initialize them.
7661 std::vector<
7663 new_hexes(n_new_hexes);
7664 for (unsigned int i = 0; i < n_new_hexes; ++i)
7665 {
7666 if (i % 2 == 0)
7667 next_unused_hex =
7668 triangulation.levels[level + 1]->cells.next_free_hex(
7669 triangulation, level + 1);
7670 else
7671 ++next_unused_hex;
7672
7673 new_hexes[i] = next_unused_hex;
7674
7675 AssertIsNotUsed(new_hexes[i]);
7676 new_hexes[i]->set_used_flag();
7677 new_hexes[i]->clear_user_flag();
7678 new_hexes[i]->clear_user_data();
7679 new_hexes[i]->clear_children();
7680 // inherit material
7681 // properties
7682 new_hexes[i]->set_material_id(hex->material_id());
7683 new_hexes[i]->set_manifold_id(hex->manifold_id());
7684 new_hexes[i]->set_subdomain_id(subdomainid);
7685
7686 if (i % 2)
7687 new_hexes[i]->set_parent(hex->index());
7688 // set the face_orientation flag to true for all
7689 // faces initially, as this is the default value
7690 // which is true for all faces interior to the
7691 // hex. later on go the other way round and
7692 // reset faces that are at the boundary of the
7693 // mother cube
7694 //
7695 // the same is true for the face_flip and
7696 // face_rotation flags. however, the latter two
7697 // are set to false by default as this is the
7698 // standard value
7699 for (const unsigned int f :
7701 new_hexes[i]->set_combined_face_orientation(
7702 f,
7704 }
7705 // note these hexes as children to the present cell
7706 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
7707 hex->set_children(2 * i, new_hexes[2 * i]->index());
7708
7709 // we have to take into account whether the
7710 // different faces are oriented correctly or in the
7711 // opposite direction, so store that up front
7712
7713 // face_orientation
7714 const bool f_or[6] = {hex->face_orientation(0),
7715 hex->face_orientation(1),
7716 hex->face_orientation(2),
7717 hex->face_orientation(3),
7718 hex->face_orientation(4),
7719 hex->face_orientation(5)};
7720
7721 // face_flip
7722 const bool f_fl[6] = {hex->face_flip(0),
7723 hex->face_flip(1),
7724 hex->face_flip(2),
7725 hex->face_flip(3),
7726 hex->face_flip(4),
7727 hex->face_flip(5)};
7728
7729 // face_rotation
7730 const bool f_ro[6] = {hex->face_rotation(0),
7731 hex->face_rotation(1),
7732 hex->face_rotation(2),
7733 hex->face_rotation(3),
7734 hex->face_rotation(4),
7735 hex->face_rotation(5)};
7736
7737 // combined orientation
7738 const unsigned char f_co[6] = {
7739 hex->combined_face_orientation(0),
7740 hex->combined_face_orientation(1),
7741 hex->combined_face_orientation(2),
7742 hex->combined_face_orientation(3),
7743 hex->combined_face_orientation(4),
7744 hex->combined_face_orientation(5)};
7745
7746 // little helper table, indicating, whether the
7747 // child with index 0 or with index 1 can be found
7748 // at the standard origin of an anisotropically
7749 // refined quads in real orientation index 1:
7750 // (RefineCase - 1) index 2: face_flip
7751
7752 // index 3: face rotation
7753 // note: face orientation has no influence
7754 const unsigned int child_at_origin[2][2][2] = {
7755 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
7756 // face_rotation=false and true
7757 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
7758 // face_rotation=false and true
7759 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
7760 // face_rotation=false and true
7761 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
7762 // face_rotation=false and true
7763
7764 //-------------------------------------
7765 //
7766 // in the following we will do the same thing for
7767 // each refinement case: create a new vertex (if
7768 // needed), create new interior lines (if needed),
7769 // create new interior quads and afterwards build
7770 // the children hexes out of these and the existing
7771 // subfaces of the outer quads (which have been
7772 // created above). However, even if the steps are
7773 // quite similar, the actual work strongly depends
7774 // on the actual refinement case. therefore, we use
7775 // separate blocks of code for each of these cases,
7776 // which hopefully increases the readability to some
7777 // extend.
7778
7779 switch (ref_case)
7780 {
7782 {
7783 //----------------------------
7784 //
7785 // RefinementCase<dim>::cut_x
7786 //
7787 // the refined cube will look
7788 // like this:
7789 //
7790 // *----*----*
7791 // / / /|
7792 // / / / |
7793 // / / / |
7794 // *----*----* |
7795 // | | | |
7796 // | | | *
7797 // | | | /
7798 // | | | /
7799 // | | |/
7800 // *----*----*
7801 //
7802 // again, first collect some data about the
7803 // indices of the lines, with the following
7804 // numbering:
7805
7806 // face 2: front plane
7807 // (note: x,y exchanged)
7808 // *---*---*
7809 // | | |
7810 // | 0 |
7811 // | | |
7812 // *---*---*
7813 // m0
7814 // face 3: back plane
7815 // (note: x,y exchanged)
7816 // m1
7817 // *---*---*
7818 // | | |
7819 // | 1 |
7820 // | | |
7821 // *---*---*
7822 // face 4: bottom plane
7823 // *---*---*
7824 // / / /
7825 // / 2 /
7826 // / / /
7827 // *---*---*
7828 // m0
7829 // face 5: top plane
7830 // m1
7831 // *---*---*
7832 // / / /
7833 // / 3 /
7834 // / / /
7835 // *---*---*
7836
7837 // set up a list of line iterators first. from
7838 // this, construct lists of line_indices and
7839 // line orientations later on
7840 const typename Triangulation<dim, spacedim>::
7841 raw_line_iterator lines[4] = {
7842 hex->face(2)->child(0)->line(
7843 (hex->face(2)->refinement_case() ==
7845 1 :
7846 3), // 0
7847 hex->face(3)->child(0)->line(
7848 (hex->face(3)->refinement_case() ==
7850 1 :
7851 3), // 1
7852 hex->face(4)->child(0)->line(
7853 (hex->face(4)->refinement_case() ==
7855 1 :
7856 3), // 2
7857 hex->face(5)->child(0)->line(
7858 (hex->face(5)->refinement_case() ==
7860 1 :
7861 3) // 3
7862 };
7863
7864 unsigned int line_indices[4];
7865 for (unsigned int i = 0; i < 4; ++i)
7866 line_indices[i] = lines[i]->index();
7867
7868 // the orientation of lines for the inner quads
7869 // is quite tricky. as these lines are newly
7870 // created ones and thus have no parents, they
7871 // cannot inherit this property. set up an array
7872 // and fill it with the respective values
7873 bool line_orientation[4];
7874
7875 // the middle vertex marked as m0 above is the
7876 // start vertex for lines 0 and 2 in standard
7877 // orientation, whereas m1 is the end vertex of
7878 // lines 1 and 3 in standard orientation
7879 const unsigned int middle_vertices[2] = {
7880 hex->line(2)->child(0)->vertex_index(1),
7881 hex->line(7)->child(0)->vertex_index(1)};
7882
7883 for (unsigned int i = 0; i < 4; ++i)
7884 if (lines[i]->vertex_index(i % 2) ==
7885 middle_vertices[i % 2])
7886 line_orientation[i] = true;
7887 else
7888 {
7889 // it must be the other
7890 // way round then
7891 Assert(lines[i]->vertex_index((i + 1) % 2) ==
7892 middle_vertices[i % 2],
7894 line_orientation[i] = false;
7895 }
7896
7897 // set up the new quad, line numbering is as
7898 // indicated above
7899 new_quads[0]->set_bounding_object_indices(
7900 {line_indices[0],
7901 line_indices[1],
7902 line_indices[2],
7903 line_indices[3]});
7904
7905 new_quads[0]->set_line_orientation(
7906 0, line_orientation[0]);
7907 new_quads[0]->set_line_orientation(
7908 1, line_orientation[1]);
7909 new_quads[0]->set_line_orientation(
7910 2, line_orientation[2]);
7911 new_quads[0]->set_line_orientation(
7912 3, line_orientation[3]);
7913
7914 // the quads are numbered as follows:
7915 //
7916 // planes in the interior of the old hex:
7917 //
7918 // *
7919 // /|
7920 // / | x
7921 // / | *-------* *---------*
7922 // * | | | / /
7923 // | 0 | | | / /
7924 // | * | | / /
7925 // | / *-------*y *---------*x
7926 // | /
7927 // |/
7928 // *
7929 //
7930 // children of the faces of the old hex
7931 //
7932 // *---*---* *---*---*
7933 // /| | | / / /|
7934 // / | | | / 9 / 10/ |
7935 // / | 5 | 6 | / / / |
7936 // * | | | *---*---* |
7937 // | 1 *---*---* | | | 2 *
7938 // | / / / | | | /
7939 // | / 7 / 8 / | 3 | 4 | /
7940 // |/ / / | | |/
7941 // *---*---* *---*---*
7942 //
7943 // note that we have to take care of the
7944 // orientation of faces.
7945 const int quad_indices[11] = {
7946 new_quads[0]->index(), // 0
7947
7948 hex->face(0)->index(), // 1
7949
7950 hex->face(1)->index(), // 2
7951
7952 hex->face(2)->child_index(
7953 child_at_origin[hex->face(2)->refinement_case() -
7954 1][f_fl[2]][f_ro[2]]), // 3
7955 hex->face(2)->child_index(
7956 1 -
7957 child_at_origin[hex->face(2)->refinement_case() -
7958 1][f_fl[2]][f_ro[2]]),
7959
7960 hex->face(3)->child_index(
7961 child_at_origin[hex->face(3)->refinement_case() -
7962 1][f_fl[3]][f_ro[3]]), // 5
7963 hex->face(3)->child_index(
7964 1 -
7965 child_at_origin[hex->face(3)->refinement_case() -
7966 1][f_fl[3]][f_ro[3]]),
7967
7968 hex->face(4)->child_index(
7969 child_at_origin[hex->face(4)->refinement_case() -
7970 1][f_fl[4]][f_ro[4]]), // 7
7971 hex->face(4)->child_index(
7972 1 -
7973 child_at_origin[hex->face(4)->refinement_case() -
7974 1][f_fl[4]][f_ro[4]]),
7975
7976 hex->face(5)->child_index(
7977 child_at_origin[hex->face(5)->refinement_case() -
7978 1][f_fl[5]][f_ro[5]]), // 9
7979 hex->face(5)->child_index(
7980 1 -
7981 child_at_origin[hex->face(5)->refinement_case() -
7982 1][f_fl[5]][f_ro[5]])
7983
7984 };
7985
7986 new_hexes[0]->set_bounding_object_indices(
7987 {quad_indices[1],
7988 quad_indices[0],
7989 quad_indices[3],
7990 quad_indices[5],
7991 quad_indices[7],
7992 quad_indices[9]});
7993 new_hexes[1]->set_bounding_object_indices(
7994 {quad_indices[0],
7995 quad_indices[2],
7996 quad_indices[4],
7997 quad_indices[6],
7998 quad_indices[8],
7999 quad_indices[10]});
8000 break;
8001 }
8002
8004 {
8005 //----------------------------
8006 //
8007 // RefinementCase<dim>::cut_y
8008 //
8009 // the refined cube will look like this:
8010 //
8011 // *---------*
8012 // / /|
8013 // *---------* |
8014 // / /| |
8015 // *---------* | |
8016 // | | | |
8017 // | | | *
8018 // | | |/
8019 // | | *
8020 // | |/
8021 // *---------*
8022 //
8023 // again, first collect some data about the
8024 // indices of the lines, with the following
8025 // numbering:
8026
8027 // face 0: left plane
8028 // *
8029 // /|
8030 // * |
8031 // /| |
8032 // * | |
8033 // | 0 |
8034 // | | *
8035 // | |/
8036 // | *m0
8037 // |/
8038 // *
8039 // face 1: right plane
8040 // *
8041 // /|
8042 // m1* |
8043 // /| |
8044 // * | |
8045 // | 1 |
8046 // | | *
8047 // | |/
8048 // | *
8049 // |/
8050 // *
8051 // face 4: bottom plane
8052 // *-------*
8053 // / /
8054 // m0*---2---*
8055 // / /
8056 // *-------*
8057 // face 5: top plane
8058 // *-------*
8059 // / /
8060 // *---3---*m1
8061 // / /
8062 // *-------*
8063
8064 // set up a list of line iterators first. from
8065 // this, construct lists of line_indices and
8066 // line orientations later on
8067 const typename Triangulation<dim, spacedim>::
8068 raw_line_iterator lines[4] = {
8069 hex->face(0)->child(0)->line(
8070 (hex->face(0)->refinement_case() ==
8072 1 :
8073 3), // 0
8074 hex->face(1)->child(0)->line(
8075 (hex->face(1)->refinement_case() ==
8077 1 :
8078 3), // 1
8079 hex->face(4)->child(0)->line(
8080 (hex->face(4)->refinement_case() ==
8082 1 :
8083 3), // 2
8084 hex->face(5)->child(0)->line(
8085 (hex->face(5)->refinement_case() ==
8087 1 :
8088 3) // 3
8089 };
8090
8091 unsigned int line_indices[4];
8092 for (unsigned int i = 0; i < 4; ++i)
8093 line_indices[i] = lines[i]->index();
8094
8095 // the orientation of lines for the inner quads
8096 // is quite tricky. as these lines are newly
8097 // created ones and thus have no parents, they
8098 // cannot inherit this property. set up an array
8099 // and fill it with the respective values
8100 bool line_orientation[4];
8101
8102 // the middle vertex marked as m0 above is the
8103 // start vertex for lines 0 and 2 in standard
8104 // orientation, whereas m1 is the end vertex of
8105 // lines 1 and 3 in standard orientation
8106 const unsigned int middle_vertices[2] = {
8107 hex->line(0)->child(0)->vertex_index(1),
8108 hex->line(5)->child(0)->vertex_index(1)};
8109
8110 for (unsigned int i = 0; i < 4; ++i)
8111 if (lines[i]->vertex_index(i % 2) ==
8112 middle_vertices[i % 2])
8113 line_orientation[i] = true;
8114 else
8115 {
8116 // it must be the other way round then
8117 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8118 middle_vertices[i % 2],
8120 line_orientation[i] = false;
8121 }
8122
8123 // set up the new quad, line numbering is as
8124 // indicated above
8125 new_quads[0]->set_bounding_object_indices(
8126 {line_indices[2],
8127 line_indices[3],
8128 line_indices[0],
8129 line_indices[1]});
8130
8131 new_quads[0]->set_line_orientation(
8132 0, line_orientation[2]);
8133 new_quads[0]->set_line_orientation(
8134 1, line_orientation[3]);
8135 new_quads[0]->set_line_orientation(
8136 2, line_orientation[0]);
8137 new_quads[0]->set_line_orientation(
8138 3, line_orientation[1]);
8139
8140 // the quads are numbered as follows:
8141 //
8142 // planes in the interior of the old hex:
8143 //
8144 // *
8145 // /|
8146 // / | x
8147 // / | *-------* *---------*
8148 // * | | | / /
8149 // | | | 0 | / /
8150 // | * | | / /
8151 // | / *-------*y *---------*x
8152 // | /
8153 // |/
8154 // *
8155 //
8156 // children of the faces of the old hex
8157 //
8158 // *-------* *-------*
8159 // /| | / 10 /|
8160 // * | | *-------* |
8161 // /| | 6 | / 9 /| |
8162 // * |2| | *-------* |4|
8163 // | | *-------* | | | *
8164 // |1|/ 8 / | |3|/
8165 // | *-------* | 5 | *
8166 // |/ 7 / | |/
8167 // *-------* *-------*
8168 //
8169 // note that we have to take care of the
8170 // orientation of faces.
8171 const int quad_indices[11] = {
8172 new_quads[0]->index(), // 0
8173
8174 hex->face(0)->child_index(
8175 child_at_origin[hex->face(0)->refinement_case() -
8176 1][f_fl[0]][f_ro[0]]), // 1
8177 hex->face(0)->child_index(
8178 1 -
8179 child_at_origin[hex->face(0)->refinement_case() -
8180 1][f_fl[0]][f_ro[0]]),
8181
8182 hex->face(1)->child_index(
8183 child_at_origin[hex->face(1)->refinement_case() -
8184 1][f_fl[1]][f_ro[1]]), // 3
8185 hex->face(1)->child_index(
8186 1 -
8187 child_at_origin[hex->face(1)->refinement_case() -
8188 1][f_fl[1]][f_ro[1]]),
8189
8190 hex->face(2)->index(), // 5
8191
8192 hex->face(3)->index(), // 6
8193
8194 hex->face(4)->child_index(
8195 child_at_origin[hex->face(4)->refinement_case() -
8196 1][f_fl[4]][f_ro[4]]), // 7
8197 hex->face(4)->child_index(
8198 1 -
8199 child_at_origin[hex->face(4)->refinement_case() -
8200 1][f_fl[4]][f_ro[4]]),
8201
8202 hex->face(5)->child_index(
8203 child_at_origin[hex->face(5)->refinement_case() -
8204 1][f_fl[5]][f_ro[5]]), // 9
8205 hex->face(5)->child_index(
8206 1 -
8207 child_at_origin[hex->face(5)->refinement_case() -
8208 1][f_fl[5]][f_ro[5]])
8209
8210 };
8211
8212 new_hexes[0]->set_bounding_object_indices(
8213 {quad_indices[1],
8214 quad_indices[3],
8215 quad_indices[5],
8216 quad_indices[0],
8217 quad_indices[7],
8218 quad_indices[9]});
8219 new_hexes[1]->set_bounding_object_indices(
8220 {quad_indices[2],
8221 quad_indices[4],
8222 quad_indices[0],
8223 quad_indices[6],
8224 quad_indices[8],
8225 quad_indices[10]});
8226 break;
8227 }
8228
8230 {
8231 //----------------------------
8232 //
8233 // RefinementCase<dim>::cut_z
8234 //
8235 // the refined cube will look like this:
8236 //
8237 // *---------*
8238 // / /|
8239 // / / |
8240 // / / *
8241 // *---------* /|
8242 // | | / |
8243 // | |/ *
8244 // *---------* /
8245 // | | /
8246 // | |/
8247 // *---------*
8248 //
8249 // again, first collect some data about the
8250 // indices of the lines, with the following
8251 // numbering:
8252
8253 // face 0: left plane
8254 // *
8255 // /|
8256 // / |
8257 // / *
8258 // * /|
8259 // | 0 |
8260 // |/ *
8261 // m0* /
8262 // | /
8263 // |/
8264 // *
8265 // face 1: right plane
8266 // *
8267 // /|
8268 // / |
8269 // / *m1
8270 // * /|
8271 // | 1 |
8272 // |/ *
8273 // * /
8274 // | /
8275 // |/
8276 // *
8277 // face 2: front plane
8278 // (note: x,y exchanged)
8279 // *-------*
8280 // | |
8281 // m0*---2---*
8282 // | |
8283 // *-------*
8284 // face 3: back plane
8285 // (note: x,y exchanged)
8286 // *-------*
8287 // | |
8288 // *---3---*m1
8289 // | |
8290 // *-------*
8291
8292 // set up a list of line iterators first. from
8293 // this, construct lists of line_indices and
8294 // line orientations later on
8295 const typename Triangulation<dim, spacedim>::
8296 raw_line_iterator lines[4] = {
8297 hex->face(0)->child(0)->line(
8298 (hex->face(0)->refinement_case() ==
8300 1 :
8301 3), // 0
8302 hex->face(1)->child(0)->line(
8303 (hex->face(1)->refinement_case() ==
8305 1 :
8306 3), // 1
8307 hex->face(2)->child(0)->line(
8308 (hex->face(2)->refinement_case() ==
8310 1 :
8311 3), // 2
8312 hex->face(3)->child(0)->line(
8313 (hex->face(3)->refinement_case() ==
8315 1 :
8316 3) // 3
8317 };
8318
8319 unsigned int line_indices[4];
8320 for (unsigned int i = 0; i < 4; ++i)
8321 line_indices[i] = lines[i]->index();
8322
8323 // the orientation of lines for the inner quads
8324 // is quite tricky. as these lines are newly
8325 // created ones and thus have no parents, they
8326 // cannot inherit this property. set up an array
8327 // and fill it with the respective values
8328 bool line_orientation[4];
8329
8330 // the middle vertex marked as m0 above is the
8331 // start vertex for lines 0 and 2 in standard
8332 // orientation, whereas m1 is the end vertex of
8333 // lines 1 and 3 in standard orientation
8334 const unsigned int middle_vertices[2] = {
8335 middle_vertex_index<dim, spacedim>(hex->line(8)),
8336 middle_vertex_index<dim, spacedim>(hex->line(11))};
8337
8338 for (unsigned int i = 0; i < 4; ++i)
8339 if (lines[i]->vertex_index(i % 2) ==
8340 middle_vertices[i % 2])
8341 line_orientation[i] = true;
8342 else
8343 {
8344 // it must be the other way round then
8345 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8346 middle_vertices[i % 2],
8348 line_orientation[i] = false;
8349 }
8350
8351 // set up the new quad, line numbering is as
8352 // indicated above
8353 new_quads[0]->set_bounding_object_indices(
8354 {line_indices[0],
8355 line_indices[1],
8356 line_indices[2],
8357 line_indices[3]});
8358
8359 new_quads[0]->set_line_orientation(
8360 0, line_orientation[0]);
8361 new_quads[0]->set_line_orientation(
8362 1, line_orientation[1]);
8363 new_quads[0]->set_line_orientation(
8364 2, line_orientation[2]);
8365 new_quads[0]->set_line_orientation(
8366 3, line_orientation[3]);
8367
8368 // the quads are numbered as follows:
8369 //
8370 // planes in the interior of the old hex:
8371 //
8372 // *
8373 // /|
8374 // / | x
8375 // / | *-------* *---------*
8376 // * | | | / /
8377 // | | | | / 0 /
8378 // | * | | / /
8379 // | / *-------*y *---------*x
8380 // | /
8381 // |/
8382 // *
8383 //
8384 // children of the faces of the old hex
8385 //
8386 // *---*---* *-------*
8387 // /| 8 | / /|
8388 // / | | / 10 / |
8389 // / *-------* / / *
8390 // * 2/| | *-------* 4/|
8391 // | / | 7 | | 6 | / |
8392 // |/1 *-------* | |/3 *
8393 // * / / *-------* /
8394 // | / 9 / | | /
8395 // |/ / | 5 |/
8396 // *-------* *---*---*
8397 //
8398 // note that we have to take care of the
8399 // orientation of faces.
8400 const int quad_indices[11] = {
8401 new_quads[0]->index(), // 0
8402
8403 hex->face(0)->child_index(
8404 child_at_origin[hex->face(0)->refinement_case() -
8405 1][f_fl[0]][f_ro[0]]), // 1
8406 hex->face(0)->child_index(
8407 1 -
8408 child_at_origin[hex->face(0)->refinement_case() -
8409 1][f_fl[0]][f_ro[0]]),
8410
8411 hex->face(1)->child_index(
8412 child_at_origin[hex->face(1)->refinement_case() -
8413 1][f_fl[1]][f_ro[1]]), // 3
8414 hex->face(1)->child_index(
8415 1 -
8416 child_at_origin[hex->face(1)->refinement_case() -
8417 1][f_fl[1]][f_ro[1]]),
8418
8419 hex->face(2)->child_index(
8420 child_at_origin[hex->face(2)->refinement_case() -
8421 1][f_fl[2]][f_ro[2]]), // 5
8422 hex->face(2)->child_index(
8423 1 -
8424 child_at_origin[hex->face(2)->refinement_case() -
8425 1][f_fl[2]][f_ro[2]]),
8426
8427 hex->face(3)->child_index(
8428 child_at_origin[hex->face(3)->refinement_case() -
8429 1][f_fl[3]][f_ro[3]]), // 7
8430 hex->face(3)->child_index(
8431 1 -
8432 child_at_origin[hex->face(3)->refinement_case() -
8433 1][f_fl[3]][f_ro[3]]),
8434
8435 hex->face(4)->index(), // 9
8436
8437 hex->face(5)->index() // 10
8438 };
8439
8440 new_hexes[0]->set_bounding_object_indices(
8441 {quad_indices[1],
8442 quad_indices[3],
8443 quad_indices[5],
8444 quad_indices[7],
8445 quad_indices[9],
8446 quad_indices[0]});
8447 new_hexes[1]->set_bounding_object_indices(
8448 {quad_indices[2],
8449 quad_indices[4],
8450 quad_indices[6],
8451 quad_indices[8],
8452 quad_indices[0],
8453 quad_indices[10]});
8454 break;
8455 }
8456
8458 {
8459 //----------------------------
8460 //
8461 // RefinementCase<dim>::cut_xy
8462 //
8463 // the refined cube will look like this:
8464 //
8465 // *----*----*
8466 // / / /|
8467 // *----*----* |
8468 // / / /| |
8469 // *----*----* | |
8470 // | | | | |
8471 // | | | | *
8472 // | | | |/
8473 // | | | *
8474 // | | |/
8475 // *----*----*
8476 //
8477
8478 // first, create the new internal line
8479 new_lines[0]->set_bounding_object_indices(
8480 {middle_vertex_index<dim, spacedim>(hex->face(4)),
8481 middle_vertex_index<dim, spacedim>(hex->face(5))});
8482
8483 // again, first collect some data about the
8484 // indices of the lines, with the following
8485 // numbering:
8486
8487 // face 0: left plane
8488 // *
8489 // /|
8490 // * |
8491 // /| |
8492 // * | |
8493 // | 0 |
8494 // | | *
8495 // | |/
8496 // | *
8497 // |/
8498 // *
8499 // face 1: right plane
8500 // *
8501 // /|
8502 // * |
8503 // /| |
8504 // * | |
8505 // | 1 |
8506 // | | *
8507 // | |/
8508 // | *
8509 // |/
8510 // *
8511 // face 2: front plane
8512 // (note: x,y exchanged)
8513 // *---*---*
8514 // | | |
8515 // | 2 |
8516 // | | |
8517 // *-------*
8518 // face 3: back plane
8519 // (note: x,y exchanged)
8520 // *---*---*
8521 // | | |
8522 // | 3 |
8523 // | | |
8524 // *---*---*
8525 // face 4: bottom plane
8526 // *---*---*
8527 // / 5 /
8528 // *-6-*-7-*
8529 // / 4 /
8530 // *---*---*
8531 // face 5: top plane
8532 // *---*---*
8533 // / 9 /
8534 // *10-*-11*
8535 // / 8 /
8536 // *---*---*
8537 // middle planes
8538 // *-------* *---*---*
8539 // / / | | |
8540 // / / | 12 |
8541 // / / | | |
8542 // *-------* *---*---*
8543
8544 // set up a list of line iterators first. from
8545 // this, construct lists of line_indices and
8546 // line orientations later on
8547 const typename Triangulation<
8548 dim,
8549 spacedim>::raw_line_iterator lines[13] = {
8550 hex->face(0)->child(0)->line(
8551 (hex->face(0)->refinement_case() ==
8553 1 :
8554 3), // 0
8555 hex->face(1)->child(0)->line(
8556 (hex->face(1)->refinement_case() ==
8558 1 :
8559 3), // 1
8560 hex->face(2)->child(0)->line(
8561 (hex->face(2)->refinement_case() ==
8563 1 :
8564 3), // 2
8565 hex->face(3)->child(0)->line(
8566 (hex->face(3)->refinement_case() ==
8568 1 :
8569 3), // 3
8570
8571 hex->face(4)
8572 ->isotropic_child(
8574 0, f_or[4], f_fl[4], f_ro[4]))
8575 ->line(
8577 1, f_or[4], f_fl[4], f_ro[4])), // 4
8578 hex->face(4)
8579 ->isotropic_child(
8581 3, f_or[4], f_fl[4], f_ro[4]))
8582 ->line(
8584 0, f_or[4], f_fl[4], f_ro[4])), // 5
8585 hex->face(4)
8586 ->isotropic_child(
8588 0, f_or[4], f_fl[4], f_ro[4]))
8589 ->line(
8591 3, f_or[4], f_fl[4], f_ro[4])), // 6
8592 hex->face(4)
8593 ->isotropic_child(
8595 3, f_or[4], f_fl[4], f_ro[4]))
8596 ->line(
8598 2, f_or[4], f_fl[4], f_ro[4])), // 7
8599
8600 hex->face(5)
8601 ->isotropic_child(
8603 0, f_or[5], f_fl[5], f_ro[5]))
8604 ->line(
8606 1, f_or[5], f_fl[5], f_ro[5])), // 8
8607 hex->face(5)
8608 ->isotropic_child(
8610 3, f_or[5], f_fl[5], f_ro[5]))
8611 ->line(
8613 0, f_or[5], f_fl[5], f_ro[5])), // 9
8614 hex->face(5)
8615 ->isotropic_child(
8617 0, f_or[5], f_fl[5], f_ro[5]))
8618 ->line(
8620 3, f_or[5], f_fl[5], f_ro[5])), // 10
8621 hex->face(5)
8622 ->isotropic_child(
8624 3, f_or[5], f_fl[5], f_ro[5]))
8625 ->line(
8627 2, f_or[5], f_fl[5], f_ro[5])), // 11
8628
8629 new_lines[0] // 12
8630 };
8631
8632 unsigned int line_indices[13];
8633 for (unsigned int i = 0; i < 13; ++i)
8634 line_indices[i] = lines[i]->index();
8635
8636 // the orientation of lines for the inner quads
8637 // is quite tricky. as these lines are newly
8638 // created ones and thus have no parents, they
8639 // cannot inherit this property. set up an array
8640 // and fill it with the respective values
8641 bool line_orientation[13];
8642
8643 // the middle vertices of the lines of our
8644 // bottom face
8645 const unsigned int middle_vertices[4] = {
8646 hex->line(0)->child(0)->vertex_index(1),
8647 hex->line(1)->child(0)->vertex_index(1),
8648 hex->line(2)->child(0)->vertex_index(1),
8649 hex->line(3)->child(0)->vertex_index(1),
8650 };
8651
8652 // note: for lines 0 to 3 the orientation of the
8653 // line is 'true', if vertex 0 is on the bottom
8654 // face
8655 for (unsigned int i = 0; i < 4; ++i)
8656 if (lines[i]->vertex_index(0) == middle_vertices[i])
8657 line_orientation[i] = true;
8658 else
8659 {
8660 // it must be the other way round then
8661 Assert(lines[i]->vertex_index(1) ==
8662 middle_vertices[i],
8664 line_orientation[i] = false;
8665 }
8666
8667 // note: for lines 4 to 11 (inner lines of the
8668 // outer quads) the following holds: the second
8669 // vertex of the even lines in standard
8670 // orientation is the vertex in the middle of
8671 // the quad, whereas for odd lines the first
8672 // vertex is the same middle vertex.
8673 for (unsigned int i = 4; i < 12; ++i)
8674 if (lines[i]->vertex_index((i + 1) % 2) ==
8675 middle_vertex_index<dim, spacedim>(
8676 hex->face(3 + i / 4)))
8677 line_orientation[i] = true;
8678 else
8679 {
8680 // it must be the other way
8681 // round then
8682 Assert(lines[i]->vertex_index(i % 2) ==
8683 (middle_vertex_index<dim, spacedim>(
8684 hex->face(3 + i / 4))),
8686 line_orientation[i] = false;
8687 }
8688 // for the last line the line orientation is
8689 // always true, since it was just constructed
8690 // that way
8691 line_orientation[12] = true;
8692
8693 // set up the 4 quads, numbered as follows (left
8694 // quad numbering, right line numbering
8695 // extracted from above)
8696 //
8697 // * *
8698 // /| 9|
8699 // * | * |
8700 // y/| | 8| 3
8701 // * |1| * | |
8702 // | | |x | 12|
8703 // |0| * | | *
8704 // | |/ 2 |5
8705 // | * | *
8706 // |/ |4
8707 // * *
8708 //
8709 // x
8710 // *---*---* *10-*-11*
8711 // | | | | | |
8712 // | 2 | 3 | 0 12 1
8713 // | | | | | |
8714 // *---*---*y *-6-*-7-*
8715
8716 new_quads[0]->set_bounding_object_indices(
8717 {line_indices[2],
8718 line_indices[12],
8719 line_indices[4],
8720 line_indices[8]});
8721 new_quads[1]->set_bounding_object_indices(
8722 {line_indices[12],
8723 line_indices[3],
8724 line_indices[5],
8725 line_indices[9]});
8726 new_quads[2]->set_bounding_object_indices(
8727 {line_indices[6],
8728 line_indices[10],
8729 line_indices[0],
8730 line_indices[12]});
8731 new_quads[3]->set_bounding_object_indices(
8732 {line_indices[7],
8733 line_indices[11],
8734 line_indices[12],
8735 line_indices[1]});
8736
8737 new_quads[0]->set_line_orientation(
8738 0, line_orientation[2]);
8739 new_quads[0]->set_line_orientation(
8740 2, line_orientation[4]);
8741 new_quads[0]->set_line_orientation(
8742 3, line_orientation[8]);
8743
8744 new_quads[1]->set_line_orientation(
8745 1, line_orientation[3]);
8746 new_quads[1]->set_line_orientation(
8747 2, line_orientation[5]);
8748 new_quads[1]->set_line_orientation(
8749 3, line_orientation[9]);
8750
8751 new_quads[2]->set_line_orientation(
8752 0, line_orientation[6]);
8753 new_quads[2]->set_line_orientation(
8754 1, line_orientation[10]);
8755 new_quads[2]->set_line_orientation(
8756 2, line_orientation[0]);
8757
8758 new_quads[3]->set_line_orientation(
8759 0, line_orientation[7]);
8760 new_quads[3]->set_line_orientation(
8761 1, line_orientation[11]);
8762 new_quads[3]->set_line_orientation(
8763 3, line_orientation[1]);
8764
8765 // the quads are numbered as follows:
8766 //
8767 // planes in the interior of the old hex:
8768 //
8769 // *
8770 // /|
8771 // * | x
8772 // /| | *---*---* *---------*
8773 // * |1| | | | / /
8774 // | | | | 2 | 3 | / /
8775 // |0| * | | | / /
8776 // | |/ *---*---*y *---------*x
8777 // | *
8778 // |/
8779 // *
8780 //
8781 // children of the faces of the old hex
8782 //
8783 // *---*---* *---*---*
8784 // /| | | /18 / 19/|
8785 // * |10 | 11| /---/---* |
8786 // /| | | | /16 / 17/| |
8787 // * |5| | | *---*---* |7|
8788 // | | *---*---* | | | | *
8789 // |4|/14 / 15/ | | |6|/
8790 // | *---/---/ | 8 | 9 | *
8791 // |/12 / 13/ | | |/
8792 // *---*---* *---*---*
8793 //
8794 // note that we have to take care of the
8795 // orientation of faces.
8796 const int quad_indices[20] = {
8797 new_quads[0]->index(), // 0
8798 new_quads[1]->index(),
8799 new_quads[2]->index(),
8800 new_quads[3]->index(),
8801
8802 hex->face(0)->child_index(
8803 child_at_origin[hex->face(0)->refinement_case() -
8804 1][f_fl[0]][f_ro[0]]), // 4
8805 hex->face(0)->child_index(
8806 1 -
8807 child_at_origin[hex->face(0)->refinement_case() -
8808 1][f_fl[0]][f_ro[0]]),
8809
8810 hex->face(1)->child_index(
8811 child_at_origin[hex->face(1)->refinement_case() -
8812 1][f_fl[1]][f_ro[1]]), // 6
8813 hex->face(1)->child_index(
8814 1 -
8815 child_at_origin[hex->face(1)->refinement_case() -
8816 1][f_fl[1]][f_ro[1]]),
8817
8818 hex->face(2)->child_index(
8819 child_at_origin[hex->face(2)->refinement_case() -
8820 1][f_fl[2]][f_ro[2]]), // 8
8821 hex->face(2)->child_index(
8822 1 -
8823 child_at_origin[hex->face(2)->refinement_case() -
8824 1][f_fl[2]][f_ro[2]]),
8825
8826 hex->face(3)->child_index(
8827 child_at_origin[hex->face(3)->refinement_case() -
8828 1][f_fl[3]][f_ro[3]]), // 10
8829 hex->face(3)->child_index(
8830 1 -
8831 child_at_origin[hex->face(3)->refinement_case() -
8832 1][f_fl[3]][f_ro[3]]),
8833
8834 hex->face(4)->isotropic_child_index(
8836 0, f_or[4], f_fl[4], f_ro[4])), // 12
8837 hex->face(4)->isotropic_child_index(
8839 1, f_or[4], f_fl[4], f_ro[4])),
8840 hex->face(4)->isotropic_child_index(
8842 2, f_or[4], f_fl[4], f_ro[4])),
8843 hex->face(4)->isotropic_child_index(
8845 3, f_or[4], f_fl[4], f_ro[4])),
8846
8847 hex->face(5)->isotropic_child_index(
8849 0, f_or[5], f_fl[5], f_ro[5])), // 16
8850 hex->face(5)->isotropic_child_index(
8852 1, f_or[5], f_fl[5], f_ro[5])),
8853 hex->face(5)->isotropic_child_index(
8855 2, f_or[5], f_fl[5], f_ro[5])),
8856 hex->face(5)->isotropic_child_index(
8858 3, f_or[5], f_fl[5], f_ro[5]))};
8859
8860 new_hexes[0]->set_bounding_object_indices(
8861 {quad_indices[4],
8862 quad_indices[0],
8863 quad_indices[8],
8864 quad_indices[2],
8865 quad_indices[12],
8866 quad_indices[16]});
8867 new_hexes[1]->set_bounding_object_indices(
8868 {quad_indices[0],
8869 quad_indices[6],
8870 quad_indices[9],
8871 quad_indices[3],
8872 quad_indices[13],
8873 quad_indices[17]});
8874 new_hexes[2]->set_bounding_object_indices(
8875 {quad_indices[5],
8876 quad_indices[1],
8877 quad_indices[2],
8878 quad_indices[10],
8879 quad_indices[14],
8880 quad_indices[18]});
8881 new_hexes[3]->set_bounding_object_indices(
8882 {quad_indices[1],
8883 quad_indices[7],
8884 quad_indices[3],
8885 quad_indices[11],
8886 quad_indices[15],
8887 quad_indices[19]});
8888 break;
8889 }
8890
8892 {
8893 //----------------------------
8894 //
8895 // RefinementCase<dim>::cut_xz
8896 //
8897 // the refined cube will look like this:
8898 //
8899 // *----*----*
8900 // / / /|
8901 // / / / |
8902 // / / / *
8903 // *----*----* /|
8904 // | | | / |
8905 // | | |/ *
8906 // *----*----* /
8907 // | | | /
8908 // | | |/
8909 // *----*----*
8910 //
8911
8912 // first, create the new internal line
8913 new_lines[0]->set_bounding_object_indices(
8914 {middle_vertex_index<dim, spacedim>(hex->face(2)),
8915 middle_vertex_index<dim, spacedim>(hex->face(3))});
8916
8917 // again, first collect some data about the
8918 // indices of the lines, with the following
8919 // numbering:
8920
8921 // face 0: left plane
8922 // *
8923 // /|
8924 // / |
8925 // / *
8926 // * /|
8927 // | 0 |
8928 // |/ *
8929 // * /
8930 // | /
8931 // |/
8932 // *
8933 // face 1: right plane
8934 // *
8935 // /|
8936 // / |
8937 // / *
8938 // * /|
8939 // | 1 |
8940 // |/ *
8941 // * /
8942 // | /
8943 // |/
8944 // *
8945 // face 2: front plane
8946 // (note: x,y exchanged)
8947 // *---*---*
8948 // | 5 |
8949 // *-6-*-7-*
8950 // | 4 |
8951 // *---*---*
8952 // face 3: back plane
8953 // (note: x,y exchanged)
8954 // *---*---*
8955 // | 9 |
8956 // *10-*-11*
8957 // | 8 |
8958 // *---*---*
8959 // face 4: bottom plane
8960 // *---*---*
8961 // / / /
8962 // / 2 /
8963 // / / /
8964 // *---*---*
8965 // face 5: top plane
8966 // *---*---*
8967 // / / /
8968 // / 3 /
8969 // / / /
8970 // *---*---*
8971 // middle planes
8972 // *---*---* *-------*
8973 // / / / | |
8974 // / 12 / | |
8975 // / / / | |
8976 // *---*---* *-------*
8977
8978 // set up a list of line iterators first. from
8979 // this, construct lists of line_indices and
8980 // line orientations later on
8981 const typename Triangulation<
8982 dim,
8983 spacedim>::raw_line_iterator lines[13] = {
8984 hex->face(0)->child(0)->line(
8985 (hex->face(0)->refinement_case() ==
8987 1 :
8988 3), // 0
8989 hex->face(1)->child(0)->line(
8990 (hex->face(1)->refinement_case() ==
8992 1 :
8993 3), // 1
8994 hex->face(4)->child(0)->line(
8995 (hex->face(4)->refinement_case() ==
8997 1 :
8998 3), // 2
8999 hex->face(5)->child(0)->line(
9000 (hex->face(5)->refinement_case() ==
9002 1 :
9003 3), // 3
9004
9005 hex->face(2)
9006 ->isotropic_child(
9008 0, f_or[2], f_fl[2], f_ro[2]))
9009 ->line(
9011 3, f_or[2], f_fl[2], f_ro[2])), // 4
9012 hex->face(2)
9013 ->isotropic_child(
9015 3, f_or[2], f_fl[2], f_ro[2]))
9016 ->line(
9018 2, f_or[2], f_fl[2], f_ro[2])), // 5
9019 hex->face(2)
9020 ->isotropic_child(
9022 0, f_or[2], f_fl[2], f_ro[2]))
9023 ->line(
9025 1, f_or[2], f_fl[2], f_ro[2])), // 6
9026 hex->face(2)
9027 ->isotropic_child(
9029 3, f_or[2], f_fl[2], f_ro[2]))
9030 ->line(
9032 0, f_or[2], f_fl[2], f_ro[2])), // 7
9033
9034 hex->face(3)
9035 ->isotropic_child(
9037 0, f_or[3], f_fl[3], f_ro[3]))
9038 ->line(
9040 3, f_or[3], f_fl[3], f_ro[3])), // 8
9041 hex->face(3)
9042 ->isotropic_child(
9044 3, f_or[3], f_fl[3], f_ro[3]))
9045 ->line(
9047 2, f_or[3], f_fl[3], f_ro[3])), // 9
9048 hex->face(3)
9049 ->isotropic_child(
9051 0, f_or[3], f_fl[3], f_ro[3]))
9052 ->line(
9054 1, f_or[3], f_fl[3], f_ro[3])), // 10
9055 hex->face(3)
9056 ->isotropic_child(
9058 3, f_or[3], f_fl[3], f_ro[3]))
9059 ->line(
9061 0, f_or[3], f_fl[3], f_ro[3])), // 11
9062
9063 new_lines[0] // 12
9064 };
9065
9066 unsigned int line_indices[13];
9067 for (unsigned int i = 0; i < 13; ++i)
9068 line_indices[i] = lines[i]->index();
9069
9070 // the orientation of lines for the inner quads
9071 // is quite tricky. as these lines are newly
9072 // created ones and thus have no parents, they
9073 // cannot inherit this property. set up an array
9074 // and fill it with the respective values
9075 bool line_orientation[13];
9076
9077 // the middle vertices of the
9078 // lines of our front face
9079 const unsigned int middle_vertices[4] = {
9080 hex->line(8)->child(0)->vertex_index(1),
9081 hex->line(9)->child(0)->vertex_index(1),
9082 hex->line(2)->child(0)->vertex_index(1),
9083 hex->line(6)->child(0)->vertex_index(1),
9084 };
9085
9086 // note: for lines 0 to 3 the orientation of the
9087 // line is 'true', if vertex 0 is on the front
9088 for (unsigned int i = 0; i < 4; ++i)
9089 if (lines[i]->vertex_index(0) == middle_vertices[i])
9090 line_orientation[i] = true;
9091 else
9092 {
9093 // it must be the other way round then
9094 Assert(lines[i]->vertex_index(1) ==
9095 middle_vertices[i],
9097 line_orientation[i] = false;
9098 }
9099
9100 // note: for lines 4 to 11 (inner lines of the
9101 // outer quads) the following holds: the second
9102 // vertex of the even lines in standard
9103 // orientation is the vertex in the middle of
9104 // the quad, whereas for odd lines the first
9105 // vertex is the same middle vertex.
9106 for (unsigned int i = 4; i < 12; ++i)
9107 if (lines[i]->vertex_index((i + 1) % 2) ==
9108 middle_vertex_index<dim, spacedim>(
9109 hex->face(1 + i / 4)))
9110 line_orientation[i] = true;
9111 else
9112 {
9113 // it must be the other way
9114 // round then
9115 Assert(lines[i]->vertex_index(i % 2) ==
9116 (middle_vertex_index<dim, spacedim>(
9117 hex->face(1 + i / 4))),
9119 line_orientation[i] = false;
9120 }
9121 // for the last line the line orientation is
9122 // always true, since it was just constructed
9123 // that way
9124 line_orientation[12] = true;
9125
9126 // set up the 4 quads, numbered as follows (left
9127 // quad numbering, right line numbering
9128 // extracted from above), the drawings denote
9129 // middle planes
9130 //
9131 // * *
9132 // /| /|
9133 // / | 3 9
9134 // y/ * / *
9135 // * 3/| * /|
9136 // | / |x 5 12|8
9137 // |/ * |/ *
9138 // * 2/ * /
9139 // | / 4 2
9140 // |/ |/
9141 // * *
9142 //
9143 // y
9144 // *----*----* *-10-*-11-*
9145 // / / / / / /
9146 // / 0 / 1 / 0 12 1
9147 // / / / / / /
9148 // *----*----*x *--6-*--7-*
9149
9150 new_quads[0]->set_bounding_object_indices(
9151 {line_indices[0],
9152 line_indices[12],
9153 line_indices[6],
9154 line_indices[10]});
9155 new_quads[1]->set_bounding_object_indices(
9156 {line_indices[12],
9157 line_indices[1],
9158 line_indices[7],
9159 line_indices[11]});
9160 new_quads[2]->set_bounding_object_indices(
9161 {line_indices[4],
9162 line_indices[8],
9163 line_indices[2],
9164 line_indices[12]});
9165 new_quads[3]->set_bounding_object_indices(
9166 {line_indices[5],
9167 line_indices[9],
9168 line_indices[12],
9169 line_indices[3]});
9170
9171 new_quads[0]->set_line_orientation(
9172 0, line_orientation[0]);
9173 new_quads[0]->set_line_orientation(
9174 2, line_orientation[6]);
9175 new_quads[0]->set_line_orientation(
9176 3, line_orientation[10]);
9177
9178 new_quads[1]->set_line_orientation(
9179 1, line_orientation[1]);
9180 new_quads[1]->set_line_orientation(
9181 2, line_orientation[7]);
9182 new_quads[1]->set_line_orientation(
9183 3, line_orientation[11]);
9184
9185 new_quads[2]->set_line_orientation(
9186 0, line_orientation[4]);
9187 new_quads[2]->set_line_orientation(
9188 1, line_orientation[8]);
9189 new_quads[2]->set_line_orientation(
9190 2, line_orientation[2]);
9191
9192 new_quads[3]->set_line_orientation(
9193 0, line_orientation[5]);
9194 new_quads[3]->set_line_orientation(
9195 1, line_orientation[9]);
9196 new_quads[3]->set_line_orientation(
9197 3, line_orientation[3]);
9198
9199 // the quads are numbered as follows:
9200 //
9201 // planes in the interior of the old hex:
9202 //
9203 // *
9204 // /|
9205 // / | x
9206 // /3 * *-------* *----*----*
9207 // * /| | | / / /
9208 // | / | | | / 0 / 1 /
9209 // |/ * | | / / /
9210 // * 2/ *-------*y *----*----*x
9211 // | /
9212 // |/
9213 // *
9214 //
9215 // children of the faces
9216 // of the old hex
9217 // *---*---* *---*---*
9218 // /|13 | 15| / / /|
9219 // / | | | /18 / 19/ |
9220 // / *---*---* / / / *
9221 // * 5/| | | *---*---* 7/|
9222 // | / |12 | 14| | 9 | 11| / |
9223 // |/4 *---*---* | | |/6 *
9224 // * / / / *---*---* /
9225 // | /16 / 17/ | | | /
9226 // |/ / / | 8 | 10|/
9227 // *---*---* *---*---*
9228 //
9229 // note that we have to take care of the
9230 // orientation of faces.
9231 const int quad_indices[20] = {
9232 new_quads[0]->index(), // 0
9233 new_quads[1]->index(),
9234 new_quads[2]->index(),
9235 new_quads[3]->index(),
9236
9237 hex->face(0)->child_index(
9238 child_at_origin[hex->face(0)->refinement_case() -
9239 1][f_fl[0]][f_ro[0]]), // 4
9240 hex->face(0)->child_index(
9241 1 -
9242 child_at_origin[hex->face(0)->refinement_case() -
9243 1][f_fl[0]][f_ro[0]]),
9244
9245 hex->face(1)->child_index(
9246 child_at_origin[hex->face(1)->refinement_case() -
9247 1][f_fl[1]][f_ro[1]]), // 6
9248 hex->face(1)->child_index(
9249 1 -
9250 child_at_origin[hex->face(1)->refinement_case() -
9251 1][f_fl[1]][f_ro[1]]),
9252
9253 hex->face(2)->isotropic_child_index(
9255 0, f_or[2], f_fl[2], f_ro[2])), // 8
9256 hex->face(2)->isotropic_child_index(
9258 1, f_or[2], f_fl[2], f_ro[2])),
9259 hex->face(2)->isotropic_child_index(
9261 2, f_or[2], f_fl[2], f_ro[2])),
9262 hex->face(2)->isotropic_child_index(
9264 3, f_or[2], f_fl[2], f_ro[2])),
9265
9266 hex->face(3)->isotropic_child_index(
9268 0, f_or[3], f_fl[3], f_ro[3])), // 12
9269 hex->face(3)->isotropic_child_index(
9271 1, f_or[3], f_fl[3], f_ro[3])),
9272 hex->face(3)->isotropic_child_index(
9274 2, f_or[3], f_fl[3], f_ro[3])),
9275 hex->face(3)->isotropic_child_index(
9277 3, f_or[3], f_fl[3], f_ro[3])),
9278
9279 hex->face(4)->child_index(
9280 child_at_origin[hex->face(4)->refinement_case() -
9281 1][f_fl[4]][f_ro[4]]), // 16
9282 hex->face(4)->child_index(
9283 1 -
9284 child_at_origin[hex->face(4)->refinement_case() -
9285 1][f_fl[4]][f_ro[4]]),
9286
9287 hex->face(5)->child_index(
9288 child_at_origin[hex->face(5)->refinement_case() -
9289 1][f_fl[5]][f_ro[5]]), // 18
9290 hex->face(5)->child_index(
9291 1 -
9292 child_at_origin[hex->face(5)->refinement_case() -
9293 1][f_fl[5]][f_ro[5]])};
9294
9295 // due to the exchange of x and y for the front
9296 // and back face, we order the children
9297 // according to
9298 //
9299 // *---*---*
9300 // | 1 | 3 |
9301 // *---*---*
9302 // | 0 | 2 |
9303 // *---*---*
9304 new_hexes[0]->set_bounding_object_indices(
9305 {quad_indices[4],
9306 quad_indices[2],
9307 quad_indices[8],
9308 quad_indices[12],
9309 quad_indices[16],
9310 quad_indices[0]});
9311 new_hexes[1]->set_bounding_object_indices(
9312 {quad_indices[5],
9313 quad_indices[3],
9314 quad_indices[9],
9315 quad_indices[13],
9316 quad_indices[0],
9317 quad_indices[18]});
9318 new_hexes[2]->set_bounding_object_indices(
9319 {quad_indices[2],
9320 quad_indices[6],
9321 quad_indices[10],
9322 quad_indices[14],
9323 quad_indices[17],
9324 quad_indices[1]});
9325 new_hexes[3]->set_bounding_object_indices(
9326 {quad_indices[3],
9327 quad_indices[7],
9328 quad_indices[11],
9329 quad_indices[15],
9330 quad_indices[1],
9331 quad_indices[19]});
9332 break;
9333 }
9334
9336 {
9337 //----------------------------
9338 //
9339 // RefinementCase<dim>::cut_yz
9340 //
9341 // the refined cube will look like this:
9342 //
9343 // *---------*
9344 // / /|
9345 // *---------* |
9346 // / /| |
9347 // *---------* |/|
9348 // | | * |
9349 // | |/| *
9350 // *---------* |/
9351 // | | *
9352 // | |/
9353 // *---------*
9354 //
9355
9356 // first, create the new
9357 // internal line
9358 new_lines[0]->set_bounding_object_indices(
9359
9360 {middle_vertex_index<dim, spacedim>(hex->face(0)),
9361 middle_vertex_index<dim, spacedim>(hex->face(1))});
9362
9363 // again, first collect some data about the
9364 // indices of the lines, with the following
9365 // numbering: (note that face 0 and 1 each are
9366 // shown twice for better readability)
9367
9368 // face 0: left plane
9369 // * *
9370 // /| /|
9371 // * | * |
9372 // /| * /| *
9373 // * 5/| * |7|
9374 // | * | | * |
9375 // |/| * |6| *
9376 // * 4/ * |/
9377 // | * | *
9378 // |/ |/
9379 // * *
9380 // face 1: right plane
9381 // * *
9382 // /| /|
9383 // * | * |
9384 // /| * /| *
9385 // * 9/| * |11
9386 // | * | | * |
9387 // |/| * |10 *
9388 // * 8/ * |/
9389 // | * | *
9390 // |/ |/
9391 // * *
9392 // face 2: front plane
9393 // (note: x,y exchanged)
9394 // *-------*
9395 // | |
9396 // *---0---*
9397 // | |
9398 // *-------*
9399 // face 3: back plane
9400 // (note: x,y exchanged)
9401 // *-------*
9402 // | |
9403 // *---1---*
9404 // | |
9405 // *-------*
9406 // face 4: bottom plane
9407 // *-------*
9408 // / /
9409 // *---2---*
9410 // / /
9411 // *-------*
9412 // face 5: top plane
9413 // *-------*
9414 // / /
9415 // *---3---*
9416 // / /
9417 // *-------*
9418 // middle planes
9419 // *-------* *-------*
9420 // / / | |
9421 // *---12--* | |
9422 // / / | |
9423 // *-------* *-------*
9424
9425 // set up a list of line iterators first. from
9426 // this, construct lists of line_indices and
9427 // line orientations later on
9428 const typename Triangulation<
9429 dim,
9430 spacedim>::raw_line_iterator lines[13] = {
9431 hex->face(2)->child(0)->line(
9432 (hex->face(2)->refinement_case() ==
9434 1 :
9435 3), // 0
9436 hex->face(3)->child(0)->line(
9437 (hex->face(3)->refinement_case() ==
9439 1 :
9440 3), // 1
9441 hex->face(4)->child(0)->line(
9442 (hex->face(4)->refinement_case() ==
9444 1 :
9445 3), // 2
9446 hex->face(5)->child(0)->line(
9447 (hex->face(5)->refinement_case() ==
9449 1 :
9450 3), // 3
9451
9452 hex->face(0)
9453 ->isotropic_child(
9455 0, f_or[0], f_fl[0], f_ro[0]))
9456 ->line(
9458 1, f_or[0], f_fl[0], f_ro[0])), // 4
9459 hex->face(0)
9460 ->isotropic_child(
9462 3, f_or[0], f_fl[0], f_ro[0]))
9463 ->line(
9465 0, f_or[0], f_fl[0], f_ro[0])), // 5
9466 hex->face(0)
9467 ->isotropic_child(
9469 0, f_or[0], f_fl[0], f_ro[0]))
9470 ->line(
9472 3, f_or[0], f_fl[0], f_ro[0])), // 6
9473 hex->face(0)
9474 ->isotropic_child(
9476 3, f_or[0], f_fl[0], f_ro[0]))
9477 ->line(
9479 2, f_or[0], f_fl[0], f_ro[0])), // 7
9480
9481 hex->face(1)
9482 ->isotropic_child(
9484 0, f_or[1], f_fl[1], f_ro[1]))
9485 ->line(
9487 1, f_or[1], f_fl[1], f_ro[1])), // 8
9488 hex->face(1)
9489 ->isotropic_child(
9491 3, f_or[1], f_fl[1], f_ro[1]))
9492 ->line(
9494 0, f_or[1], f_fl[1], f_ro[1])), // 9
9495 hex->face(1)
9496 ->isotropic_child(
9498 0, f_or[1], f_fl[1], f_ro[1]))
9499 ->line(
9501 3, f_or[1], f_fl[1], f_ro[1])), // 10
9502 hex->face(1)
9503 ->isotropic_child(
9505 3, f_or[1], f_fl[1], f_ro[1]))
9506 ->line(
9508 2, f_or[1], f_fl[1], f_ro[1])), // 11
9509
9510 new_lines[0] // 12
9511 };
9512
9513 unsigned int line_indices[13];
9514
9515 for (unsigned int i = 0; i < 13; ++i)
9516 line_indices[i] = lines[i]->index();
9517
9518 // the orientation of lines for the inner quads
9519 // is quite tricky. as these lines are newly
9520 // created ones and thus have no parents, they
9521 // cannot inherit this property. set up an array
9522 // and fill it with the respective values
9523 bool line_orientation[13];
9524
9525 // the middle vertices of the lines of our front
9526 // face
9527 const unsigned int middle_vertices[4] = {
9528 hex->line(8)->child(0)->vertex_index(1),
9529 hex->line(10)->child(0)->vertex_index(1),
9530 hex->line(0)->child(0)->vertex_index(1),
9531 hex->line(4)->child(0)->vertex_index(1),
9532 };
9533
9534 // note: for lines 0 to 3 the orientation of the
9535 // line is 'true', if vertex 0 is on the front
9536 for (unsigned int i = 0; i < 4; ++i)
9537 if (lines[i]->vertex_index(0) == middle_vertices[i])
9538 line_orientation[i] = true;
9539 else
9540 {
9541 // it must be the other way round then
9542 Assert(lines[i]->vertex_index(1) ==
9543 middle_vertices[i],
9545 line_orientation[i] = false;
9546 }
9547
9548 // note: for lines 4 to 11 (inner lines of the
9549 // outer quads) the following holds: the second
9550 // vertex of the even lines in standard
9551 // orientation is the vertex in the middle of
9552 // the quad, whereas for odd lines the first
9553 // vertex is the same middle vertex.
9554 for (unsigned int i = 4; i < 12; ++i)
9555 if (lines[i]->vertex_index((i + 1) % 2) ==
9556 middle_vertex_index<dim, spacedim>(
9557 hex->face(i / 4 - 1)))
9558 line_orientation[i] = true;
9559 else
9560 {
9561 // it must be the other way
9562 // round then
9563 Assert(lines[i]->vertex_index(i % 2) ==
9564 (middle_vertex_index<dim, spacedim>(
9565 hex->face(i / 4 - 1))),
9567 line_orientation[i] = false;
9568 }
9569 // for the last line the line orientation is
9570 // always true, since it was just constructed
9571 // that way
9572 line_orientation[12] = true;
9573
9574 // set up the 4 quads, numbered as follows (left
9575 // quad numbering, right line numbering
9576 // extracted from above)
9577 //
9578 // x
9579 // *-------* *---3---*
9580 // | 3 | 5 9
9581 // *-------* *---12--*
9582 // | 2 | 4 8
9583 // *-------*y *---2---*
9584 //
9585 // y
9586 // *---------* *----1----*
9587 // / 1 / 7 11
9588 // *---------* *----12---*
9589 // / 0 / 6 10
9590 // *---------*x *----0----*
9591
9592 new_quads[0]->set_bounding_object_indices(
9593 {line_indices[6],
9594 line_indices[10],
9595 line_indices[0],
9596 line_indices[12]});
9597 new_quads[1]->set_bounding_object_indices(
9598 {line_indices[7],
9599 line_indices[11],
9600 line_indices[12],
9601 line_indices[1]});
9602 new_quads[2]->set_bounding_object_indices(
9603 {line_indices[2],
9604 line_indices[12],
9605 line_indices[4],
9606 line_indices[8]});
9607 new_quads[3]->set_bounding_object_indices(
9608 {line_indices[12],
9609 line_indices[3],
9610 line_indices[5],
9611 line_indices[9]});
9612
9613 new_quads[0]->set_line_orientation(
9614 0, line_orientation[6]);
9615 new_quads[0]->set_line_orientation(
9616 1, line_orientation[10]);
9617 new_quads[0]->set_line_orientation(
9618 2, line_orientation[0]);
9619
9620 new_quads[1]->set_line_orientation(
9621 0, line_orientation[7]);
9622 new_quads[1]->set_line_orientation(
9623 1, line_orientation[11]);
9624 new_quads[1]->set_line_orientation(
9625 3, line_orientation[1]);
9626
9627 new_quads[2]->set_line_orientation(
9628 0, line_orientation[2]);
9629 new_quads[2]->set_line_orientation(
9630 2, line_orientation[4]);
9631 new_quads[2]->set_line_orientation(
9632 3, line_orientation[8]);
9633
9634 new_quads[3]->set_line_orientation(
9635 1, line_orientation[3]);
9636 new_quads[3]->set_line_orientation(
9637 2, line_orientation[5]);
9638 new_quads[3]->set_line_orientation(
9639 3, line_orientation[9]);
9640
9641 // the quads are numbered as follows:
9642 //
9643 // planes in the interior of the old hex:
9644 //
9645 // *
9646 // /|
9647 // / | x
9648 // / | *-------* *---------*
9649 // * | | 3 | / 1 /
9650 // | | *-------* *---------*
9651 // | * | 2 | / 0 /
9652 // | / *-------*y *---------*x
9653 // | /
9654 // |/
9655 // *
9656 //
9657 // children of the faces
9658 // of the old hex
9659 // *-------* *-------*
9660 // /| | / 19 /|
9661 // * | 15 | *-------* |
9662 // /|7*-------* / 18 /|11
9663 // * |/| | *-------* |/|
9664 // |6* | 14 | | 10* |
9665 // |/|5*-------* | 13 |/|9*
9666 // * |/ 17 / *-------* |/
9667 // |4*-------* | |8*
9668 // |/ 16 / | 12 |/
9669 // *-------* *-------*
9670 //
9671 // note that we have to take care of the
9672 // orientation of faces.
9673 const int quad_indices[20] = {
9674 new_quads[0]->index(), // 0
9675 new_quads[1]->index(),
9676 new_quads[2]->index(),
9677 new_quads[3]->index(),
9678
9679 hex->face(0)->isotropic_child_index(
9681 0, f_or[0], f_fl[0], f_ro[0])), // 4
9682 hex->face(0)->isotropic_child_index(
9684 1, f_or[0], f_fl[0], f_ro[0])),
9685 hex->face(0)->isotropic_child_index(
9687 2, f_or[0], f_fl[0], f_ro[0])),
9688 hex->face(0)->isotropic_child_index(
9690 3, f_or[0], f_fl[0], f_ro[0])),
9691
9692 hex->face(1)->isotropic_child_index(
9694 0, f_or[1], f_fl[1], f_ro[1])), // 8
9695 hex->face(1)->isotropic_child_index(
9697 1, f_or[1], f_fl[1], f_ro[1])),
9698 hex->face(1)->isotropic_child_index(
9700 2, f_or[1], f_fl[1], f_ro[1])),
9701 hex->face(1)->isotropic_child_index(
9703 3, f_or[1], f_fl[1], f_ro[1])),
9704
9705 hex->face(2)->child_index(
9706 child_at_origin[hex->face(2)->refinement_case() -
9707 1][f_fl[2]][f_ro[2]]), // 12
9708 hex->face(2)->child_index(
9709 1 -
9710 child_at_origin[hex->face(2)->refinement_case() -
9711 1][f_fl[2]][f_ro[2]]),
9712
9713 hex->face(3)->child_index(
9714 child_at_origin[hex->face(3)->refinement_case() -
9715 1][f_fl[3]][f_ro[3]]), // 14
9716 hex->face(3)->child_index(
9717 1 -
9718 child_at_origin[hex->face(3)->refinement_case() -
9719 1][f_fl[3]][f_ro[3]]),
9720
9721 hex->face(4)->child_index(
9722 child_at_origin[hex->face(4)->refinement_case() -
9723 1][f_fl[4]][f_ro[4]]), // 16
9724 hex->face(4)->child_index(
9725 1 -
9726 child_at_origin[hex->face(4)->refinement_case() -
9727 1][f_fl[4]][f_ro[4]]),
9728
9729 hex->face(5)->child_index(
9730 child_at_origin[hex->face(5)->refinement_case() -
9731 1][f_fl[5]][f_ro[5]]), // 18
9732 hex->face(5)->child_index(
9733 1 -
9734 child_at_origin[hex->face(5)->refinement_case() -
9735 1][f_fl[5]][f_ro[5]])};
9736
9737 new_hexes[0]->set_bounding_object_indices(
9738 {quad_indices[4],
9739 quad_indices[8],
9740 quad_indices[12],
9741 quad_indices[2],
9742 quad_indices[16],
9743 quad_indices[0]});
9744 new_hexes[1]->set_bounding_object_indices(
9745 {quad_indices[5],
9746 quad_indices[9],
9747 quad_indices[2],
9748 quad_indices[14],
9749 quad_indices[17],
9750 quad_indices[1]});
9751 new_hexes[2]->set_bounding_object_indices(
9752 {quad_indices[6],
9753 quad_indices[10],
9754 quad_indices[13],
9755 quad_indices[3],
9756 quad_indices[0],
9757 quad_indices[18]});
9758 new_hexes[3]->set_bounding_object_indices(
9759 {quad_indices[7],
9760 quad_indices[11],
9761 quad_indices[3],
9762 quad_indices[15],
9763 quad_indices[1],
9764 quad_indices[19]});
9765 break;
9766 }
9767
9769 {
9770 //----------------------------
9771 //
9772 // RefinementCase<dim>::cut_xyz
9773 // isotropic refinement
9774 //
9775 // the refined cube will look
9776 // like this:
9777 //
9778 // *----*----*
9779 // / / /|
9780 // *----*----* |
9781 // / / /| *
9782 // *----*----* |/|
9783 // | | | * |
9784 // | | |/| *
9785 // *----*----* |/
9786 // | | | *
9787 // | | |/
9788 // *----*----*
9789 //
9790
9791 // find the next unused vertex and set it
9792 // appropriately
9793 while (
9794 triangulation.vertices_used[next_unused_vertex] ==
9795 true)
9796 ++next_unused_vertex;
9797 Assert(
9798 next_unused_vertex < triangulation.vertices.size(),
9799 ExcMessage(
9800 "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."));
9801 triangulation.vertices_used[next_unused_vertex] =
9802 true;
9803
9804 // the new vertex is definitely in the interior,
9805 // so we need not worry about the
9806 // boundary. However we need to worry about
9807 // Manifolds. Let the cell compute its own
9808 // center, by querying the underlying manifold
9809 // object.
9810 triangulation.vertices[next_unused_vertex] =
9811 hex->center(true, true);
9812
9813 // set the data of the six lines. first collect
9814 // the indices of the seven vertices (consider
9815 // the two planes to be crossed to form the
9816 // planes cutting the hex in two vertically and
9817 // horizontally)
9818 //
9819 // *--3--* *--5--*
9820 // / / / | | |
9821 // 0--6--1 0--6--1
9822 // / / / | | |
9823 // *--2--* *--4--*
9824 // the lines are numbered
9825 // as follows:
9826 // *--*--* *--*--*
9827 // / 1 / | 5 |
9828 // *2-*-3* *2-*-3*
9829 // / 0 / | 4 |
9830 // *--*--* *--*--*
9831 //
9832 const unsigned int vertex_indices[7] = {
9833 middle_vertex_index<dim, spacedim>(hex->face(0)),
9834 middle_vertex_index<dim, spacedim>(hex->face(1)),
9835 middle_vertex_index<dim, spacedim>(hex->face(2)),
9836 middle_vertex_index<dim, spacedim>(hex->face(3)),
9837 middle_vertex_index<dim, spacedim>(hex->face(4)),
9838 middle_vertex_index<dim, spacedim>(hex->face(5)),
9839 next_unused_vertex};
9840
9841 new_lines[0]->set_bounding_object_indices(
9843 new_lines[1]->set_bounding_object_indices(
9845 new_lines[2]->set_bounding_object_indices(
9847 new_lines[3]->set_bounding_object_indices(
9849 new_lines[4]->set_bounding_object_indices(
9851 new_lines[5]->set_bounding_object_indices(
9853
9854 // again, first collect some data about the
9855 // indices of the lines, with the following
9856 // numbering: (note that face 0 and 1 each are
9857 // shown twice for better readability)
9858
9859 // face 0: left plane
9860 // * *
9861 // /| /|
9862 // * | * |
9863 // /| * /| *
9864 // * 1/| * |3|
9865 // | * | | * |
9866 // |/| * |2| *
9867 // * 0/ * |/
9868 // | * | *
9869 // |/ |/
9870 // * *
9871 // face 1: right plane
9872 // * *
9873 // /| /|
9874 // * | * |
9875 // /| * /| *
9876 // * 5/| * |7|
9877 // | * | | * |
9878 // |/| * |6| *
9879 // * 4/ * |/
9880 // | * | *
9881 // |/ |/
9882 // * *
9883 // face 2: front plane
9884 // (note: x,y exchanged)
9885 // *---*---*
9886 // | 11 |
9887 // *-8-*-9-*
9888 // | 10 |
9889 // *---*---*
9890 // face 3: back plane
9891 // (note: x,y exchanged)
9892 // *---*---*
9893 // | 15 |
9894 // *12-*-13*
9895 // | 14 |
9896 // *---*---*
9897 // face 4: bottom plane
9898 // *---*---*
9899 // / 17 /
9900 // *18-*-19*
9901 // / 16 /
9902 // *---*---*
9903 // face 5: top plane
9904 // *---*---*
9905 // / 21 /
9906 // *22-*-23*
9907 // / 20 /
9908 // *---*---*
9909 // middle planes
9910 // *---*---* *---*---*
9911 // / 25 / | 29 |
9912 // *26-*-27* *26-*-27*
9913 // / 24 / | 28 |
9914 // *---*---* *---*---*
9915
9916 // set up a list of line iterators first. from
9917 // this, construct lists of line_indices and
9918 // line orientations later on
9919 const typename Triangulation<
9920 dim,
9921 spacedim>::raw_line_iterator lines[30] = {
9922 hex->face(0)
9923 ->isotropic_child(
9925 0, f_or[0], f_fl[0], f_ro[0]))
9926 ->line(
9928 1, f_or[0], f_fl[0], f_ro[0])), // 0
9929 hex->face(0)
9930 ->isotropic_child(
9932 3, f_or[0], f_fl[0], f_ro[0]))
9933 ->line(
9935 0, f_or[0], f_fl[0], f_ro[0])), // 1
9936 hex->face(0)
9937 ->isotropic_child(
9939 0, f_or[0], f_fl[0], f_ro[0]))
9940 ->line(
9942 3, f_or[0], f_fl[0], f_ro[0])), // 2
9943 hex->face(0)
9944 ->isotropic_child(
9946 3, f_or[0], f_fl[0], f_ro[0]))
9947 ->line(
9949 2, f_or[0], f_fl[0], f_ro[0])), // 3
9950
9951 hex->face(1)
9952 ->isotropic_child(
9954 0, f_or[1], f_fl[1], f_ro[1]))
9955 ->line(
9957 1, f_or[1], f_fl[1], f_ro[1])), // 4
9958 hex->face(1)
9959 ->isotropic_child(
9961 3, f_or[1], f_fl[1], f_ro[1]))
9962 ->line(
9964 0, f_or[1], f_fl[1], f_ro[1])), // 5
9965 hex->face(1)
9966 ->isotropic_child(
9968 0, f_or[1], f_fl[1], f_ro[1]))
9969 ->line(
9971 3, f_or[1], f_fl[1], f_ro[1])), // 6
9972 hex->face(1)
9973 ->isotropic_child(
9975 3, f_or[1], f_fl[1], f_ro[1]))
9976 ->line(
9978 2, f_or[1], f_fl[1], f_ro[1])), // 7
9979
9980 hex->face(2)
9981 ->isotropic_child(
9983 0, f_or[2], f_fl[2], f_ro[2]))
9984 ->line(
9986 1, f_or[2], f_fl[2], f_ro[2])), // 8
9987 hex->face(2)
9988 ->isotropic_child(
9990 3, f_or[2], f_fl[2], f_ro[2]))
9991 ->line(
9993 0, f_or[2], f_fl[2], f_ro[2])), // 9
9994 hex->face(2)
9995 ->isotropic_child(
9997 0, f_or[2], f_fl[2], f_ro[2]))
9998 ->line(
10000 3, f_or[2], f_fl[2], f_ro[2])), // 10
10001 hex->face(2)
10002 ->isotropic_child(
10004 3, f_or[2], f_fl[2], f_ro[2]))
10005 ->line(
10007 2, f_or[2], f_fl[2], f_ro[2])), // 11
10008
10009 hex->face(3)
10010 ->isotropic_child(
10012 0, f_or[3], f_fl[3], f_ro[3]))
10013 ->line(
10015 1, f_or[3], f_fl[3], f_ro[3])), // 12
10016 hex->face(3)
10017 ->isotropic_child(
10019 3, f_or[3], f_fl[3], f_ro[3]))
10020 ->line(
10022 0, f_or[3], f_fl[3], f_ro[3])), // 13
10023 hex->face(3)
10024 ->isotropic_child(
10026 0, f_or[3], f_fl[3], f_ro[3]))
10027 ->line(
10029 3, f_or[3], f_fl[3], f_ro[3])), // 14
10030 hex->face(3)
10031 ->isotropic_child(
10033 3, f_or[3], f_fl[3], f_ro[3]))
10034 ->line(
10036 2, f_or[3], f_fl[3], f_ro[3])), // 15
10037
10038 hex->face(4)
10039 ->isotropic_child(
10041 0, f_or[4], f_fl[4], f_ro[4]))
10042 ->line(
10044 1, f_or[4], f_fl[4], f_ro[4])), // 16
10045 hex->face(4)
10046 ->isotropic_child(
10048 3, f_or[4], f_fl[4], f_ro[4]))
10049 ->line(
10051 0, f_or[4], f_fl[4], f_ro[4])), // 17
10052 hex->face(4)
10053 ->isotropic_child(
10055 0, f_or[4], f_fl[4], f_ro[4]))
10056 ->line(
10058 3, f_or[4], f_fl[4], f_ro[4])), // 18
10059 hex->face(4)
10060 ->isotropic_child(
10062 3, f_or[4], f_fl[4], f_ro[4]))
10063 ->line(
10065 2, f_or[4], f_fl[4], f_ro[4])), // 19
10066
10067 hex->face(5)
10068 ->isotropic_child(
10070 0, f_or[5], f_fl[5], f_ro[5]))
10071 ->line(
10073 1, f_or[5], f_fl[5], f_ro[5])), // 20
10074 hex->face(5)
10075 ->isotropic_child(
10077 3, f_or[5], f_fl[5], f_ro[5]))
10078 ->line(
10080 0, f_or[5], f_fl[5], f_ro[5])), // 21
10081 hex->face(5)
10082 ->isotropic_child(
10084 0, f_or[5], f_fl[5], f_ro[5]))
10085 ->line(
10087 3, f_or[5], f_fl[5], f_ro[5])), // 22
10088 hex->face(5)
10089 ->isotropic_child(
10091 3, f_or[5], f_fl[5], f_ro[5]))
10092 ->line(
10094 2, f_or[5], f_fl[5], f_ro[5])), // 23
10095
10096 new_lines[0], // 24
10097 new_lines[1], // 25
10098 new_lines[2], // 26
10099 new_lines[3], // 27
10100 new_lines[4], // 28
10101 new_lines[5] // 29
10102 };
10103
10104 unsigned int line_indices[30];
10105 for (unsigned int i = 0; i < 30; ++i)
10106 line_indices[i] = lines[i]->index();
10107
10108 // the orientation of lines for the inner quads
10109 // is quite tricky. as these lines are newly
10110 // created ones and thus have no parents, they
10111 // cannot inherit this property. set up an array
10112 // and fill it with the respective values
10113 bool line_orientation[30];
10114
10115 // note: for the first 24 lines (inner lines of
10116 // the outer quads) the following holds: the
10117 // second vertex of the even lines in standard
10118 // orientation is the vertex in the middle of
10119 // the quad, whereas for odd lines the first
10120 // vertex is the same middle vertex.
10121 for (unsigned int i = 0; i < 24; ++i)
10122 if (lines[i]->vertex_index((i + 1) % 2) ==
10123 vertex_indices[i / 4])
10124 line_orientation[i] = true;
10125 else
10126 {
10127 // it must be the other way
10128 // round then
10129 Assert(lines[i]->vertex_index(i % 2) ==
10130 vertex_indices[i / 4],
10132 line_orientation[i] = false;
10133 }
10134 // for the last 6 lines the line orientation is
10135 // always true, since they were just constructed
10136 // that way
10137 for (unsigned int i = 24; i < 30; ++i)
10138 line_orientation[i] = true;
10139
10140 // set up the 12 quads, numbered as follows
10141 // (left quad numbering, right line numbering
10142 // extracted from above)
10143 //
10144 // * *
10145 // /| 21|
10146 // * | * 15
10147 // y/|3* 20| *
10148 // * |/| * |/|
10149 // |2* |x 11 * 14
10150 // |/|1* |/| *
10151 // * |/ * |17
10152 // |0* 10 *
10153 // |/ |16
10154 // * *
10155 //
10156 // x
10157 // *---*---* *22-*-23*
10158 // | 5 | 7 | 1 29 5
10159 // *---*---* *26-*-27*
10160 // | 4 | 6 | 0 28 4
10161 // *---*---*y *18-*-19*
10162 //
10163 // y
10164 // *----*----* *-12-*-13-*
10165 // / 10 / 11 / 3 25 7
10166 // *----*----* *-26-*-27-*
10167 // / 8 / 9 / 2 24 6
10168 // *----*----*x *--8-*--9-*
10169
10170 new_quads[0]->set_bounding_object_indices(
10171 {line_indices[10],
10172 line_indices[28],
10173 line_indices[16],
10174 line_indices[24]});
10175 new_quads[1]->set_bounding_object_indices(
10176 {line_indices[28],
10177 line_indices[14],
10178 line_indices[17],
10179 line_indices[25]});
10180 new_quads[2]->set_bounding_object_indices(
10181 {line_indices[11],
10182 line_indices[29],
10183 line_indices[24],
10184 line_indices[20]});
10185 new_quads[3]->set_bounding_object_indices(
10186 {line_indices[29],
10187 line_indices[15],
10188 line_indices[25],
10189 line_indices[21]});
10190 new_quads[4]->set_bounding_object_indices(
10191 {line_indices[18],
10192 line_indices[26],
10193 line_indices[0],
10194 line_indices[28]});
10195 new_quads[5]->set_bounding_object_indices(
10196 {line_indices[26],
10197 line_indices[22],
10198 line_indices[1],
10199 line_indices[29]});
10200 new_quads[6]->set_bounding_object_indices(
10201 {line_indices[19],
10202 line_indices[27],
10203 line_indices[28],
10204 line_indices[4]});
10205 new_quads[7]->set_bounding_object_indices(
10206 {line_indices[27],
10207 line_indices[23],
10208 line_indices[29],
10209 line_indices[5]});
10210 new_quads[8]->set_bounding_object_indices(
10211 {line_indices[2],
10212 line_indices[24],
10213 line_indices[8],
10214 line_indices[26]});
10215 new_quads[9]->set_bounding_object_indices(
10216 {line_indices[24],
10217 line_indices[6],
10218 line_indices[9],
10219 line_indices[27]});
10220 new_quads[10]->set_bounding_object_indices(
10221 {line_indices[3],
10222 line_indices[25],
10223 line_indices[26],
10224 line_indices[12]});
10225 new_quads[11]->set_bounding_object_indices(
10226 {line_indices[25],
10227 line_indices[7],
10228 line_indices[27],
10229 line_indices[13]});
10230
10231 // now reset the line_orientation flags of outer
10232 // lines as they cannot be set in a loop (at
10233 // least not easily)
10234 new_quads[0]->set_line_orientation(
10235 0, line_orientation[10]);
10236 new_quads[0]->set_line_orientation(
10237 2, line_orientation[16]);
10238
10239 new_quads[1]->set_line_orientation(
10240 1, line_orientation[14]);
10241 new_quads[1]->set_line_orientation(
10242 2, line_orientation[17]);
10243
10244 new_quads[2]->set_line_orientation(
10245 0, line_orientation[11]);
10246 new_quads[2]->set_line_orientation(
10247 3, line_orientation[20]);
10248
10249 new_quads[3]->set_line_orientation(
10250 1, line_orientation[15]);
10251 new_quads[3]->set_line_orientation(
10252 3, line_orientation[21]);
10253
10254 new_quads[4]->set_line_orientation(
10255 0, line_orientation[18]);
10256 new_quads[4]->set_line_orientation(
10257 2, line_orientation[0]);
10258
10259 new_quads[5]->set_line_orientation(
10260 1, line_orientation[22]);
10261 new_quads[5]->set_line_orientation(
10262 2, line_orientation[1]);
10263
10264 new_quads[6]->set_line_orientation(
10265 0, line_orientation[19]);
10266 new_quads[6]->set_line_orientation(
10267 3, line_orientation[4]);
10268
10269 new_quads[7]->set_line_orientation(
10270 1, line_orientation[23]);
10271 new_quads[7]->set_line_orientation(
10272 3, line_orientation[5]);
10273
10274 new_quads[8]->set_line_orientation(
10275 0, line_orientation[2]);
10276 new_quads[8]->set_line_orientation(
10277 2, line_orientation[8]);
10278
10279 new_quads[9]->set_line_orientation(
10280 1, line_orientation[6]);
10281 new_quads[9]->set_line_orientation(
10282 2, line_orientation[9]);
10283
10284 new_quads[10]->set_line_orientation(
10285 0, line_orientation[3]);
10286 new_quads[10]->set_line_orientation(
10287 3, line_orientation[12]);
10288
10289 new_quads[11]->set_line_orientation(
10290 1, line_orientation[7]);
10291 new_quads[11]->set_line_orientation(
10292 3, line_orientation[13]);
10293
10294 //-------------------------------
10295 // create the eight new hexes
10296 //
10297 // again first collect some data. here, we need
10298 // the indices of a whole lotta quads.
10299
10300 // the quads are numbered as follows:
10301 //
10302 // planes in the interior of the old hex:
10303 //
10304 // *
10305 // /|
10306 // * |
10307 // /|3* *---*---* *----*----*
10308 // * |/| | 5 | 7 | / 10 / 11 /
10309 // |2* | *---*---* *----*----*
10310 // |/|1* | 4 | 6 | / 8 / 9 /
10311 // * |/ *---*---*y *----*----*x
10312 // |0*
10313 // |/
10314 // *
10315 //
10316 // children of the faces
10317 // of the old hex
10318 // *-------* *-------*
10319 // /|25 27| /34 35/|
10320 // 15| | / /19
10321 // / | | /32 33/ |
10322 // * |24 26| *-------*18 |
10323 // 1413*-------* |21 23| 17*
10324 // | /30 31/ | | /
10325 // 12/ / | |16
10326 // |/28 29/ |20 22|/
10327 // *-------* *-------*
10328 //
10329 // note that we have to
10330 // take care of the
10331 // orientation of
10332 // faces.
10333 const int quad_indices[36] = {
10334 new_quads[0]->index(), // 0
10335 new_quads[1]->index(),
10336 new_quads[2]->index(),
10337 new_quads[3]->index(),
10338 new_quads[4]->index(),
10339 new_quads[5]->index(),
10340 new_quads[6]->index(),
10341 new_quads[7]->index(),
10342 new_quads[8]->index(),
10343 new_quads[9]->index(),
10344 new_quads[10]->index(),
10345 new_quads[11]->index(), // 11
10346
10347 hex->face(0)->isotropic_child_index(
10349 0, f_or[0], f_fl[0], f_ro[0])), // 12
10350 hex->face(0)->isotropic_child_index(
10352 1, f_or[0], f_fl[0], f_ro[0])),
10353 hex->face(0)->isotropic_child_index(
10355 2, f_or[0], f_fl[0], f_ro[0])),
10356 hex->face(0)->isotropic_child_index(
10358 3, f_or[0], f_fl[0], f_ro[0])),
10359
10360 hex->face(1)->isotropic_child_index(
10362 0, f_or[1], f_fl[1], f_ro[1])), // 16
10363 hex->face(1)->isotropic_child_index(
10365 1, f_or[1], f_fl[1], f_ro[1])),
10366 hex->face(1)->isotropic_child_index(
10368 2, f_or[1], f_fl[1], f_ro[1])),
10369 hex->face(1)->isotropic_child_index(
10371 3, f_or[1], f_fl[1], f_ro[1])),
10372
10373 hex->face(2)->isotropic_child_index(
10375 0, f_or[2], f_fl[2], f_ro[2])), // 20
10376 hex->face(2)->isotropic_child_index(
10378 1, f_or[2], f_fl[2], f_ro[2])),
10379 hex->face(2)->isotropic_child_index(
10381 2, f_or[2], f_fl[2], f_ro[2])),
10382 hex->face(2)->isotropic_child_index(
10384 3, f_or[2], f_fl[2], f_ro[2])),
10385
10386 hex->face(3)->isotropic_child_index(
10388 0, f_or[3], f_fl[3], f_ro[3])), // 24
10389 hex->face(3)->isotropic_child_index(
10391 1, f_or[3], f_fl[3], f_ro[3])),
10392 hex->face(3)->isotropic_child_index(
10394 2, f_or[3], f_fl[3], f_ro[3])),
10395 hex->face(3)->isotropic_child_index(
10397 3, f_or[3], f_fl[3], f_ro[3])),
10398
10399 hex->face(4)->isotropic_child_index(
10401 0, f_or[4], f_fl[4], f_ro[4])), // 28
10402 hex->face(4)->isotropic_child_index(
10404 1, f_or[4], f_fl[4], f_ro[4])),
10405 hex->face(4)->isotropic_child_index(
10407 2, f_or[4], f_fl[4], f_ro[4])),
10408 hex->face(4)->isotropic_child_index(
10410 3, f_or[4], f_fl[4], f_ro[4])),
10411
10412 hex->face(5)->isotropic_child_index(
10414 0, f_or[5], f_fl[5], f_ro[5])), // 32
10415 hex->face(5)->isotropic_child_index(
10417 1, f_or[5], f_fl[5], f_ro[5])),
10418 hex->face(5)->isotropic_child_index(
10420 2, f_or[5], f_fl[5], f_ro[5])),
10421 hex->face(5)->isotropic_child_index(
10423 3, f_or[5], f_fl[5], f_ro[5]))};
10424
10425 // bottom children
10426 new_hexes[0]->set_bounding_object_indices(
10427 {quad_indices[12],
10428 quad_indices[0],
10429 quad_indices[20],
10430 quad_indices[4],
10431 quad_indices[28],
10432 quad_indices[8]});
10433 new_hexes[1]->set_bounding_object_indices(
10434 {quad_indices[0],
10435 quad_indices[16],
10436 quad_indices[22],
10437 quad_indices[6],
10438 quad_indices[29],
10439 quad_indices[9]});
10440 new_hexes[2]->set_bounding_object_indices(
10441 {quad_indices[13],
10442 quad_indices[1],
10443 quad_indices[4],
10444 quad_indices[24],
10445 quad_indices[30],
10446 quad_indices[10]});
10447 new_hexes[3]->set_bounding_object_indices(
10448 {quad_indices[1],
10449 quad_indices[17],
10450 quad_indices[6],
10451 quad_indices[26],
10452 quad_indices[31],
10453 quad_indices[11]});
10454
10455 // top children
10456 new_hexes[4]->set_bounding_object_indices(
10457 {quad_indices[14],
10458 quad_indices[2],
10459 quad_indices[21],
10460 quad_indices[5],
10461 quad_indices[8],
10462 quad_indices[32]});
10463 new_hexes[5]->set_bounding_object_indices(
10464 {quad_indices[2],
10465 quad_indices[18],
10466 quad_indices[23],
10467 quad_indices[7],
10468 quad_indices[9],
10469 quad_indices[33]});
10470 new_hexes[6]->set_bounding_object_indices(
10471 {quad_indices[15],
10472 quad_indices[3],
10473 quad_indices[5],
10474 quad_indices[25],
10475 quad_indices[10],
10476 quad_indices[34]});
10477 new_hexes[7]->set_bounding_object_indices(
10478 {quad_indices[3],
10479 quad_indices[19],
10480 quad_indices[7],
10481 quad_indices[27],
10482 quad_indices[11],
10483 quad_indices[35]});
10484 break;
10485 }
10486 default:
10487 // all refinement cases have been treated, there
10488 // only remains
10489 // RefinementCase<dim>::no_refinement as
10490 // untreated enumeration value. However, in that
10491 // case we should have aborted much
10492 // earlier. thus we should never get here
10493 Assert(false, ExcInternalError());
10494 break;
10495 } // switch (ref_case)
10496
10497 // and set face orientation flags. note that new
10498 // faces in the interior of the mother cell always
10499 // have a correctly oriented face, but the ones on
10500 // the outer faces will inherit this flag
10501 //
10502 // the flag have been set to true for all faces
10503 // initially, now go the other way round and reset
10504 // faces that are at the boundary of the mother cube
10505 //
10506 // the same is true for the face_flip and
10507 // face_rotation flags. however, the latter two are
10508 // set to false by default as this is the standard
10509 // value
10510
10511 // loop over all faces and all (relevant) subfaces
10512 // of that in order to set the correct values for
10513 // face_orientation, face_flip and face_rotation,
10514 // which are inherited from the corresponding face
10515 // of the mother cube
10516 for (const unsigned int f : GeometryInfo<dim>::face_indices())
10517 for (unsigned int s = 0;
10520 ref_case, f)),
10521 1U);
10522 ++s)
10523 {
10524 const unsigned int current_child =
10526 ref_case,
10527 f,
10528 s,
10529 f_or[f],
10530 f_fl[f],
10531 f_ro[f],
10533 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
10534 new_hexes[current_child]->set_combined_face_orientation(
10535 f, f_co[f]);
10536 }
10537
10538 // now see if we have created cells that are
10539 // distorted and if so add them to our list
10540 if (check_for_distorted_cells &&
10541 has_distorted_children<dim, spacedim>(hex))
10542 cells_with_distorted_children.distorted_cells.push_back(
10543 hex);
10544
10545 // note that the refinement flag was already cleared
10546 // at the beginning of this loop
10547
10548 // inform all listeners that cell refinement is done
10549 triangulation.signals.post_refinement_on_cell(hex);
10550 }
10551 }
10552
10553 // clear user data on quads. we used some of this data to
10554 // indicate anisotropic refinemnt cases on faces. all data
10555 // should be cleared by now, but the information whether we
10556 // used indices or pointers is still present. reset it now to
10557 // enable the user to use whichever they like later on.
10558 triangulation.faces->quads.clear_user_data();
10559
10560 // return the list with distorted children
10561 return cells_with_distorted_children;
10562 }
10563
10564
10577 template <int spacedim>
10578 static void
10580 {}
10581
10582
10583
10584 template <int dim, int spacedim>
10585 static void
10588 {
10589 // If the codimension is one, we cannot perform this check
10590 // yet.
10591 if (spacedim > dim)
10592 return;
10593
10594 for (const auto &cell : triangulation.cell_iterators())
10595 if (cell->at_boundary() && cell->refine_flag_set() &&
10596 cell->refine_flag_set() !=
10598 {
10599 // The cell is at the boundary and it is flagged for
10600 // anisotropic refinement. Therefore, we have a closer
10601 // look
10602 const RefinementCase<dim> ref_case = cell->refine_flag_set();
10603 for (const unsigned int face_no :
10605 if (cell->face(face_no)->at_boundary())
10606 {
10607 // this is the critical face at the boundary.
10609 face_no) !=
10610 RefinementCase<dim - 1>::isotropic_refinement)
10611 {
10612 // up to now, we do not want to refine this
10613 // cell along the face under consideration
10614 // here.
10615 const typename Triangulation<dim,
10616 spacedim>::face_iterator
10617 face = cell->face(face_no);
10618 // the new point on the boundary would be this
10619 // one.
10620 const Point<spacedim> new_bound = face->center(true);
10621 // to check it, transform to the unit cell
10622 // with a linear mapping
10623 const Point<dim> new_unit =
10624 cell->reference_cell()
10625 .template get_default_linear_mapping<dim,
10626 spacedim>()
10627 .transform_real_to_unit_cell(cell, new_bound);
10628
10629 // Now, we have to calculate the distance from
10630 // the face in the unit cell.
10631
10632 // take the correct coordinate direction (0
10633 // for faces 0 and 1, 1 for faces 2 and 3, 2
10634 // for faces 4 and 5) and subtract the correct
10635 // boundary value of the face (0 for faces 0,
10636 // 2, and 4; 1 for faces 1, 3 and 5)
10637 const double dist =
10638 std::fabs(new_unit[face_no / 2] - face_no % 2);
10639
10640 // compare this with the empirical value
10641 // allowed. if it is too big, flag the face
10642 // for isotropic refinement
10643 const double allowed = 0.25;
10644
10645 if (dist > allowed)
10646 cell->flag_for_face_refinement(face_no);
10647 } // if flagged for anistropic refinement
10648 } // if (cell->face(face)->at_boundary())
10649 } // for all cells
10650 }
10651
10652
10665 template <int dim, int spacedim>
10666 static void
10668 {
10669 Assert(dim < 3,
10670 ExcMessage("Wrong function called -- there should "
10671 "be a specialization."));
10672 }
10673
10674
10675 template <int spacedim>
10676 static void
10679 {
10680 const unsigned int dim = 3;
10681 using raw_line_iterator =
10683
10684 // variable to store whether the mesh was changed in the
10685 // present loop and in the whole process
10686 bool mesh_changed = false;
10687
10688 do
10689 {
10690 mesh_changed = false;
10691
10692 // for this following, we need to know which cells are
10693 // going to be coarsened, if we had to make a
10694 // decision. the following function sets these flags:
10695 triangulation.fix_coarsen_flags();
10696
10697 // first clear flags on lines, since we need them to determine
10698 // which lines will be refined
10699 triangulation.clear_user_flags_line();
10700
10701 // flag those lines that are refined and will not be
10702 // coarsened and those that will be refined
10703 for (const auto &cell : triangulation.cell_iterators())
10704 if (cell->refine_flag_set())
10705 {
10706 const std::array<unsigned int, 12> line_indices =
10707 TriaAccessorImplementation::Implementation::
10708 get_line_indices_of_cell(*cell);
10709 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10711 cell->refine_flag_set(), l) ==
10713 {
10714 raw_line_iterator line(&triangulation,
10715 0,
10716 line_indices[l]);
10717 // flag a line, that will be refined
10718 line->set_user_flag();
10719 }
10720 }
10721 else if (cell->has_children() &&
10722 !cell->child(0)->coarsen_flag_set())
10723 {
10724 const std::array<unsigned int, 12> line_indices =
10725 TriaAccessorImplementation::Implementation::
10726 get_line_indices_of_cell(*cell);
10727 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10729 cell->refinement_case(), l) ==
10731 {
10732 raw_line_iterator line(&triangulation,
10733 0,
10734 line_indices[l]);
10735 // flag a line, that is refined and will stay so
10736 line->set_user_flag();
10737 }
10738 }
10739 else if (cell->has_children() &&
10740 cell->child(0)->coarsen_flag_set())
10741 cell->set_user_flag();
10742
10743
10744 // now check whether there are cells with lines that are
10745 // more than once refined or that will be more than once
10746 // refined. The first thing should never be the case, in
10747 // the second case we flag the cell for refinement
10749 cell = triangulation.last_active();
10750 cell != triangulation.end();
10751 --cell)
10752 {
10753 const std::array<unsigned int, 12> line_indices =
10754 TriaAccessorImplementation::Implementation::
10755 get_line_indices_of_cell(*cell);
10756 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10757 {
10758 raw_line_iterator line(&triangulation, 0, line_indices[l]);
10759 if (line->has_children())
10760 {
10761 // if this line is refined, its children should
10762 // not have further children
10763 //
10764 // however, if any of the children is flagged
10765 // for further refinement, we need to refine
10766 // this cell also (at least, if the cell is not
10767 // already flagged)
10768 bool offending_line_found = false;
10769
10770 for (unsigned int c = 0; c < 2; ++c)
10771 {
10772 Assert(line->child(c)->has_children() == false,
10774
10775 if (line->child(c)->user_flag_set() &&
10777 cell->refine_flag_set(), l) ==
10779 {
10780 // tag this cell for refinement
10781 cell->clear_coarsen_flag();
10782 // if anisotropic coarsening is allowed:
10783 // extend the refine_flag in the needed
10784 // direction, else set refine_flag
10785 // (isotropic)
10786 if (triangulation.smooth_grid &
10788 allow_anisotropic_smoothing)
10789 cell->flag_for_line_refinement(l);
10790 else
10791 cell->set_refine_flag();
10792
10793 for (unsigned int k = 0; k < cell->n_lines();
10794 ++k)
10796 cell->refine_flag_set(), l) ==
10798 // flag a line, that will be refined
10799 raw_line_iterator(&triangulation,
10800 0,
10801 line_indices[k])
10802 ->set_user_flag();
10803
10804 // note that we have changed the grid
10805 offending_line_found = true;
10806
10807 // it may save us several loop
10808 // iterations if we flag all lines of
10809 // this cell now (and not at the outset
10810 // of the next iteration) for refinement
10811 for (unsigned int k = 0; k < cell->n_lines();
10812 ++k)
10813 {
10814 const auto line =
10815 raw_line_iterator(&triangulation,
10816 0,
10817 line_indices[k]);
10818 if (!line->has_children() &&
10820 line_refinement_case(
10821 cell->refine_flag_set(), k) !=
10823 line->set_user_flag();
10824 }
10825
10826 break;
10827 }
10828 }
10829
10830 if (offending_line_found)
10831 {
10832 mesh_changed = true;
10833 break;
10834 }
10835 }
10836 }
10837 }
10838
10839
10840 // there is another thing here: if any of the lines will
10841 // be refined, then we may not coarsen the present cell
10842 // similarly, if any of the lines *is* already refined, we
10843 // may not coarsen the current cell. however, there's a
10844 // catch: if the line is refined, but the cell behind it
10845 // is going to be coarsened, then the situation
10846 // changes. if we forget this second condition, the
10847 // refine_and_coarsen_3d test will start to fail. note
10848 // that to know which cells are going to be coarsened, the
10849 // call for fix_coarsen_flags above is necessary
10851 triangulation.last();
10852 cell != triangulation.end();
10853 --cell)
10854 if (cell->user_flag_set())
10855 {
10856 const std::array<unsigned int, 12> line_indices =
10857 TriaAccessorImplementation::Implementation::
10858 get_line_indices_of_cell(*cell);
10859 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10860 {
10861 raw_line_iterator line(&triangulation,
10862 0,
10863 line_indices[l]);
10864 if (line->has_children() &&
10865 (line->child(0)->user_flag_set() ||
10866 line->child(1)->user_flag_set()))
10867 {
10868 for (unsigned int c = 0; c < cell->n_children(); ++c)
10869 cell->child(c)->clear_coarsen_flag();
10870 cell->clear_user_flag();
10871 for (unsigned int k = 0; k < cell->n_lines(); ++k)
10873 cell->refinement_case(), k) ==
10875 // flag a line, that is refined and will
10876 // stay so
10877 raw_line_iterator(&triangulation,
10878 0,
10879 line_indices[k])
10880 ->set_user_flag();
10881 mesh_changed = true;
10882 break;
10883 }
10884 }
10885 }
10886 }
10887 while (mesh_changed == true);
10888 }
10889
10890
10891
10898 template <int dim, int spacedim>
10899 static bool
10902 {
10903 // in 1d, coarsening is always allowed since we don't enforce
10904 // the 2:1 constraint there
10905 if (dim == 1)
10906 return true;
10907
10908 const RefinementCase<dim> ref_case = cell->refinement_case();
10909 for (const unsigned int n : GeometryInfo<dim>::face_indices())
10910 {
10911 // if the cell is not refined along that face, coarsening
10912 // will not change anything, so do nothing. the same
10913 // applies, if the face is at the boundary
10914 const RefinementCase<dim - 1> face_ref_case =
10915 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
10916 n);
10917
10918 const unsigned int n_subfaces =
10919 GeometryInfo<dim - 1>::n_children(face_ref_case);
10920
10921 if (n_subfaces == 0 || cell->at_boundary(n))
10922 continue;
10923 for (unsigned int c = 0; c < n_subfaces; ++c)
10924 {
10926 child = cell->child(
10928
10930 child_neighbor = child->neighbor(n);
10931 if (!child->neighbor_is_coarser(n))
10932 {
10933 // in 2d, if the child's neighbor is coarser, then it has
10934 // no children. however, in 3d it might be
10935 // otherwise. consider for example, that our face might be
10936 // refined with cut_x, but the neighbor is refined with
10937 // cut_xy at that face. then the neighbor pointers of the
10938 // children of our cell will point to the common neighbor
10939 // cell, not to its children. what we really want to know
10940 // in the following is, whether the neighbor cell is
10941 // refined twice with reference to our cell. that only
10942 // has to be asked, if the child's neighbor is not a
10943 // coarser one. we check whether some of the children on
10944 // the neighbor are not flagged for coarsening, in that
10945 // case we may not coarsen. it is enough to check the
10946 // first child because we have already fixed the coarsen
10947 // flags on finer levels
10948 if (child_neighbor->has_children() &&
10949 !(child_neighbor->child(0)->is_active() &&
10950 child_neighbor->child(0)->coarsen_flag_set()))
10951 return false;
10952
10953 // the same applies, if the neighbors children are not
10954 // refined but will be after refinement
10955 if (child_neighbor->refine_flag_set())
10956 return false;
10957 }
10958 }
10959 }
10960 return true;
10961 }
10962 };
10963
10964
10969 {
10970 template <int spacedim>
10971 static void
10973 {}
10974
10975 template <int dim, int spacedim>
10977 {
10978 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
10979 2 * triangulation.n_raw_faces(),
10980 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
10981
10982 const auto set_entry = [&](const auto &face_index, const auto &cell) {
10983 const std::pair<unsigned int, unsigned int> cell_pair = {
10984 cell->level(), cell->index()};
10985 unsigned int index;
10986
10987 if (adjacent_cells[2 * face_index].first ==
10989 adjacent_cells[2 * face_index].second ==
10991 {
10992 index = 2 * face_index + 0;
10993 }
10994 else
10995 {
10996 Assert(((adjacent_cells[2 * face_index + 1].first ==
10998 (adjacent_cells[2 * face_index + 1].second ==
11001 index = 2 * face_index + 1;
11002 }
11003
11004 adjacent_cells[index] = cell_pair;
11005 };
11006
11007 const auto get_entry =
11008 [&](const auto &face_index,
11009 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11010 auto test = adjacent_cells[2 * face_index];
11011
11012 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11013 cell->index()))
11014 test = adjacent_cells[2 * face_index + 1];
11015
11016 if ((test.first != numbers::invalid_unsigned_int) &&
11017 (test.second != numbers::invalid_unsigned_int))
11019 test.first,
11020 test.second);
11021 else
11023 };
11024
11025 for (const auto &cell : triangulation.cell_iterators())
11026 for (const auto &face : cell->face_iterators())
11027 {
11028 set_entry(face->index(), cell);
11029
11030 if (cell->is_active() && face->has_children())
11031 for (unsigned int c = 0; c < face->n_children(); ++c)
11032 set_entry(face->child(c)->index(), cell);
11033 }
11034
11035 for (const auto &cell : triangulation.cell_iterators())
11036 for (auto f : cell->face_indices())
11037 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11038 }
11039
11040 template <int dim, int spacedim>
11041 static void
11045 std::vector<unsigned int> & line_cell_count,
11046 std::vector<unsigned int> & quad_cell_count)
11047 {
11049 (void)triangulation;
11050 (void)cell;
11051 (void)line_cell_count;
11052 (void)quad_cell_count;
11053 }
11054
11055 template <int dim, int spacedim>
11058 const bool check_for_distorted_cells)
11059 {
11060 return Implementation::execute_refinement_isotropic(
11061 triangulation, check_for_distorted_cells);
11062 }
11063
11064 template <int dim, int spacedim>
11065 static void
11068 {
11069 // nothing to do since anisotropy is not supported
11070 (void)triangulation;
11071 }
11072
11073 template <int dim, int spacedim>
11074 static void
11077 {
11078 Implementation::prepare_refinement_dim_dependent(triangulation);
11079 }
11080
11081 template <int dim, int spacedim>
11082 static bool
11085 {
11087
11088 return false;
11089 }
11090 };
11091
11092
11093 template <int dim, int spacedim>
11096 {
11097 static const FlatManifold<dim, spacedim> flat_manifold;
11098 return flat_manifold;
11099 }
11100 } // namespace TriangulationImplementation
11101} // namespace internal
11102
11103
11104
11105template <int dim, int spacedim>
11108
11109
11110
11111template <int dim, int spacedim>
11114 const MeshSmoothing smooth_grid,
11115 const bool check_for_distorted_cells)
11116 : smooth_grid(smooth_grid)
11117 , anisotropic_refinement(false)
11118 , check_for_distorted_cells(check_for_distorted_cells)
11119{
11120 if (dim == 1)
11121 {
11122 vertex_to_boundary_id_map_1d =
11123 std::make_unique<std::map<unsigned int, types::boundary_id>>();
11124 vertex_to_manifold_id_map_1d =
11125 std::make_unique<std::map<unsigned int, types::manifold_id>>();
11126 }
11127
11128 // connect the any_change signal to the other top level signals
11129 signals.create.connect(signals.any_change);
11130 signals.post_refinement.connect(signals.any_change);
11131 signals.clear.connect(signals.any_change);
11132 signals.mesh_movement.connect(signals.any_change);
11133}
11134
11135
11136
11137template <int dim, int spacedim>
11141 : Subscriptor(std::move(tria))
11142 , smooth_grid(tria.smooth_grid)
11143 , reference_cells(std::move(tria.reference_cells))
11144 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
11145 , periodic_face_map(std::move(tria.periodic_face_map))
11146 , levels(std::move(tria.levels))
11147 , faces(std::move(tria.faces))
11148 , vertices(std::move(tria.vertices))
11149 , vertices_used(std::move(tria.vertices_used))
11150 , manifolds(std::move(tria.manifolds))
11151 , anisotropic_refinement(tria.anisotropic_refinement)
11152 , check_for_distorted_cells(tria.check_for_distorted_cells)
11153 , number_cache(std::move(tria.number_cache))
11154 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
11155 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
11156{
11158
11159 if (tria.policy)
11160 this->policy = tria.policy->clone();
11161}
11162
11163
11164template <int dim, int spacedim>
11168{
11169 Subscriptor::operator=(std::move(tria));
11170
11171 smooth_grid = tria.smooth_grid;
11172 reference_cells = std::move(tria.reference_cells);
11173 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
11174 periodic_face_map = std::move(tria.periodic_face_map);
11175 levels = std::move(tria.levels);
11176 faces = std::move(tria.faces);
11177 vertices = std::move(tria.vertices);
11178 vertices_used = std::move(tria.vertices_used);
11179 manifolds = std::move(tria.manifolds);
11180 anisotropic_refinement = tria.anisotropic_refinement;
11181 number_cache = tria.number_cache;
11182 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
11183 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
11184
11186
11187 if (tria.policy)
11188 this->policy = tria.policy->clone();
11189
11190 return *this;
11191}
11192
11193
11194
11195template <int dim, int spacedim>
11198{
11199 // notify listeners that the triangulation is going down...
11200 try
11201 {
11202 signals.clear();
11203 }
11204 catch (...)
11205 {}
11206
11207 levels.clear();
11208
11209 // the vertex_to_boundary_id_map_1d field should be unused except in
11210 // 1d. double check this here, as destruction is a good place to
11211 // ensure that what we've done over the course of the lifetime of
11212 // this object makes sense
11213 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
11215
11216 // the vertex_to_manifold_id_map_1d field should be also unused
11217 // except in 1d. check this as well
11218 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
11220}
11221
11222
11223
11224template <int dim, int spacedim>
11227{
11228 // notify listeners that the triangulation is going down...
11229 signals.clear();
11230
11231 // ...and then actually clear all content of it
11232 clear_despite_subscriptions();
11233 periodic_face_pairs_level_0.clear();
11234 periodic_face_map.clear();
11235 reference_cells.clear();
11236}
11237
11238
11239template <int dim, int spacedim>
11242{
11243 return MPI_COMM_SELF;
11244}
11245
11246
11247
11248template <int dim, int spacedim>
11250const std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<
11251 dim,
11252 spacedim>::global_active_cell_index_partitioner() const
11253{
11254 return number_cache.active_cell_index_partitioner;
11255}
11256
11257
11258
11259template <int dim, int spacedim>
11261const std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<
11262 dim,
11263 spacedim>::global_level_cell_index_partitioner(const unsigned int level) const
11264{
11265 AssertIndexRange(level, this->n_levels());
11266
11267 return number_cache.level_cell_index_partitioners[level];
11268}
11269
11270
11271
11272template <int dim, int spacedim>
11275 const MeshSmoothing mesh_smoothing)
11276{
11277 Assert(n_levels() == 0,
11278 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11279 smooth_grid = mesh_smoothing;
11280}
11281
11282
11283
11284template <int dim, int spacedim>
11288{
11289 return smooth_grid;
11290}
11291
11292
11293
11294template <int dim, int spacedim>
11297 const types::manifold_id m_number,
11298 const Manifold<dim, spacedim> &manifold_object)
11299{
11301
11302 manifolds[m_number] = manifold_object.clone();
11303}
11304
11305
11306
11307template <int dim, int spacedim>
11310 const types::manifold_id m_number)
11311{
11313
11314 // delete the entry located at number.
11315 manifolds.erase(m_number);
11316}
11317
11318
11319template <int dim, int spacedim>
11322{
11323 manifolds.clear();
11324}
11325
11326
11327template <int dim, int spacedim>
11330 const types::manifold_id m_number)
11331{
11332 Assert(
11333 n_cells() > 0,
11334 ExcMessage(
11335 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
11336
11337 for (const auto &cell : this->active_cell_iterators())
11338 cell->set_all_manifold_ids(m_number);
11339}
11340
11341
11342template <int dim, int spacedim>
11345 const types::manifold_id m_number)
11346{
11347 Assert(
11348 n_cells() > 0,
11349 ExcMessage(
11350 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
11351
11352 for (const auto &cell : this->active_cell_iterators())
11353 for (auto f : GeometryInfo<dim>::face_indices())
11354 if (cell->face(f)->at_boundary())
11355 cell->face(f)->set_all_manifold_ids(m_number);
11356}
11357
11358
11359template <int dim, int spacedim>
11362 const types::boundary_id b_id,
11363 const types::manifold_id m_number)
11364{
11365 Assert(
11366 n_cells() > 0,
11367 ExcMessage(
11368 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
11369
11370 bool boundary_found = false;
11371
11372 for (const auto &cell : this->active_cell_iterators())
11373 {
11374 // loop on faces
11375 for (auto f : GeometryInfo<dim>::face_indices())
11376 if (cell->face(f)->at_boundary() &&
11377 cell->face(f)->boundary_id() == b_id)
11378 {
11379 boundary_found = true;
11380 cell->face(f)->set_manifold_id(m_number);
11381 }
11382
11383 // loop on edges if dim >= 3
11384 if (dim >= 3)
11385 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
11386 if (cell->line(e)->at_boundary() &&
11387 cell->line(e)->boundary_id() == b_id)
11388 {
11389 boundary_found = true;
11390 cell->line(e)->set_manifold_id(m_number);
11391 }
11392 }
11393
11394 (void)boundary_found;
11395 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
11396}
11397
11398
11399
11400template <int dim, int spacedim>
11403 const types::manifold_id m_number) const
11404{
11405 // look, if there is a manifold stored at
11406 // manifold_id number.
11407 const auto it = manifolds.find(m_number);
11408
11409 if (it != manifolds.end())
11410 {
11411 // if we have found an entry, return it
11412 return *(it->second);
11413 }
11414
11415 // if we have not found an entry connected with number, we return
11416 // the default (flat) manifold
11417 return internal::TriangulationImplementation::
11418 get_default_flat_manifold<dim, spacedim>();
11419}
11420
11421
11422
11423template <int dim, int spacedim>
11425std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
11426 const
11427{
11428 // in 1d, we store a map of all used boundary indicators. use it for
11429 // our purposes
11430 if (dim == 1)
11431 {
11432 std::vector<types::boundary_id> boundary_ids;
11433 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
11434 vertex_to_boundary_id_map_1d->begin();
11435 p != vertex_to_boundary_id_map_1d->end();
11436 ++p)
11437 boundary_ids.push_back(p->second);
11438
11439 return boundary_ids;
11440 }
11441 else
11442 {
11443 std::set<types::boundary_id> b_ids;
11444 for (auto cell : active_cell_iterators())
11445 if (cell->is_locally_owned())
11446 for (const unsigned int face : cell->face_indices())
11447 if (cell->at_boundary(face))
11448 b_ids.insert(cell->face(face)->boundary_id());
11449 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
11450 return boundary_ids;
11451 }
11452}
11453
11454
11455
11456template <int dim, int spacedim>
11458std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
11459 const
11460{
11461 std::set<types::manifold_id> m_ids;
11462 for (const auto &cell : active_cell_iterators())
11463 if (cell->is_locally_owned())
11464 {
11465 m_ids.insert(cell->manifold_id());
11466 for (const auto &face : cell->face_iterators())
11467 m_ids.insert(face->manifold_id());
11468 if (dim == 3)
11469 {
11470 const auto line_indices = internal::TriaAccessorImplementation::
11471 Implementation::get_line_indices_of_cell(*cell);
11472 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11473 {
11474 raw_line_iterator line(this, 0, line_indices[l]);
11475 m_ids.insert(line->manifold_id());
11476 }
11477 }
11478 }
11479 return {m_ids.begin(), m_ids.end()};
11480}
11481
11482/*-----------------------------------------------------------------*/
11483
11484
11485template <int dim, int spacedim>
11488 const Triangulation<dim, spacedim> &other_tria)
11489{
11490 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
11491 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11492 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
11493 (dim == 1 || other_tria.faces != nullptr),
11494 ExcMessage(
11495 "When calling Triangulation::copy_triangulation(), "
11496 "the target triangulation must be empty but the source "
11497 "triangulation (the argument to this function) must contain "
11498 "something. Here, it seems like the source does not "
11499 "contain anything at all."));
11500
11501
11502 // copy normal elements
11503 vertices = other_tria.vertices;
11504 vertices_used = other_tria.vertices_used;
11505 anisotropic_refinement = other_tria.anisotropic_refinement;
11506 smooth_grid = other_tria.smooth_grid;
11507 reference_cells = other_tria.reference_cells;
11508
11509 if (dim > 1)
11510 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
11511 *other_tria.faces);
11512
11513 for (const auto &p : other_tria.manifolds)
11514 set_manifold(p.first, *p.second);
11515
11516
11517 levels.reserve(other_tria.levels.size());
11518 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
11519 levels.push_back(
11520 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
11521 *other_tria.levels[level]));
11522
11523 number_cache = other_tria.number_cache;
11524
11525 if (dim == 1)
11526 {
11527 vertex_to_boundary_id_map_1d =
11528 std::make_unique<std::map<unsigned int, types::boundary_id>>(
11529 *other_tria.vertex_to_boundary_id_map_1d);
11530
11531 vertex_to_manifold_id_map_1d =
11532 std::make_unique<std::map<unsigned int, types::manifold_id>>(
11533 *other_tria.vertex_to_manifold_id_map_1d);
11534 }
11535
11536 if (other_tria.policy)
11537 this->policy = other_tria.policy->clone();
11538
11539 // inform those who are listening on other_tria of the copy operation
11540 other_tria.signals.copy(*this);
11541 // also inform all listeners of the current triangulation that the
11542 // triangulation has been created
11543 signals.create();
11544
11545 // note that we need not copy the
11546 // subscriptor!
11547}
11548
11549
11550
11551template <int dim, int spacedim>
11554 const std::vector<Point<spacedim>> &v,
11555 const std::vector<CellData<dim>> & cells,
11556 const SubCellData & subcelldata)
11557{
11558 std::vector<CellData<dim>> reordered_cells(cells); // NOLINT
11559 SubCellData reordered_subcelldata(subcelldata); // NOLINT
11560
11561 // in-place reordering of data
11562 reorder_compatibility(reordered_cells, reordered_subcelldata);
11563
11564 // now create triangulation from
11565 // reordered data
11566 create_triangulation(v, reordered_cells, reordered_subcelldata);
11567}
11568
11569
11570template <int dim, int spacedim>
11573{
11574 this->update_reference_cells();
11575
11576 if (this->all_reference_cells_are_hyper_cube())
11577 {
11578 this->policy =
11580 dim,
11581 spacedim,
11583 }
11584 else
11585 {
11586 this->policy =
11588 dim,
11589 spacedim,
11591 }
11592}
11593
11594
11595
11596template <int dim, int spacedim>
11599 const std::vector<Point<spacedim>> &v,
11600 const std::vector<CellData<dim>> & cells,
11601 const SubCellData & subcelldata)
11602{
11603 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
11604 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11605 // check that no forbidden arrays
11606 // are used
11607 Assert(subcelldata.check_consistency(dim), ExcInternalError());
11608
11609 // try to create a triangulation; if this fails, we still want to
11610 // throw an exception but if we just do so we'll get into trouble
11611 // because sometimes other objects are already attached to it:
11612 try
11613 {
11615 create_triangulation(v, cells, subcelldata, *this);
11616 }
11617 catch (...)
11618 {
11619 clear_despite_subscriptions();
11620 throw;
11621 }
11622
11623 reset_policy();
11624
11625 // update our counts of the various elements of a triangulation, and set
11626 // active_cell_indices of all cells
11627 reset_cell_vertex_indices_cache();
11629 *this, levels.size(), number_cache);
11630 reset_active_cell_indices();
11631 reset_global_cell_indices();
11632
11633 // now verify that there are indeed no distorted cells. as per the
11634 // documentation of this class, we first collect all distorted cells
11635 // and then throw an exception if there are any
11636 if (check_for_distorted_cells)
11637 {
11638 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
11639 // throw the array (and fill the various location fields) if
11640 // there are distorted cells. otherwise, just fall off the end
11641 // of the function
11642 AssertThrow(distorted_cells.distorted_cells.size() == 0, distorted_cells);
11643 }
11644
11645
11646 /*
11647 When the triangulation is a manifold (dim < spacedim) and made of
11648 quadrilaterals, the normal field provided from the map class depends on
11649 the order of the vertices. It may happen that this normal field is
11650 discontinuous. The following code takes care that this is not the case by
11651 setting the cell direction flag on those cell that produce the wrong
11652 orientation.
11653
11654 To determine if 2 neighbors have the same or opposite orientation we use
11655 a table of truth. Its entries are indexes by the local indices of the
11656 common face. For example if two elements share a face, and this face is
11657 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
11658 whether the orientation are the same (true) or opposite (false).
11659
11660 Even though there may be a combinatorial/graph theory argument to get this
11661 table in any dimension, I tested by hand all the different possible cases
11662 in 1D and 2D to generate the table.
11663
11664 Assuming that a surface respects the standard orientation for 2d meshes,
11665 the tables of truth are symmetric and their true values are the following
11666
11667 - 1D curves: (0,1)
11668 - 2D surface: (0,1),(0,2),(1,3),(2,3)
11669
11670 We store this data using an n_faces x n_faces full matrix, which is
11671 actually much bigger than the minimal data required, but it makes the code
11672 more readable.
11673
11674 */
11675 if (dim < spacedim && all_reference_cells_are_hyper_cube())
11676 {
11679 switch (dim)
11680 {
11681 case 1:
11682 {
11683 bool values[][2] = {{false, true}, {true, false}};
11684 for (const unsigned int i : GeometryInfo<dim>::face_indices())
11685 for (const unsigned int j : GeometryInfo<dim>::face_indices())
11686 correct(i, j) = (values[i][j]);
11687 break;
11688 }
11689 case 2:
11690 {
11691 bool values[][4] = {{false, true, true, false},
11692 {true, false, false, true},
11693 {true, false, false, true},
11694 {false, true, true, false}};
11695 for (const unsigned int i : GeometryInfo<dim>::face_indices())
11696 for (const unsigned int j : GeometryInfo<dim>::face_indices())
11697 correct(i, j) = (values[i][j]);
11698 break;
11699 }
11700 default:
11701 Assert(false, ExcNotImplemented());
11702 }
11703
11704
11705 std::list<active_cell_iterator> this_round, next_round;
11706 active_cell_iterator neighbor;
11707
11708 this_round.push_back(begin_active());
11709 begin_active()->set_direction_flag(true);
11710 begin_active()->set_user_flag();
11711
11712 while (this_round.size() > 0)
11713 {
11714 for (typename std::list<active_cell_iterator>::iterator cell =
11715 this_round.begin();
11716 cell != this_round.end();
11717 ++cell)
11718 {
11719 for (const unsigned int i : (*cell)->face_indices())
11720 {
11721 if (!((*cell)->face(i)->at_boundary()))
11722 {
11723 neighbor = (*cell)->neighbor(i);
11724
11725 unsigned int cf = (*cell)->face_index(i);
11726 unsigned int j = 0;
11727 while (neighbor->face_index(j) != cf)
11728 {
11729 ++j;
11730 }
11731
11732
11733 // If we already saw this guy, check that everything is
11734 // fine
11735 if (neighbor->user_flag_set())
11736 {
11737 // If we have visited this guy, then the ordering and
11738 // the orientation should agree
11739 Assert(!(correct(i, j) ^
11740 (neighbor->direction_flag() ==
11741 (*cell)->direction_flag())),
11742 ExcNonOrientableTriangulation());
11743 }
11744 else
11745 {
11746 next_round.push_back(neighbor);
11747 neighbor->set_user_flag();
11748 if ((correct(i, j) ^ (neighbor->direction_flag() ==
11749 (*cell)->direction_flag())))
11750 neighbor->set_direction_flag(
11751 !neighbor->direction_flag());
11752 }
11753 }
11754 }
11755 }
11756
11757 // Before we quit let's check that if the triangulation is
11758 // disconnected that we still get all cells
11759 if (next_round.size() == 0)
11760 for (const auto &cell : this->active_cell_iterators())
11761 if (cell->user_flag_set() == false)
11762 {
11763 next_round.push_back(cell);
11764 cell->set_direction_flag(true);
11765 cell->set_user_flag();
11766 break;
11767 }
11768
11769 this_round = next_round;
11770 next_round.clear();
11771 }
11772 clear_user_flags();
11773 }
11774
11775 // inform all listeners that the triangulation has been created
11776 signals.create();
11777}
11778
11779
11780
11781template <int dim, int spacedim>
11785{
11786 // 1) create coarse grid
11788 construction_data.coarse_cells,
11789 SubCellData());
11790
11791 // create a copy of cell_infos such that we can sort them
11792 auto cell_infos = construction_data.cell_infos;
11793
11794 // sort cell_infos on each level separately
11795 for (auto &cell_info : cell_infos)
11796 std::sort(
11797 cell_info.begin(),
11798 cell_info.end(),
11801 const CellId a_id(a.id);
11802 const CellId b_id(b.id);
11803
11804 const auto a_coarse_cell_index =
11805 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
11806 const auto b_coarse_cell_index =
11807 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
11808
11809 // according to their coarse-cell index and if that is
11810 // same according to their cell id (the result is that
11811 // cells on each level are sorted according to their
11812 // index on that level - what we need in the following
11813 // operations)
11814 if (a_coarse_cell_index != b_coarse_cell_index)
11815 return a_coarse_cell_index < b_coarse_cell_index;
11816 else
11817 return a_id < b_id;
11818 });
11819
11820 // 2) create all levels via a sequence of refinements. note that
11821 // we must make sure that we actually have cells on this level,
11822 // which is not clear in a parallel context for some processes
11823 for (unsigned int level = 0;
11824 level < cell_infos.size() && !cell_infos[level].empty();
11825 ++level)
11826 {
11827 // a) set manifold ids here (because new vertices have to be
11828 // positioned correctly during each refinement step)
11829 {
11830 auto cell = this->begin(level);
11831 auto cell_info = cell_infos[level].begin();
11832 for (; cell_info != cell_infos[level].end(); ++cell_info)
11833 {
11834 while (cell_info->id != cell->id().template to_binary<dim>())
11835 ++cell;
11836 if (dim == 2)
11837 for (const auto face : cell->face_indices())
11838 cell->face(face)->set_manifold_id(
11839 cell_info->manifold_line_ids[face]);
11840 else if (dim == 3)
11841 {
11842 for (const auto face : cell->face_indices())
11843 cell->face(face)->set_manifold_id(
11844 cell_info->manifold_quad_ids[face]);
11845
11846 const auto line_indices = internal::TriaAccessorImplementation::
11847 Implementation::get_line_indices_of_cell(*cell);
11848 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11849 {
11850 raw_line_iterator line(this, 0, line_indices[l]);
11851 line->set_manifold_id(cell_info->manifold_line_ids[l]);
11852 }
11853 }
11854
11855 cell->set_manifold_id(cell_info->manifold_id);
11856 }
11857 }
11858
11859 // b) perform refinement on all levels but on the finest
11860 if (level + 1 != cell_infos.size())
11861 {
11862 // find cells that should have children and mark them for
11863 // refinement
11864 auto coarse_cell = this->begin(level);
11865 auto fine_cell_info = cell_infos[level + 1].begin();
11866
11867 // loop over all cells on the next level
11868 for (; fine_cell_info != cell_infos[level + 1].end();
11869 ++fine_cell_info)
11870 {
11871 // find the parent of that cell
11872 while (
11873 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
11874 ++coarse_cell;
11875
11876 // set parent for refinement
11877 coarse_cell->set_refine_flag();
11878 }
11879
11880 // execute refinement
11881 ::Triangulation<dim,
11882 spacedim>::execute_coarsening_and_refinement();
11883 }
11884 }
11885
11886 // 3) set boundary ids
11887 for (unsigned int level = 0;
11888 level < cell_infos.size() && !cell_infos[level].empty();
11889 ++level)
11890 {
11891 auto cell = this->begin(level);
11892 auto cell_info = cell_infos[level].begin();
11893 for (; cell_info != cell_infos[level].end(); ++cell_info)
11894 {
11895 // find cell that has the correct cell
11896 while (cell_info->id != cell->id().template to_binary<dim>())
11897 ++cell;
11898
11899 // boundary ids
11900 for (auto pair : cell_info->boundary_ids)
11901 if (cell->face(pair.first)->at_boundary())
11902 cell->face(pair.first)->set_boundary_id(pair.second);
11903 }
11904 }
11905
11906 // inform all listeners that the triangulation has been created
11907 signals.create();
11908}
11909
11910
11911template <int dim, int spacedim>
11914{
11915 AssertThrow(dim + 1 == spacedim,
11916 ExcMessage("Only works for dim == spacedim-1"));
11917 for (const auto &cell : this->active_cell_iterators())
11918 cell->set_direction_flag(!cell->direction_flag());
11919}
11920
11921
11922
11923template <int dim, int spacedim>
11926{
11927 Assert(n_cells() > 0,
11928 ExcMessage("Error: An empty Triangulation can not be refined."));
11929
11930 for (const auto &cell : this->active_cell_iterators())
11931 {
11932 cell->clear_coarsen_flag();
11933 cell->set_refine_flag();
11934 }
11935}
11936
11937
11938
11939template <int dim, int spacedim>
11941void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
11942{
11943 for (unsigned int i = 0; i < times; ++i)
11944 {
11945 set_all_refine_flags();
11946 execute_coarsening_and_refinement();
11947 }
11948}
11949
11950
11951
11952template <int dim, int spacedim>
11954void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
11955{
11956 for (unsigned int i = 0; i < times; ++i)
11957 {
11958 for (const auto &cell : this->active_cell_iterators())
11959 {
11960 cell->clear_refine_flag();
11961 cell->set_coarsen_flag();
11962 }
11963 execute_coarsening_and_refinement();
11964 }
11965}
11966
11967
11968/*-------------------- refine/coarsen flags -------------------------*/
11969
11970
11971
11972template <int dim, int spacedim>
11974void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
11975{
11976 v.resize(dim * n_active_cells(), false);
11977 std::vector<bool>::iterator i = v.begin();
11978
11979 for (const auto &cell : this->active_cell_iterators())
11980 for (unsigned int j = 0; j < dim; ++j, ++i)
11981 if (cell->refine_flag_set() & (1 << j))
11982 *i = true;
11983
11984 Assert(i == v.end(), ExcInternalError());
11985}
11986
11987
11988
11989template <int dim, int spacedim>
11991void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
11992{
11993 std::vector<bool> v;
11994 save_refine_flags(v);
11995 write_bool_vector(mn_tria_refine_flags_begin,
11996 v,
11998 out);
11999}
12000
12001
12002
12003template <int dim, int spacedim>
12006{
12007 std::vector<bool> v;
12008 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12009 load_refine_flags(v);
12010}
12011
12012
12013
12014template <int dim, int spacedim>
12016void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12017{
12018 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12019
12020 std::vector<bool>::const_iterator i = v.begin();
12021 for (const auto &cell : this->active_cell_iterators())
12022 {
12023 unsigned int ref_case = 0;
12024
12025 for (unsigned int j = 0; j < dim; ++j, ++i)
12026 if (*i == true)
12027 ref_case += 1 << j;
12029 ExcGridReadError());
12030 if (ref_case > 0)
12031 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12032 else
12033 cell->clear_refine_flag();
12034 }
12035
12036 Assert(i == v.end(), ExcInternalError());
12037}
12038
12039
12040
12041template <int dim, int spacedim>
12044 std::vector<bool> &v) const
12045{
12046 v.resize(n_active_cells(), false);
12047 std::vector<bool>::iterator i = v.begin();
12048 for (const auto &cell : this->active_cell_iterators())
12049 {
12050 *i = cell->coarsen_flag_set();
12051 ++i;
12052 }
12053
12054 Assert(i == v.end(), ExcInternalError());
12055}
12056
12057
12058
12059template <int dim, int spacedim>
12061void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
12062{
12063 std::vector<bool> v;
12064 save_coarsen_flags(v);
12065 write_bool_vector(mn_tria_coarsen_flags_begin,
12066 v,
12068 out);
12069}
12070
12071
12072
12073template <int dim, int spacedim>
12076{
12077 std::vector<bool> v;
12078 read_bool_vector(mn_tria_coarsen_flags_begin,
12079 v,
12081 in);
12082 load_coarsen_flags(v);
12083}
12084
12085
12086
12087template <int dim, int spacedim>
12090 const std::vector<bool> &v)
12091{
12092 Assert(v.size() == n_active_cells(), ExcGridReadError());
12093
12094 std::vector<bool>::const_iterator i = v.begin();
12095 for (const auto &cell : this->active_cell_iterators())
12096 {
12097 if (*i == true)
12098 cell->set_coarsen_flag();
12099 else
12100 cell->clear_coarsen_flag();
12101 ++i;
12102 }
12103
12104 Assert(i == v.end(), ExcInternalError());
12105}
12106
12107
12108template <int dim, int spacedim>
12111{
12112 return anisotropic_refinement;
12113}
12114
12115
12116
12117namespace internal
12118{
12119 namespace
12120 {
12121 std::vector<std::vector<bool>>
12122 extract_raw_coarsen_flags(
12123 const std::vector<std::unique_ptr<
12125 {
12126 std::vector<std::vector<bool>> coarsen_flags(levels.size());
12127 for (unsigned int level = 0; level < levels.size(); ++level)
12128 coarsen_flags[level] = levels[level]->coarsen_flags;
12129 return coarsen_flags;
12130 }
12131
12132 std::vector<std::vector<std::uint8_t>>
12133 extract_raw_refine_flags(
12134 const std::vector<std::unique_ptr<
12136 {
12137 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
12138 for (unsigned int level = 0; level < levels.size(); ++level)
12139 refine_flags[level] = levels[level]->refine_flags;
12140 return refine_flags;
12141 }
12142 } // namespace
12143} // namespace internal
12144
12145
12146/*-------------------- user data/flags -------------------------*/
12147
12148
12149namespace
12150{
12151 // clear user data of cells
12152 void
12153 clear_user_data(std::vector<std::unique_ptr<
12155 {
12156 for (auto &level : levels)
12157 level->cells.clear_user_data();
12158 }
12159
12160
12161 // clear user data of faces
12162 void
12164 {
12165 if (faces->dim == 2)
12166 {
12167 faces->lines.clear_user_data();
12168 }
12169
12170
12171 if (faces->dim == 3)
12172 {
12173 faces->lines.clear_user_data();
12174 faces->quads.clear_user_data();
12175 }
12176 }
12177} // namespace
12178
12179
12180template <int dim, int spacedim>
12183{
12184 // let functions in anonymous namespace do their work
12185 ::clear_user_data(levels);
12186 if (dim > 1)
12187 ::clear_user_data(faces.get());
12188}
12189
12190
12191
12192namespace
12193{
12194 void
12195 clear_user_flags_line(
12196 unsigned int dim,
12197 std::vector<
12198 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12199 & levels,
12201 {
12202 if (dim == 1)
12203 {
12204 for (const auto &level : levels)
12205 level->cells.clear_user_flags();
12206 }
12207 else if (dim == 2 || dim == 3)
12208 {
12209 faces->lines.clear_user_flags();
12210 }
12211 else
12212 {
12213 Assert(false, ExcNotImplemented())
12214 }
12215 }
12216} // namespace
12217
12218
12219template <int dim, int spacedim>
12222{
12223 ::clear_user_flags_line(dim, levels, faces.get());
12224}
12225
12226
12227
12228namespace
12229{
12230 void
12231 clear_user_flags_quad(
12232 unsigned int dim,
12233 std::vector<
12234 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12235 & levels,
12237 {
12238 if (dim == 1)
12239 {
12240 // nothing to do in 1d
12241 }
12242 else if (dim == 2)
12243 {
12244 for (const auto &level : levels)
12245 level->cells.clear_user_flags();
12246 }
12247 else if (dim == 3)
12248 {
12249 faces->quads.clear_user_flags();
12250 }
12251 else
12252 {
12253 Assert(false, ExcNotImplemented())
12254 }
12255 }
12256} // namespace
12257
12258
12259template <int dim, int spacedim>
12262{
12263 ::clear_user_flags_quad(dim, levels, faces.get());
12264}
12265
12266
12267
12268namespace
12269{
12270 void
12271 clear_user_flags_hex(
12272 unsigned int dim,
12273 std::vector<
12274 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12275 &levels,
12277 {
12278 if (dim == 1)
12279 {
12280 // nothing to do in 1d
12281 }
12282 else if (dim == 2)
12283 {
12284 // nothing to do in 2d
12285 }
12286 else if (dim == 3)
12287 {
12288 for (const auto &level : levels)
12289 level->cells.clear_user_flags();
12290 }
12291 else
12292 {
12293 Assert(false, ExcNotImplemented())
12294 }
12295 }
12296} // namespace
12297
12298
12299template <int dim, int spacedim>
12302{
12303 ::clear_user_flags_hex(dim, levels, faces.get());
12304}
12305
12306
12307
12308template <int dim, int spacedim>
12311{
12312 clear_user_flags_line();
12313 clear_user_flags_quad();
12314 clear_user_flags_hex();
12315}
12316
12317
12318
12319template <int dim, int spacedim>
12321void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
12322{
12323 save_user_flags_line(out);
12324
12325 if (dim >= 2)
12326 save_user_flags_quad(out);
12327
12328 if (dim >= 3)
12329 save_user_flags_hex(out);
12330
12331 if (dim >= 4)
12332 Assert(false, ExcNotImplemented());
12333}
12334
12335
12336
12337template <int dim, int spacedim>
12339void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
12340{
12341 // clear vector and append
12342 // all the stuff later on
12343 v.clear();
12344
12345 std::vector<bool> tmp;
12346
12347 save_user_flags_line(tmp);
12348 v.insert(v.end(), tmp.begin(), tmp.end());
12349
12350 if (dim >= 2)
12351 {
12352 save_user_flags_quad(tmp);
12353 v.insert(v.end(), tmp.begin(), tmp.end());
12354 }
12355
12356 if (dim >= 3)
12357 {
12358 save_user_flags_hex(tmp);
12359 v.insert(v.end(), tmp.begin(), tmp.end());
12360 }
12361
12362 if (dim >= 4)
12363 Assert(false, ExcNotImplemented());
12364}
12365
12366
12367
12368template <int dim, int spacedim>
12371{
12372 load_user_flags_line(in);
12373
12374 if (dim >= 2)
12375 load_user_flags_quad(in);
12376
12377 if (dim >= 3)
12378 load_user_flags_hex(in);
12379
12380 if (dim >= 4)
12381 Assert(false, ExcNotImplemented());
12382}
12383
12384
12385
12386template <int dim, int spacedim>
12388void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
12389{
12390 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12391 std::vector<bool> tmp;
12392
12393 // first extract the flags
12394 // belonging to lines
12395 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12396 // and set the lines
12397 load_user_flags_line(tmp);
12398
12399 if (dim >= 2)
12400 {
12401 tmp.clear();
12402 tmp.insert(tmp.end(),
12403 v.begin() + n_lines(),
12404 v.begin() + n_lines() + n_quads());
12405 load_user_flags_quad(tmp);
12406 }
12407
12408 if (dim >= 3)
12409 {
12410 tmp.clear();
12411 tmp.insert(tmp.end(),
12412 v.begin() + n_lines() + n_quads(),
12413 v.begin() + n_lines() + n_quads() + n_hexs());
12414 load_user_flags_hex(tmp);
12415 }
12416
12417 if (dim >= 4)
12418 Assert(false, ExcNotImplemented());
12419}
12420
12421
12422
12423template <int dim, int spacedim>
12426 std::vector<bool> &v) const
12427{
12428 v.resize(n_lines(), false);
12429 std::vector<bool>::iterator i = v.begin();
12430 line_iterator line = begin_line(), endl = end_line();
12431 for (; line != endl; ++line, ++i)
12432 *i = line->user_flag_set();
12433
12434 Assert(i == v.end(), ExcInternalError());
12435}
12436
12437
12438
12439template <int dim, int spacedim>
12441void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
12442{
12443 std::vector<bool> v;
12444 save_user_flags_line(v);
12445 write_bool_vector(mn_tria_line_user_flags_begin,
12446 v,
12448 out);
12449}
12450
12451
12452
12453template <int dim, int spacedim>
12456{
12457 std::vector<bool> v;
12458 read_bool_vector(mn_tria_line_user_flags_begin,
12459 v,
12461 in);
12462 load_user_flags_line(v);
12463}
12464
12465
12466
12467template <int dim, int spacedim>
12470 const std::vector<bool> &v)
12471{
12472 Assert(v.size() == n_lines(), ExcGridReadError());
12473
12474 line_iterator line = begin_line(), endl = end_line();
12475 std::vector<bool>::const_iterator i = v.begin();
12476 for (; line != endl; ++line, ++i)
12477 if (*i == true)
12478 line->set_user_flag();
12479 else
12480 line->clear_user_flag();
12481
12482 Assert(i == v.end(), ExcInternalError());
12483}
12484
12485
12486namespace
12487{
12488 template <typename Iterator>
12489 bool
12490 get_user_flag(const Iterator &i)
12491 {
12492 return i->user_flag_set();
12493 }
12494
12495
12496
12497 template <int structdim, int dim, int spacedim>
12498 bool
12500 {
12501 Assert(false, ExcInternalError());
12502 return false;
12503 }
12504
12505
12506
12507 template <typename Iterator>
12508 void
12509 set_user_flag(const Iterator &i)
12510 {
12511 i->set_user_flag();
12512 }
12513
12514
12515
12516 template <int structdim, int dim, int spacedim>
12517 void
12519 {
12520 Assert(false, ExcInternalError());
12521 }
12522
12523
12524
12525 template <typename Iterator>
12526 void
12527 clear_user_flag(const Iterator &i)
12528 {
12529 i->clear_user_flag();
12530 }
12531
12532
12533
12534 template <int structdim, int dim, int spacedim>
12535 void
12536 clear_user_flag(
12538 {
12539 Assert(false, ExcInternalError());
12540 }
12541} // namespace
12542
12543
12544template <int dim, int spacedim>
12547 std::vector<bool> &v) const
12548{
12549 v.resize(n_quads(), false);
12550
12551 if (dim >= 2)
12552 {
12553 std::vector<bool>::iterator i = v.begin();
12554 quad_iterator quad = begin_quad(), endq = end_quad();
12555 for (; quad != endq; ++quad, ++i)
12556 *i = get_user_flag(quad);
12557
12558 Assert(i == v.end(), ExcInternalError());
12559 }
12560}
12561
12562
12563
12564template <int dim, int spacedim>
12566void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
12567{
12568 std::vector<bool> v;
12569 save_user_flags_quad(v);
12570 write_bool_vector(mn_tria_quad_user_flags_begin,
12571 v,
12573 out);
12574}
12575
12576
12577
12578template <int dim, int spacedim>
12581{
12582 std::vector<bool> v;
12583 read_bool_vector(mn_tria_quad_user_flags_begin,
12584 v,
12586 in);
12587 load_user_flags_quad(v);
12588}
12589
12590
12591
12592template <int dim, int spacedim>
12595 const std::vector<bool> &v)
12596{
12597 Assert(v.size() == n_quads(), ExcGridReadError());
12598
12599 if (dim >= 2)
12600 {
12601 quad_iterator quad = begin_quad(), endq = end_quad();
12602 std::vector<bool>::const_iterator i = v.begin();
12603 for (; quad != endq; ++quad, ++i)
12604 if (*i == true)
12605 set_user_flag(quad);
12606 else
12607 clear_user_flag(quad);
12608
12609 Assert(i == v.end(), ExcInternalError());
12610 }
12611}
12612
12613
12614
12615template <int dim, int spacedim>
12618 std::vector<bool> &v) const
12619{
12620 v.resize(n_hexs(), false);
12621
12622 if (dim >= 3)
12623 {
12624 std::vector<bool>::iterator i = v.begin();
12625 hex_iterator hex = begin_hex(), endh = end_hex();
12626 for (; hex != endh; ++hex, ++i)
12627 *i = get_user_flag(hex);
12628
12629 Assert(i == v.end(), ExcInternalError());
12630 }
12631}
12632
12633
12634
12635template <int dim, int spacedim>
12637void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
12638{
12639 std::vector<bool> v;
12640 save_user_flags_hex(v);
12641 write_bool_vector(mn_tria_hex_user_flags_begin,
12642 v,
12644 out);
12645}
12646
12647
12648
12649template <int dim, int spacedim>
12652{
12653 std::vector<bool> v;
12654 read_bool_vector(mn_tria_hex_user_flags_begin,
12655 v,
12657 in);
12658 load_user_flags_hex(v);
12659}
12660
12661
12662
12663template <int dim, int spacedim>
12666 const std::vector<bool> &v)
12667{
12668 Assert(v.size() == n_hexs(), ExcGridReadError());
12669
12670 if (dim >= 3)
12671 {
12672 hex_iterator hex = begin_hex(), endh = end_hex();
12673 std::vector<bool>::const_iterator i = v.begin();
12674 for (; hex != endh; ++hex, ++i)
12675 if (*i == true)
12676 set_user_flag(hex);
12677 else
12678 clear_user_flag(hex);
12679
12680 Assert(i == v.end(), ExcInternalError());
12681 }
12682}
12683
12684
12685
12686template <int dim, int spacedim>
12689 std::vector<unsigned int> &v) const
12690{
12691 // clear vector and append all the
12692 // stuff later on
12693 v.clear();
12694
12695 std::vector<unsigned int> tmp;
12696
12697 save_user_indices_line(tmp);
12698 v.insert(v.end(), tmp.begin(), tmp.end());
12699
12700 if (dim >= 2)
12701 {
12702 save_user_indices_quad(tmp);
12703 v.insert(v.end(), tmp.begin(), tmp.end());
12704 }
12705
12706 if (dim >= 3)
12707 {
12708 save_user_indices_hex(tmp);
12709 v.insert(v.end(), tmp.begin(), tmp.end());
12710 }
12711
12712 if (dim >= 4)
12713 Assert(false, ExcNotImplemented());
12714}
12715
12716
12717
12718template <int dim, int spacedim>
12721 const std::vector<unsigned int> &v)
12722{
12723 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12724 std::vector<unsigned int> tmp;
12725
12726 // first extract the indices
12727 // belonging to lines
12728 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12729 // and set the lines
12730 load_user_indices_line(tmp);
12731
12732 if (dim >= 2)
12733 {
12734 tmp.clear();
12735 tmp.insert(tmp.end(),
12736 v.begin() + n_lines(),
12737 v.begin() + n_lines() + n_quads());
12738 load_user_indices_quad(tmp);
12739 }
12740
12741 if (dim >= 3)
12742 {
12743 tmp.clear();
12744 tmp.insert(tmp.end(),
12745 v.begin() + n_lines() + n_quads(),
12746 v.begin() + n_lines() + n_quads() + n_hexs());
12747 load_user_indices_hex(tmp);
12748 }
12749
12750 if (dim >= 4)
12751 Assert(false, ExcNotImplemented());
12752}
12753
12754
12755
12756namespace
12757{
12758 template <typename Iterator>
12759 unsigned int
12760 get_user_index(const Iterator &i)
12761 {
12762 return i->user_index();
12763 }
12764
12765
12766
12767 template <int structdim, int dim, int spacedim>
12768 unsigned int
12769 get_user_index(
12771 {
12772 Assert(false, ExcInternalError());
12774 }
12775
12776
12777
12778 template <typename Iterator>
12779 void
12780 set_user_index(const Iterator &i, const unsigned int x)
12781 {
12782 i->set_user_index(x);
12783 }
12784
12785
12786
12787 template <int structdim, int dim, int spacedim>
12788 void
12789 set_user_index(
12791 const unsigned int)
12792 {
12793 Assert(false, ExcInternalError());
12794 }
12795} // namespace
12796
12797
12798template <int dim, int spacedim>
12801 std::vector<unsigned int> &v) const
12802{
12803 v.resize(n_lines(), 0);
12804 std::vector<unsigned int>::iterator i = v.begin();
12805 line_iterator line = begin_line(), endl = end_line();
12806 for (; line != endl; ++line, ++i)
12807 *i = line->user_index();
12808}
12809
12810
12811
12812template <int dim, int spacedim>
12815 const std::vector<unsigned int> &v)
12816{
12817 Assert(v.size() == n_lines(), ExcGridReadError());
12818
12819 line_iterator line = begin_line(), endl = end_line();
12820 std::vector<unsigned int>::const_iterator i = v.begin();
12821 for (; line != endl; ++line, ++i)
12822 line->set_user_index(*i);
12823}
12824
12825
12826template <int dim, int spacedim>
12829 std::vector<unsigned int> &v) const
12830{
12831 v.resize(n_quads(), 0);
12832
12833 if (dim >= 2)
12834 {
12835 std::vector<unsigned int>::iterator i = v.begin();
12836 quad_iterator quad = begin_quad(), endq = end_quad();
12837 for (; quad != endq; ++quad, ++i)
12838 *i = get_user_index(quad);
12839 }
12840}
12841
12842
12843
12844template <int dim, int spacedim>
12847 const std::vector<unsigned int> &v)
12848{
12849 Assert(v.size() == n_quads(), ExcGridReadError());
12850
12851 if (dim >= 2)
12852 {
12853 quad_iterator quad = begin_quad(), endq = end_quad();
12854 std::vector<unsigned int>::const_iterator i = v.begin();
12855 for (; quad != endq; ++quad, ++i)
12856 set_user_index(quad, *i);
12857 }
12858}
12859
12860
12861template <int dim, int spacedim>
12864 std::vector<unsigned int> &v) const
12865{
12866 v.resize(n_hexs(), 0);
12867
12868 if (dim >= 3)
12869 {
12870 std::vector<unsigned int>::iterator i = v.begin();
12871 hex_iterator hex = begin_hex(), endh = end_hex();
12872 for (; hex != endh; ++hex, ++i)
12873 *i = get_user_index(hex);
12874 }
12875}
12876
12877
12878
12879template <int dim, int spacedim>
12882 const std::vector<unsigned int> &v)
12883{
12884 Assert(v.size() == n_hexs(), ExcGridReadError());
12885
12886 if (dim >= 3)
12887 {
12888 hex_iterator hex = begin_hex(), endh = end_hex();
12889 std::vector<unsigned int>::const_iterator i = v.begin();
12890 for (; hex != endh; ++hex, ++i)
12891 set_user_index(hex, *i);
12892 }
12893}
12894
12895
12896
12897//---------------- user pointers ----------------------------------------//
12898
12899
12900namespace
12901{
12902 template <typename Iterator>
12903 void *
12904 get_user_pointer(const Iterator &i)
12905 {
12906 return i->user_pointer();
12907 }
12908
12909
12910
12911 template <int structdim, int dim, int spacedim>
12912 void *
12913 get_user_pointer(
12915 {
12916 Assert(false, ExcInternalError());
12917 return nullptr;
12918 }
12919
12920
12921
12922 template <typename Iterator>
12923 void
12924 set_user_pointer(const Iterator &i, void *x)
12925 {
12926 i->set_user_pointer(x);
12927 }
12928
12929
12930
12931 template <int structdim, int dim, int spacedim>
12932 void
12933 set_user_pointer(
12935 void *)
12936 {
12937 Assert(false, ExcInternalError());
12938 }
12939} // namespace
12940
12941
12942template <int dim, int spacedim>
12945 std::vector<void *> &v) const
12946{
12947 // clear vector and append all the
12948 // stuff later on
12949 v.clear();
12950
12951 std::vector<void *> tmp;
12952
12953 save_user_pointers_line(tmp);
12954 v.insert(v.end(), tmp.begin(), tmp.end());
12955
12956 if (dim >= 2)
12957 {
12958 save_user_pointers_quad(tmp);
12959 v.insert(v.end(), tmp.begin(), tmp.end());
12960 }
12961
12962 if (dim >= 3)
12963 {
12964 save_user_pointers_hex(tmp);
12965 v.insert(v.end(), tmp.begin(), tmp.end());
12966 }
12967
12968 if (dim >= 4)
12969 Assert(false, ExcNotImplemented());
12970}
12971
12972
12973
12974template <int dim, int spacedim>
12977 const std::vector<void *> &v)
12978{
12979 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12980 std::vector<void *> tmp;
12981
12982 // first extract the pointers
12983 // belonging to lines
12984 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12985 // and set the lines
12986 load_user_pointers_line(tmp);
12987
12988 if (dim >= 2)
12989 {
12990 tmp.clear();
12991 tmp.insert(tmp.end(),
12992 v.begin() + n_lines(),
12993 v.begin() + n_lines() + n_quads());
12994 load_user_pointers_quad(tmp);
12995 }
12996
12997 if (dim >= 3)
12998 {
12999 tmp.clear();
13000 tmp.insert(tmp.end(),
13001 v.begin() + n_lines() + n_quads(),
13002 v.begin() + n_lines() + n_quads() + n_hexs());
13003 load_user_pointers_hex(tmp);
13004 }
13005
13006 if (dim >= 4)
13007 Assert(false, ExcNotImplemented());
13008}
13009
13010
13011
13012template <int dim, int spacedim>
13015 std::vector<void *> &v) const
13016{
13017 v.resize(n_lines(), nullptr);
13018 std::vector<void *>::iterator i = v.begin();
13019 line_iterator line = begin_line(), endl = end_line();
13020 for (; line != endl; ++line, ++i)
13021 *i = line->user_pointer();
13022}
13023
13024
13025
13026template <int dim, int spacedim>
13029 const std::vector<void *> &v)
13030{
13031 Assert(v.size() == n_lines(), ExcGridReadError());
13032
13033 line_iterator line = begin_line(), endl = end_line();
13034 std::vector<void *>::const_iterator i = v.begin();
13035 for (; line != endl; ++line, ++i)
13036 line->set_user_pointer(*i);
13037}
13038
13039
13040
13041template <int dim, int spacedim>
13044 std::vector<void *> &v) const
13045{
13046 v.resize(n_quads(), nullptr);
13047
13048 if (dim >= 2)
13049 {
13050 std::vector<void *>::iterator i = v.begin();
13051 quad_iterator quad = begin_quad(), endq = end_quad();
13052 for (; quad != endq; ++quad, ++i)
13053 *i = get_user_pointer(quad);
13054 }
13055}
13056
13057
13058
13059template <int dim, int spacedim>
13062 const std::vector<void *> &v)
13063{
13064 Assert(v.size() == n_quads(), ExcGridReadError());
13065
13066 if (dim >= 2)
13067 {
13068 quad_iterator quad = begin_quad(), endq = end_quad();
13069 std::vector<void *>::const_iterator i = v.begin();
13070 for (; quad != endq; ++quad, ++i)
13071 set_user_pointer(quad, *i);
13072 }
13073}
13074
13075
13076template <int dim, int spacedim>
13079 std::vector<void *> &v) const
13080{
13081 v.resize(n_hexs(), nullptr);
13082
13083 if (dim >= 3)
13084 {
13085 std::vector<void *>::iterator i = v.begin();
13086 hex_iterator hex = begin_hex(), endh = end_hex();
13087 for (; hex != endh; ++hex, ++i)
13088 *i = get_user_pointer(hex);
13089 }
13090}
13091
13092
13093
13094template <int dim, int spacedim>
13097 const std::vector<void *> &v)
13098{
13099 Assert(v.size() == n_hexs(), ExcGridReadError());
13100
13101 if (dim >= 3)
13102 {
13103 hex_iterator hex = begin_hex(), endh = end_hex();
13104 std::vector<void *>::const_iterator i = v.begin();
13105 for (; hex != endh; ++hex, ++i)
13106 set_user_pointer(hex, *i);
13107 }
13108}
13109
13110
13111
13112/*------------------------ Cell iterator functions ------------------------*/
13113
13114
13115template <int dim, int spacedim>
13118 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
13119{
13120 switch (dim)
13121 {
13122 case 1:
13123 return begin_raw_line(level);
13124 case 2:
13125 return begin_raw_quad(level);
13126 case 3:
13127 return begin_raw_hex(level);
13128 default:
13129 Assert(false, ExcNotImplemented());
13130 return raw_cell_iterator();
13131 }
13132}
13133
13134
13135
13136template <int dim, int spacedim>
13139 Triangulation<dim, spacedim>::begin(const unsigned int level) const
13140{
13141 switch (dim)
13142 {
13143 case 1:
13144 return begin_line(level);
13145 case 2:
13146 return begin_quad(level);
13147 case 3:
13148 return begin_hex(level);
13149 default:
13150 Assert(false, ExcImpossibleInDim(dim));
13151 return cell_iterator();
13152 }
13153}
13154
13155
13156
13157template <int dim, int spacedim>
13160 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
13161{
13162 switch (dim)
13163 {
13164 case 1:
13165 return begin_active_line(level);
13166 case 2:
13167 return begin_active_quad(level);
13168 case 3:
13169 return begin_active_hex(level);
13170 default:
13171 Assert(false, ExcNotImplemented());
13172 return active_cell_iterator();
13173 }
13174}
13175
13176
13177
13178template <int dim, int spacedim>
13182{
13183 const unsigned int level = levels.size() - 1;
13184 if (levels[level]->cells.n_objects() == 0)
13185 return end(level);
13186
13187 // find the last raw iterator on
13188 // this level
13189 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
13190 level,
13191 levels[level]->cells.n_objects() - 1);
13192
13193 // then move to the last used one
13194 if (ri->used() == true)
13195 return ri;
13196 while ((--ri).state() == IteratorState::valid)
13197 if (ri->used() == true)
13198 return ri;
13199 return ri;
13200}
13201
13202
13203
13204template <int dim, int spacedim>
13208{
13209 // get the last used cell
13210 cell_iterator cell = last();
13211
13212 if (cell != end())
13213 {
13214 // then move to the last active one
13215 if (cell->is_active() == true)
13216 return cell;
13217 while ((--cell).state() == IteratorState::valid)
13218 if (cell->is_active() == true)
13219 return cell;
13220 }
13221 return cell;
13222}
13223
13224
13225
13226template <int dim, int spacedim>
13230 const CellId &cell_id) const
13231{
13232 cell_iterator cell(
13233 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
13234
13235 for (const auto &child_index : cell_id.get_child_indices())
13236 {
13237 Assert(
13238 cell->has_children(),
13239 ExcMessage(
13240 "CellId is invalid for this triangulation.\n"
13241 "Either the provided CellId does not correspond to a cell in this "
13242 "triangulation object, or, in case you are using a parallel "
13243 "triangulation, may correspond to an artificial cell that is less "
13244 "refined on this processor."));
13245 cell = cell->child(static_cast<unsigned int>(child_index));
13246 }
13247
13248 return cell;
13249}
13250
13251
13252
13253template <int dim, int spacedim>
13257{
13258 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13259 -1,
13260 -1);
13261}
13262
13263
13264
13265template <int dim, int spacedim>
13268 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
13269{
13270 // This function may be called on parallel triangulations on levels
13271 // that exist globally, but not on the local portion of the
13272 // triangulation. In that case, just return the end iterator.
13273 //
13274 // We need to use levels.size() instead of n_levels() because the
13275 // latter function uses the cache, but we need to be able to call
13276 // this function at a time when the cache is not currently up to
13277 // date.
13278 if (level >= levels.size())
13279 {
13280 Assert(level < n_global_levels(),
13281 ExcInvalidLevel(level, n_global_levels()));
13282 return end();
13283 }
13284
13285 // Query whether the given level is valid for the local portion of the
13286 // triangulation.
13287 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13288 if (level < levels.size() - 1)
13289 return begin_raw(level + 1);
13290 else
13291 return end();
13292}
13293
13294
13295template <int dim, int spacedim>
13298 Triangulation<dim, spacedim>::end(const unsigned int level) const
13299{
13300 // This function may be called on parallel triangulations on levels
13301 // that exist globally, but not on the local portion of the
13302 // triangulation. In that case, just return the end iterator.
13303 //
13304 // We need to use levels.size() instead of n_levels() because the
13305 // latter function uses the cache, but we need to be able to call
13306 // this function at a time when the cache is not currently up to
13307 // date.
13308 if (level >= levels.size())
13309 {
13310 Assert(level < n_global_levels(),
13311 ExcInvalidLevel(level, n_global_levels()));
13312 return end();
13313 }
13314
13315 // Query whether the given level is valid for the local portion of the
13316 // triangulation.
13317 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13318 if (level < levels.size() - 1)
13319 return begin(level + 1);
13320 else
13321 return end();
13322}
13323
13324
13325template <int dim, int spacedim>
13328 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
13329{
13330 // This function may be called on parallel triangulations on levels
13331 // that exist globally, but not on the local portion of the
13332 // triangulation. In that case, just return the end iterator.
13333 //
13334 // We need to use levels.size() instead of n_levels() because the
13335 // latter function uses the cache, but we need to be able to call
13336 // this function at a time when the cache is not currently up to
13337 // date.
13338 if (level >= levels.size())
13339 {
13340 Assert(level < n_global_levels(),
13341 ExcInvalidLevel(level, n_global_levels()));
13342 return end();
13343 }
13344
13345 // Query whether the given level is valid for the local portion of the
13346 // triangulation.
13347 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13348 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
13349 begin_active(level + 1));
13350}
13351
13352
13353
13354template <int dim, int spacedim>
13358 const
13359{
13361 begin(), end());
13362}
13363
13364
13365template <int dim, int spacedim>
13368 active_cell_iterator> Triangulation<dim, spacedim>::
13370{
13371 return IteratorRange<
13373 end());
13374}
13375
13376
13377
13378template <int dim, int spacedim>
13381 cell_iterator> Triangulation<dim, spacedim>::
13382 cell_iterators_on_level(const unsigned int level) const
13383{
13385 begin(level), end(level));
13386}
13387
13388
13389
13390template <int dim, int spacedim>
13393 active_cell_iterator> Triangulation<dim, spacedim>::
13394 active_cell_iterators_on_level(const unsigned int level) const
13395{
13396 return IteratorRange<
13398 begin_active(level), end_active(level));
13399}
13400
13401
13402/*------------------------ Face iterator functions ------------------------*/
13403
13404
13405template <int dim, int spacedim>
13409{
13410 switch (dim)
13411 {
13412 case 1:
13413 Assert(false, ExcImpossibleInDim(1));
13414 return raw_face_iterator();
13415 case 2:
13416 return begin_line();
13417 case 3:
13418 return begin_quad();
13419 default:
13420 Assert(false, ExcNotImplemented());
13421 return face_iterator();
13422 }
13423}
13424
13425
13426
13427template <int dim, int spacedim>
13431{
13432 switch (dim)
13433 {
13434 case 1:
13435 Assert(false, ExcImpossibleInDim(1));
13436 return raw_face_iterator();
13437 case 2:
13438 return begin_active_line();
13439 case 3:
13440 return begin_active_quad();
13441 default:
13442 Assert(false, ExcNotImplemented());
13443 return active_face_iterator();
13444 }
13445}
13446
13447
13448
13449template <int dim, int spacedim>
13453{
13454 switch (dim)
13455 {
13456 case 1:
13457 Assert(false, ExcImpossibleInDim(1));
13458 return raw_face_iterator();
13459 case 2:
13460 return end_line();
13461 case 3:
13462 return end_quad();
13463 default:
13464 Assert(false, ExcNotImplemented());
13465 return raw_face_iterator();
13466 }
13467}
13468
13469
13470
13471template <int dim, int spacedim>
13474 active_face_iterator> Triangulation<dim, spacedim>::
13476{
13477 return IteratorRange<
13479 begin_active_face(), end_face());
13480}
13481
13482/*------------------------ Vertex iterator functions ------------------------*/
13483
13484
13485template <int dim, int spacedim>
13489{
13490 vertex_iterator i =
13491 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13492 if (i.state() != IteratorState::valid)
13493 return i;
13494 // This loop will end because every triangulation has used vertices.
13495 while (i->used() == false)
13496 if ((++i).state() != IteratorState::valid)
13497 return i;
13498 return i;
13499}
13500
13501
13502
13503template <int dim, int spacedim>
13507{
13508 // every vertex is active
13509 return begin_vertex();
13510}
13511
13512
13513
13514template <int dim, int spacedim>
13518{
13519 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13520 -1,
13522}
13523
13524
13525
13526/*------------------------ Line iterator functions ------------------------*/
13527
13528
13529
13530template <int dim, int spacedim>
13533 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
13534{
13535 // This function may be called on parallel triangulations on levels
13536 // that exist globally, but not on the local portion of the
13537 // triangulation. In that case, just return the end iterator.
13538 //
13539 // We need to use levels.size() instead of n_levels() because the
13540 // latter function uses the cache, but we need to be able to call
13541 // this function at a time when the cache is not currently up to
13542 // date.
13543 if (level >= levels.size())
13544 {
13545 Assert(level < n_global_levels(),
13546 ExcInvalidLevel(level, n_global_levels()));
13547 return end_line();
13548 }
13549
13550 switch (dim)
13551 {
13552 case 1:
13553 // Query whether the given level is valid for the local portion of the
13554 // triangulation.
13555 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13556
13557 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13558 return end_line();
13559
13560 return raw_line_iterator(
13561 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13562
13563 default:
13564 Assert(level == 0, ExcFacesHaveNoLevel());
13565 return raw_line_iterator(
13566 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13567 }
13568}
13569
13570
13571template <int dim, int spacedim>
13574 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
13575{
13576 // level is checked in begin_raw
13577 raw_line_iterator ri = begin_raw_line(level);
13578 if (ri.state() != IteratorState::valid)
13579 return ri;
13580 while (ri->used() == false)
13581 if ((++ri).state() != IteratorState::valid)
13582 return ri;
13583 return ri;
13584}
13585
13586
13587
13588template <int dim, int spacedim>
13592 const unsigned int level) const
13593{
13594 // level is checked in begin_raw
13595 line_iterator i = begin_line(level);
13596 if (i.state() != IteratorState::valid)
13597 return i;
13598 while (i->has_children())
13599 if ((++i).state() != IteratorState::valid)
13600 return i;
13601 return i;
13602}
13603
13604
13605
13606template <int dim, int spacedim>
13610{
13611 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13612 -1,
13613 -1);
13614}
13615
13616
13617
13618/*------------------------ Quad iterator functions ------------------------*/
13619
13620
13621template <int dim, int spacedim>
13624 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
13625{
13626 // This function may be called on parallel triangulations on levels
13627 // that exist globally, but not on the local portion of the
13628 // triangulation. In that case, just return the end iterator.
13629 //
13630 // We need to use levels.size() instead of n_levels() because the
13631 // latter function uses the cache, but we need to be able to call
13632 // this function at a time when the cache is not currently up to
13633 // date.
13634 if (level >= levels.size())
13635 {
13636 Assert(level < n_global_levels(),
13637 ExcInvalidLevel(level, n_global_levels()));
13638 return end_quad();
13639 }
13640
13641 switch (dim)
13642 {
13643 case 1:
13644 Assert(false, ExcImpossibleInDim(1));
13645 return raw_hex_iterator();
13646 case 2:
13647 {
13648 // Query whether the given level is valid for the local portion of the
13649 // triangulation.
13650 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13651
13652 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13653 return end_quad();
13654
13655 return raw_quad_iterator(
13656 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13657 }
13658
13659 case 3:
13660 {
13661 Assert(level == 0, ExcFacesHaveNoLevel());
13662
13663 return raw_quad_iterator(
13664 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13665 }
13666
13667
13668 default:
13669 Assert(false, ExcNotImplemented());
13670 return raw_hex_iterator();
13671 }
13672}
13673
13674
13675
13676template <int dim, int spacedim>
13679 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
13680{
13681 // level is checked in begin_raw
13682 raw_quad_iterator ri = begin_raw_quad(level);
13683 if (ri.state() != IteratorState::valid)
13684 return ri;
13685 while (ri->used() == false)
13686 if ((++ri).state() != IteratorState::valid)
13687 return ri;
13688 return ri;
13689}
13690
13691
13692
13693template <int dim, int spacedim>
13697 const unsigned int level) const
13698{
13699 // level is checked in begin_raw
13700 quad_iterator i = begin_quad(level);
13701 if (i.state() != IteratorState::valid)
13702 return i;
13703 while (i->has_children())
13704 if ((++i).state() != IteratorState::valid)
13705 return i;
13706 return i;
13707}
13708
13709
13710
13711template <int dim, int spacedim>
13715{
13716 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13717 -1,
13718 -1);
13719}
13720
13721
13722/*------------------------ Hex iterator functions ------------------------*/
13723
13724
13725template <int dim, int spacedim>
13728 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
13729{
13730 // This function may be called on parallel triangulations on levels
13731 // that exist globally, but not on the local portion of the
13732 // triangulation. In that case, just return the end iterator.
13733 //
13734 // We need to use levels.size() instead of n_levels() because the
13735 // latter function uses the cache, but we need to be able to call
13736 // this function at a time when the cache is not currently up to
13737 // date.
13738 if (level >= levels.size())
13739 {
13740 Assert(level < n_global_levels(),
13741 ExcInvalidLevel(level, n_global_levels()));
13742 return end_hex();
13743 }
13744
13745 switch (dim)
13746 {
13747 case 1:
13748 case 2:
13749 Assert(false, ExcImpossibleInDim(1));
13750 return raw_hex_iterator();
13751 case 3:
13752 {
13753 // Query whether the given level is valid for the local portion of the
13754 // triangulation.
13755 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13756
13757 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13758 return end_hex();
13759
13760 return raw_hex_iterator(
13761 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13762 }
13763
13764 default:
13765 Assert(false, ExcNotImplemented());
13766 return raw_hex_iterator();
13767 }
13768}
13769
13770
13771
13772template <int dim, int spacedim>
13775 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
13776{
13777 // level is checked in begin_raw
13778 raw_hex_iterator ri = begin_raw_hex(level);
13779 if (ri.state() != IteratorState::valid)
13780 return ri;
13781 while (ri->used() == false)
13782 if ((++ri).state() != IteratorState::valid)
13783 return ri;
13784 return ri;
13785}
13786
13787
13788
13789template <int dim, int spacedim>
13793{
13794 // level is checked in begin_raw
13795 hex_iterator i = begin_hex(level);
13796 if (i.state() != IteratorState::valid)
13797 return i;
13798 while (i->has_children())
13799 if ((++i).state() != IteratorState::valid)
13800 return i;
13801 return i;
13802}
13803
13804
13805
13806template <int dim, int spacedim>
13810{
13811 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13812 -1,
13813 -1);
13814}
13815
13816
13817
13818// -------------------------------- number of cells etc ---------------
13819
13820
13821namespace internal
13822{
13823 namespace TriangulationImplementation
13824 {
13825 inline unsigned int
13827 {
13828 return c.n_lines;
13829 }
13830
13831
13832 inline unsigned int
13835 {
13836 return c.n_active_lines;
13837 }
13838
13839
13840 inline unsigned int
13842 {
13843 return c.n_quads;
13844 }
13845
13846
13847 inline unsigned int
13850 {
13851 return c.n_active_quads;
13852 }
13853
13854
13855 inline unsigned int
13857 {
13858 return c.n_hexes;
13859 }
13860
13861
13862 inline unsigned int
13865 {
13866 return c.n_active_hexes;
13867 }
13868 } // namespace TriangulationImplementation
13869} // namespace internal
13870
13871
13872
13873template <int dim, int spacedim>
13875unsigned int Triangulation<dim, spacedim>::n_cells() const
13876{
13878}
13879
13880
13881template <int dim, int spacedim>
13884{
13886}
13887
13888template <int dim, int spacedim>
13892{
13893 return n_active_cells();
13894}
13895
13896template <int dim, int spacedim>
13900{
13901 return n_cells(0);
13902}
13903
13904template <int dim, int spacedim>
13906unsigned int Triangulation<dim, spacedim>::n_faces() const
13907{
13908 switch (dim)
13909 {
13910 case 1:
13911 return n_used_vertices();
13912 case 2:
13913 return n_lines();
13914 case 3:
13915 return n_quads();
13916 default:
13917 Assert(false, ExcNotImplemented());
13918 }
13919 return 0;
13920}
13921
13922
13923template <int dim, int spacedim>
13926{
13927 switch (dim)
13928 {
13929 case 1:
13930 return n_vertices();
13931 case 2:
13932 return n_raw_lines();
13933 case 3:
13934 return n_raw_quads();
13935 default:
13936 Assert(false, ExcNotImplemented());
13937 }
13938 return 0;
13939}
13940
13941
13942template <int dim, int spacedim>
13945{
13946 switch (dim)
13947 {
13948 case 1:
13949 return n_used_vertices();
13950 case 2:
13951 return n_active_lines();
13952 case 3:
13953 return n_active_quads();
13954 default:
13955 Assert(false, ExcNotImplemented());
13956 }
13957 return 0;
13958}
13959
13960
13961template <int dim, int spacedim>
13964 const unsigned int level) const
13965{
13966 switch (dim)
13967 {
13968 case 1:
13969 return n_raw_lines(level);
13970 case 2:
13971 return n_raw_quads(level);
13972 case 3:
13973 return n_raw_hexs(level);
13974 default:
13975 Assert(false, ExcNotImplemented());
13976 }
13977 return 0;
13978}
13979
13980
13981
13982template <int dim, int spacedim>
13985 const unsigned int level) const
13986{
13987 switch (dim)
13988 {
13989 case 1:
13990 return n_lines(level);
13991 case 2:
13992 return n_quads(level);
13993 case 3:
13994 return n_hexs(level);
13995 default:
13996 Assert(false, ExcNotImplemented());
13997 }
13998 return 0;
13999}
14000
14001
14002
14003template <int dim, int spacedim>
14006 const unsigned int level) const
14007{
14008 switch (dim)
14009 {
14010 case 1:
14011 return n_active_lines(level);
14012 case 2:
14013 return n_active_quads(level);
14014 case 3:
14015 return n_active_hexs(level);
14016 default:
14017 Assert(false, ExcNotImplemented());
14018 }
14019 return 0;
14020}
14021
14022
14023template <int dim, int spacedim>
14026{
14027 if (anisotropic_refinement == false)
14028 {
14029 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
14030 if (n_active_cells(lvl) != 0)
14031 return true;
14032 }
14033 else
14034 {
14035 for (const auto &cell : active_cell_iterators())
14036 for (const auto &i : cell->face_indices())
14037 if (cell->face(i)->has_children())
14038 return true;
14039 }
14040 return false;
14041}
14042
14043
14044template <int dim, int spacedim>
14046unsigned int Triangulation<dim, spacedim>::n_lines() const
14047{
14048 return number_cache.n_lines;
14049}
14050
14051
14052
14053template <int dim, int spacedim>
14056 const unsigned int level) const
14057{
14058 if (dim == 1)
14059 {
14060 AssertIndexRange(level, n_levels());
14061 return levels[level]->cells.n_objects();
14062 }
14063
14064 Assert(false, ExcFacesHaveNoLevel());
14065 return 0;
14066}
14067
14068
14069template <int dim, int spacedim>
14072{
14073 if (dim == 1)
14074 {
14075 Assert(false, ExcNotImplemented());
14076 return 0;
14077 }
14078
14079 return faces->lines.n_objects();
14080}
14081
14082
14083template <int dim, int spacedim>
14086 const unsigned int level) const
14087{
14088 AssertIndexRange(level, number_cache.n_lines_level.size());
14089 Assert(dim == 1, ExcFacesHaveNoLevel());
14090 return number_cache.n_lines_level[level];
14091}
14092
14093
14094template <int dim, int spacedim>
14097{
14098 return number_cache.n_active_lines;
14099}
14100
14101
14102template <int dim, int spacedim>
14105 const unsigned int level) const
14106{
14107 AssertIndexRange(level, number_cache.n_lines_level.size());
14108 Assert(dim == 1, ExcFacesHaveNoLevel());
14109
14110 return number_cache.n_active_lines_level[level];
14111}
14112
14113
14114template <>
14115unsigned int
14117{
14118 return 0;
14119}
14120
14121
14122template <>
14123unsigned int
14124Triangulation<1, 1>::n_quads(const unsigned int) const
14125{
14126 return 0;
14127}
14128
14129
14130template <>
14131unsigned int
14132Triangulation<1, 1>::n_raw_quads(const unsigned int) const
14133{
14134 return 0;
14135}
14136
14137
14138template <>
14139unsigned int
14140Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
14141{
14142 return 0;
14143}
14144
14145
14146template <>
14147unsigned int
14149{
14150 return 0;
14151}
14152
14153
14154template <>
14155unsigned int
14157{
14158 return 0;
14159}
14160
14161
14162
14163template <>
14164unsigned int
14166{
14167 return 0;
14168}
14169
14170
14171template <>
14172unsigned int
14173Triangulation<1, 2>::n_quads(const unsigned int) const
14174{
14175 return 0;
14176}
14177
14178
14179template <>
14180unsigned int
14181Triangulation<1, 2>::n_raw_quads(const unsigned int) const
14182{
14183 return 0;
14184}
14185
14186
14187template <>
14188unsigned int
14189Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
14190{
14191 return 0;
14192}
14193
14194
14195template <>
14196unsigned int
14198{
14199 return 0;
14200}
14201
14202
14203template <>
14204unsigned int
14206{
14207 return 0;
14208}
14209
14210
14211template <>
14212unsigned int
14214{
14215 return 0;
14216}
14217
14218
14219template <>
14220unsigned int
14221Triangulation<1, 3>::n_quads(const unsigned int) const
14222{
14223 return 0;
14224}
14225
14226
14227template <>
14228unsigned int
14229Triangulation<1, 3>::n_raw_quads(const unsigned int) const
14230{
14231 return 0;
14232}
14233
14234
14235template <>
14236unsigned int
14237Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
14238{
14239 return 0;
14240}
14241
14242
14243template <>
14244unsigned int
14246{
14247 return 0;
14248}
14249
14250
14251template <>
14252unsigned int
14254{
14255 return 0;
14256}
14257
14258
14259
14260template <int dim, int spacedim>
14262unsigned int Triangulation<dim, spacedim>::n_quads() const
14263{
14264 return number_cache.n_quads;
14265}
14266
14267
14268template <int dim, int spacedim>
14271 const unsigned int level) const
14272{
14273 Assert(dim == 2, ExcFacesHaveNoLevel());
14274 AssertIndexRange(level, number_cache.n_quads_level.size());
14275 return number_cache.n_quads_level[level];
14276}
14277
14278
14279
14280template <>
14281unsigned int
14283{
14284 AssertIndexRange(level, n_levels());
14285 return levels[level]->cells.n_objects();
14286}
14287
14288
14289
14290template <>
14291unsigned int
14293{
14294 AssertIndexRange(level, n_levels());
14295 return levels[level]->cells.n_objects();
14296}
14297
14298
14299template <>
14300unsigned int
14301Triangulation<3, 3>::n_raw_quads(const unsigned int) const
14302{
14303 Assert(false, ExcFacesHaveNoLevel());
14304 return 0;
14305}
14306
14307
14308
14309template <int dim, int spacedim>
14312{
14313 Assert(false, ExcNotImplemented());
14314 return 0;
14315}
14316
14317
14318
14319template <>
14320unsigned int
14322{
14323 return faces->quads.n_objects();
14324}
14325
14326
14327
14328template <int dim, int spacedim>
14331{
14332 return number_cache.n_active_quads;
14333}
14334
14335
14336template <int dim, int spacedim>
14339 const unsigned int level) const
14340{
14341 AssertIndexRange(level, number_cache.n_quads_level.size());
14342 Assert(dim == 2, ExcFacesHaveNoLevel());
14343
14344 return number_cache.n_active_quads_level[level];
14345}
14346
14347
14348template <int dim, int spacedim>
14350unsigned int Triangulation<dim, spacedim>::n_hexs() const
14351{
14352 return 0;
14353}
14354
14355
14356
14357template <int dim, int spacedim>
14359unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
14360{
14361 return 0;
14362}
14363
14364
14365
14366template <int dim, int spacedim>
14368unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
14369{
14370 return 0;
14371}
14372
14373
14374template <int dim, int spacedim>
14377{
14378 return 0;
14379}
14380
14381
14382
14383template <int dim, int spacedim>
14386 const unsigned int) const
14387{
14388 return 0;
14389}
14390
14391
14392template <>
14393unsigned int
14395{
14396 return number_cache.n_hexes;
14397}
14398
14399
14400
14401template <>
14402unsigned int
14403Triangulation<3, 3>::n_hexs(const unsigned int level) const
14404{
14405 AssertIndexRange(level, number_cache.n_hexes_level.size());
14406
14407 return number_cache.n_hexes_level[level];
14408}
14409
14410
14411
14412template <>
14413unsigned int
14415{
14416 AssertIndexRange(level, n_levels());
14417 return levels[level]->cells.n_objects();
14418}
14419
14420
14421template <>
14422unsigned int
14424{
14425 return number_cache.n_active_hexes;
14426}
14427
14428
14429
14430template <>
14431unsigned int
14433{
14434 AssertIndexRange(level, number_cache.n_hexes_level.size());
14435
14436 return number_cache.n_active_hexes_level[level];
14437}
14438
14439
14440
14441template <int dim, int spacedim>
14444{
14445 return std::count(vertices_used.begin(), vertices_used.end(), true);
14446}
14447
14448
14449
14450template <int dim, int spacedim>
14452const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
14453{
14454 return vertices_used;
14455}
14456
14457
14458
14459template <>
14460unsigned int
14462{
14463 return 2;
14464}
14465
14466
14467
14468template <>
14469unsigned int
14471{
14472 return 2;
14473}
14474
14475
14476template <>
14477unsigned int
14479{
14480 return 2;
14481}
14482
14483
14484template <int dim, int spacedim>
14487{
14488 cell_iterator cell = begin(0),
14489 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
14490 // store the largest index of the
14491 // vertices used on level 0
14492 unsigned int max_vertex_index = 0;
14493 for (; cell != endc; ++cell)
14494 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
14495 if (cell->vertex_index(vertex) > max_vertex_index)
14496 max_vertex_index = cell->vertex_index(vertex);
14497
14498 // store the number of times a cell
14499 // touches a vertex. An unsigned
14500 // int should suffice, even for
14501 // larger dimensions
14502 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
14503 // touch a vertex's usage count
14504 // every time we find an adjacent
14505 // element
14506 for (cell = begin(); cell != endc; ++cell)
14507 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
14508 ++usage_count[cell->vertex_index(vertex)];
14509
14511 static_cast<unsigned int>(
14512 *std::max_element(usage_count.begin(), usage_count.end())));
14513}
14514
14515
14516
14517template <int dim, int spacedim>
14521{
14523}
14524
14525
14526
14527template <int dim, int spacedim>
14530{
14531 return *this;
14532}
14533
14534
14535
14536template <int dim, int spacedim>
14540{
14541 return *this;
14542}
14543
14544
14545
14546template <int dim, int spacedim>
14550 &periodicity_vector)
14551{
14552 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
14553 periodicity_vector.begin(),
14554 periodicity_vector.end());
14555
14556 // Now initialize periodic_face_map
14557 update_periodic_face_map();
14558}
14559
14560
14561
14562template <int dim, int spacedim>
14564const typename std::map<
14565 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
14566 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
14567 unsigned int>,
14568 std::bitset<3>>>
14570{
14571 return periodic_face_map;
14572}
14573
14574
14575
14576template <int dim, int spacedim>
14579{
14580 // Call our version of prepare_coarsening_and_refinement() even if a derived
14581 // class like parallel::distributed::Triangulation overrides it. Their
14582 // function will be called in their execute_coarsening_and_refinement()
14583 // function. Even in a distributed computation our job here is to reconstruct
14584 // the local part of the mesh and as such checking our flags is enough.
14586
14587 // verify a case with which we have had
14588 // some difficulty in the past (see the
14589 // deal.II/coarsening_* tests)
14590 if (smooth_grid & limit_level_difference_at_vertices)
14591 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
14592
14593 // Inform all listeners about beginning of refinement.
14594 signals.pre_refinement();
14595
14596 execute_coarsening();
14597
14598 const DistortedCellList cells_with_distorted_children = execute_refinement();
14599
14600 reset_cell_vertex_indices_cache();
14601
14602 // verify a case with which we have had
14603 // some difficulty in the past (see the
14604 // deal.II/coarsening_* tests)
14605 if (smooth_grid & limit_level_difference_at_vertices)
14606 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
14607
14608 // finally build up neighbor connectivity information, and set
14609 // active cell indices
14610 this->policy->update_neighbors(*this);
14611 reset_active_cell_indices();
14612
14613 reset_global_cell_indices(); // TODO: better place?
14614
14615 // Inform all listeners about end of refinement.
14616 signals.post_refinement();
14617
14618 AssertThrow(cells_with_distorted_children.distorted_cells.size() == 0,
14619 cells_with_distorted_children);
14620
14621 update_periodic_face_map();
14622}
14623
14624
14625
14626template <int dim, int spacedim>
14629{
14630 unsigned int active_cell_index = 0;
14631 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
14632 if ((cell->used() == false) || cell->has_children())
14633 cell->set_active_cell_index(numbers::invalid_unsigned_int);
14634 else
14635 {
14636 cell->set_active_cell_index(active_cell_index);
14637 ++active_cell_index;
14638 }
14639
14640 Assert(active_cell_index == n_active_cells(), ExcInternalError());
14641}
14642
14643
14644
14645template <int dim, int spacedim>
14648{
14649 {
14651 for (const auto &cell : active_cell_iterators())
14652 cell->set_global_active_cell_index(cell_index++);
14653 }
14654
14655 for (unsigned int l = 0; l < levels.size(); ++l)
14656 {
14658 for (const auto &cell : cell_iterators_on_level(l))
14659 cell->set_global_level_cell_index(cell_index++);
14660 }
14661}
14662
14663
14664
14665template <int dim, int spacedim>
14668{
14669 for (unsigned int l = 0; l < levels.size(); ++l)
14670 {
14671 constexpr unsigned int max_vertices_per_cell = 1 << dim;
14672 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
14673 cache.clear();
14674 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
14676 for (const auto &cell : cell_iterators_on_level(l))
14677 {
14678 const unsigned int my_index = cell->index() * max_vertices_per_cell;
14679
14680 // to reduce the cost of this function when passing down into quads,
14681 // then lines, then vertices, we use a more low-level access method
14682 // for hexahedral cells, where we can streamline most of the logic
14683 const ReferenceCell ref_cell = cell->reference_cell();
14684 if (ref_cell == ReferenceCells::Hexahedron)
14685 for (unsigned int face = 4; face < 6; ++face)
14686 {
14687 const auto face_iter = cell->face(face);
14688 const std::array<bool, 2> line_orientations{
14689 {face_iter->line_orientation(0),
14690 face_iter->line_orientation(1)}};
14691 std::array<unsigned int, 4> raw_vertex_indices{
14692 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
14693 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
14694 face_iter->line(0)->vertex_index(line_orientations[0]),
14695 face_iter->line(1)->vertex_index(line_orientations[1])}};
14696
14697 const unsigned char combined_orientation =
14698 levels[l]->face_orientations.get_combined_orientation(
14699 cell->index() * GeometryInfo<3>::faces_per_cell + face);
14700 std::array<unsigned int, 4> vertex_order{
14701 {ref_cell.standard_to_real_face_vertex(0,
14702 face,
14703 combined_orientation),
14705 face,
14706 combined_orientation),
14708 face,
14709 combined_orientation),
14711 3, face, combined_orientation)}};
14712
14713 const unsigned int index = my_index + 4 * (face - 4);
14714 for (unsigned int i = 0; i < 4; ++i)
14715 cache[index + i] = raw_vertex_indices[vertex_order[i]];
14716 }
14717 else if (ref_cell == ReferenceCells::Quadrilateral)
14718 {
14719 const std::array<bool, 2> line_orientations{
14720 {cell->line_orientation(0), cell->line_orientation(1)}};
14721 std::array<unsigned int, 4> raw_vertex_indices{
14722 {cell->line(0)->vertex_index(1 - line_orientations[0]),
14723 cell->line(1)->vertex_index(1 - line_orientations[1]),
14724 cell->line(0)->vertex_index(line_orientations[0]),
14725 cell->line(1)->vertex_index(line_orientations[1])}};
14726 for (unsigned int i = 0; i < 4; ++i)
14727 cache[my_index + i] = raw_vertex_indices[i];
14728 }
14729 else
14730 for (const unsigned int i : cell->vertex_indices())
14731 cache[my_index + i] = internal::TriaAccessorImplementation::
14732 Implementation::vertex_index(*cell, i);
14733 }
14734 }
14735}
14736
14737
14738
14739template <int dim, int spacedim>
14742{
14743 // first empty the currently stored objects
14744 periodic_face_map.clear();
14745
14746 typename std::vector<
14748 for (it = periodic_face_pairs_level_0.begin();
14749 it != periodic_face_pairs_level_0.end();
14750 ++it)
14751 {
14752 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
14753 it->cell[1],
14754 it->face_idx[0],
14755 it->face_idx[1],
14756 it->orientation,
14757 periodic_face_map);
14758
14759 // for the other way, we need to invert the orientation
14760 std::bitset<3> inverted_orientation;
14761 {
14762 bool orientation, flip, rotation;
14763 orientation = it->orientation[0];
14764 rotation = it->orientation[2];
14765 flip = orientation ? rotation ^ it->orientation[1] : it->orientation[1];
14766 inverted_orientation[0] = orientation;
14767 inverted_orientation[1] = flip;
14768 inverted_orientation[2] = rotation;
14769 }
14770 update_periodic_face_map_recursively<dim, spacedim>(it->cell[1],
14771 it->cell[0],
14772 it->face_idx[1],
14773 it->face_idx[0],
14774 inverted_orientation,
14775 periodic_face_map);
14776 }
14777
14778 // check consistency
14779 typename std::map<std::pair<cell_iterator, unsigned int>,
14780 std::pair<std::pair<cell_iterator, unsigned int>,
14781 std::bitset<3>>>::const_iterator it_test;
14782 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
14783 ++it_test)
14784 {
14786 it_test->first.first;
14788 it_test->second.first.first;
14789 if (cell_1->level() == cell_2->level())
14790 {
14791 // if both cells have the same neighbor, then the same pair
14792 // order swapped has to be in the map
14793 Assert(periodic_face_map[it_test->second.first].first ==
14794 it_test->first,
14796 }
14797 }
14798}
14799
14800
14801
14802template <int dim, int spacedim>
14805{
14806 std::set<ReferenceCell> reference_cells_set;
14807 for (auto cell : active_cell_iterators())
14808 if (cell->is_locally_owned())
14809 reference_cells_set.insert(cell->reference_cell());
14810
14811 this->reference_cells =
14812 std::vector<ReferenceCell>(reference_cells_set.begin(),
14813 reference_cells_set.end());
14814}
14815
14816
14817
14818template <int dim, int spacedim>
14820const std::vector<ReferenceCell>
14822{
14823 return this->reference_cells;
14824}
14825
14826
14827
14828template <int dim, int spacedim>
14831{
14832 Assert(this->reference_cells.size() > 0,
14833 ExcMessage("You can't ask about the kinds of reference "
14834 "cells used by this triangulation if the "
14835 "triangulation doesn't yet have any cells in it."));
14836 return (this->reference_cells.size() == 1 &&
14837 this->reference_cells[0].is_hyper_cube());
14838}
14839
14840
14841
14842template <int dim, int spacedim>
14845{
14846 Assert(this->reference_cells.size() > 0,
14847 ExcMessage("You can't ask about the kinds of reference "
14848 "cells used by this triangulation if the "
14849 "triangulation doesn't yet have any cells in it."));
14850 return (this->reference_cells.size() == 1 &&
14851 this->reference_cells[0].is_simplex());
14852}
14853
14854
14855
14856template <int dim, int spacedim>
14859{
14860 Assert(this->reference_cells.size() > 0,
14861 ExcMessage("You can't ask about the kinds of reference "
14862 "cells used by this triangulation if the "
14863 "triangulation doesn't yet have any cells in it."));
14864 return reference_cells.size() > 1 ||
14865 ((reference_cells[0].is_hyper_cube() == false) &&
14866 (reference_cells[0].is_simplex() == false));
14867}
14868
14869
14870
14871template <int dim, int spacedim>
14874{
14875 levels.clear();
14876 faces.reset();
14877
14878 vertices.clear();
14879 vertices_used.clear();
14880
14881 manifolds.clear();
14882
14884}
14885
14886
14887
14888template <int dim, int spacedim>
14892{
14893 const DistortedCellList cells_with_distorted_children =
14894 this->policy->execute_refinement(*this, check_for_distorted_cells);
14895
14896
14897
14898 // re-compute number of lines
14900 *this, levels.size(), number_cache);
14901
14902#ifdef DEBUG
14903 for (const auto &level : levels)
14904 monitor_memory(level->cells, dim);
14905
14906 // check whether really all refinement flags are reset (also of
14907 // previously non-active cells which we may not have touched. If the
14908 // refinement flag of a non-active cell is set, something went wrong
14909 // since the cell-accessors should have caught this)
14910 for (const auto &cell : this->cell_iterators())
14911 Assert(!cell->refine_flag_set(), ExcInternalError());
14912#endif
14913
14914 return cells_with_distorted_children;
14915}
14916
14917
14918
14919template <int dim, int spacedim>
14922{
14923 // first find out if there are any cells at all to be coarsened in the
14924 // loop below
14925 const cell_iterator endc = end();
14926 bool do_coarsen = false;
14927 if (levels.size() >= 2)
14928 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
14929 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
14930 {
14931 do_coarsen = true;
14932 break;
14933 }
14934
14935 if (!do_coarsen)
14936 return;
14937
14938 // create a vector counting for each line and quads how many cells contain
14939 // the respective object. this is used later to decide which lines can be
14940 // deleted after coarsening a cell.
14941 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
14942 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
14943 if (dim > 1)
14944 for (const auto &cell : this->cell_iterators())
14945 {
14946 if (dim > 2)
14947 {
14948 const auto line_indices = internal::TriaAccessorImplementation::
14949 Implementation::get_line_indices_of_cell(*cell);
14950 // avoid a compiler warning by fixing the max number of
14951 // loop iterations to 12
14952 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
14953 for (unsigned int l = 0; l < n_lines; ++l)
14954 ++line_cell_count[line_indices[l]];
14955 for (const unsigned int q : cell->face_indices())
14956 ++quad_cell_count[cell->face_index(q)];
14957 }
14958 else
14959 for (unsigned int l = 0; l < cell->n_lines(); ++l)
14960 ++line_cell_count[cell->line(l)->index()];
14961 }
14962
14963 // Since the loop goes over used cells we only need not worry about
14964 // deleting some cells since the ++operator will then just hop over them
14965 // if we should hit one. Do the loop in the reverse way since we may
14966 // only delete some cells if their neighbors have already been deleted
14967 // (if the latter are on a higher level for example). In effect, only
14968 // those cells are deleted of which originally all children were flagged
14969 // and for which all children are on the same refinement level. Note
14970 // that because of the effects of
14971 // @p{fix_coarsen_flags}, of a cell either all or no children must be
14972 // flagged for coarsening, so it is ok to only check the first child
14973 //
14974 // since we delete the *children* of cells, we can ignore cells on the
14975 // highest level, i.e., level must be less than or equal to
14976 // n_levels()-2.
14977 if (levels.size() >= 2)
14978 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
14979 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
14980 {
14981 for (unsigned int child = 0; child < cell->n_children(); ++child)
14982 {
14983 Assert(cell->child(child)->coarsen_flag_set(),
14985 cell->child(child)->clear_coarsen_flag();
14986 }
14987 // inform all listeners that cell coarsening is going to happen
14988 signals.pre_coarsening_on_cell(cell);
14989 // use a separate function, since this is dimension specific
14990 this->policy->delete_children(*this,
14991 cell,
14992 line_cell_count,
14993 quad_cell_count);
14994 }
14995
14996 // re-compute number of lines and quads
14998 *this, levels.size(), number_cache);
14999}
15000
15001
15002
15003template <int dim, int spacedim>
15006{
15007 // copy a piece of code from prepare_coarsening_and_refinement that
15008 // ensures that the level difference at vertices is limited if so
15009 // desired. we need this code here since at least in 1d we don't
15010 // call the dimension-independent version of
15011 // prepare_coarsening_and_refinement function. in 2d and 3d, having
15012 // this hunk here makes our lives a bit easier as well as it takes
15013 // care of these cases earlier than it would otherwise happen.
15014 //
15015 // the main difference to the code in p_c_and_r is that here we
15016 // absolutely have to make sure that we get things right, i.e. that
15017 // in particular we set flags right if
15018 // limit_level_difference_at_vertices is set. to do so we iterate
15019 // until the flags don't change any more
15020 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
15021
15022 bool continue_iterating = true;
15023
15024 do
15025 {
15026 if (smooth_grid & limit_level_difference_at_vertices)
15027 {
15028 Assert(!anisotropic_refinement,
15029 ExcMessage("In case of anisotropic refinement the "
15030 "limit_level_difference_at_vertices flag for "
15031 "mesh smoothing must not be set!"));
15032
15033 // store highest level one of the cells adjacent to a vertex
15034 // belongs to
15035 std::vector<int> vertex_level(vertices.size(), 0);
15036 for (const auto &cell : this->active_cell_iterators())
15037 {
15038 if (cell->refine_flag_set())
15039 for (const unsigned int vertex :
15041 vertex_level[cell->vertex_index(vertex)] =
15042 std::max(vertex_level[cell->vertex_index(vertex)],
15043 cell->level() + 1);
15044 else if (!cell->coarsen_flag_set())
15045 for (const unsigned int vertex :
15047 vertex_level[cell->vertex_index(vertex)] =
15048 std::max(vertex_level[cell->vertex_index(vertex)],
15049 cell->level());
15050 else
15051 {
15052 // if coarsen flag is set then tentatively assume
15053 // that the cell will be coarsened. this isn't
15054 // always true (the coarsen flag could be removed
15055 // again) and so we may make an error here. we try
15056 // to correct this by iterating over the entire
15057 // process until we are converged
15058 Assert(cell->coarsen_flag_set(), ExcInternalError());
15059 for (const unsigned int vertex :
15061 vertex_level[cell->vertex_index(vertex)] =
15062 std::max(vertex_level[cell->vertex_index(vertex)],
15063 cell->level() - 1);
15064 }
15065 }
15066
15067
15068 // loop over all cells in reverse order. do so because we
15069 // can then update the vertex levels on the adjacent
15070 // vertices and maybe already flag additional cells in this
15071 // loop
15072 //
15073 // note that not only may we have to add additional
15074 // refinement flags, but we will also have to remove
15075 // coarsening flags on cells adjacent to vertices that will
15076 // see refinement
15077 active_cell_iterator endc = end();
15078 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
15079 if (cell->refine_flag_set() == false)
15080 {
15081 for (const unsigned int vertex :
15083 if (vertex_level[cell->vertex_index(vertex)] >=
15084 cell->level() + 1)
15085 {
15086 // remove coarsen flag...
15087 cell->clear_coarsen_flag();
15088
15089 // ...and if necessary also refine the current
15090 // cell, at the same time updating the level
15091 // information about vertices
15092 if (vertex_level[cell->vertex_index(vertex)] >
15093 cell->level() + 1)
15094 {
15095 cell->set_refine_flag();
15096
15097 for (const unsigned int v :
15099 vertex_level[cell->vertex_index(v)] =
15100 std::max(vertex_level[cell->vertex_index(v)],
15101 cell->level() + 1);
15102 }
15103
15104 // continue and see whether we may, for example,
15105 // go into the inner 'if' above based on a
15106 // different vertex
15107 }
15108 }
15109 }
15110
15111 // loop over all cells and remove the coarsen flags for those cells that
15112 // have sister cells not marked for coarsening, or where some neighbors
15113 // are more refined.
15114
15115 // Coarsen flags of cells with no mother cell, i.e. on the
15116 // coarsest level, are deleted explicitly.
15117 for (const auto &acell : this->active_cell_iterators_on_level(0))
15118 acell->clear_coarsen_flag();
15119
15120 const cell_iterator endc = end();
15121 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
15122 {
15123 // nothing to do if we are already on the finest level
15124 if (cell->is_active())
15125 continue;
15126
15127 const unsigned int n_children = cell->n_children();
15128 unsigned int flagged_children = 0;
15129 for (unsigned int child = 0; child < n_children; ++child)
15130 {
15131 const auto child_cell = cell->child(child);
15132 if (child_cell->is_active() && child_cell->coarsen_flag_set())
15133 {
15134 ++flagged_children;
15135 // clear flag since we don't need it anymore
15136 child_cell->clear_coarsen_flag();
15137 }
15138 }
15139
15140 // flag the children for coarsening again if all children were
15141 // flagged and if the policy allows it
15142 if (flagged_children == n_children &&
15143 this->policy->coarsening_allowed(cell))
15144 for (unsigned int c = 0; c < n_children; ++c)
15145 {
15146 Assert(cell->child(c)->refine_flag_set() == false,
15148
15149 cell->child(c)->set_coarsen_flag();
15150 }
15151 }
15152
15153 // now see if anything has changed in the last iteration of this
15154 // function
15155 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
15156
15157 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
15158 previous_coarsen_flags.swap(current_coarsen_flags);
15159 }
15160 while (continue_iterating == true);
15161}
15162
15163
15164
15165// TODO: merge the following 3 functions since they are the same
15166template <>
15167bool
15169{
15170 // save the flags to determine whether something was changed in the
15171 // course of this function
15172 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
15173
15174 // do nothing in 1d, except setting the coarsening flags correctly
15175 fix_coarsen_flags();
15176
15177 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
15178
15179 return (flags_before != flags_after);
15180}
15181
15182
15183
15184template <>
15185bool
15187{
15188 // save the flags to determine whether something was changed in the
15189 // course of this function
15190 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
15191
15192 // do nothing in 1d, except setting the coarsening flags correctly
15193 fix_coarsen_flags();
15194
15195 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
15196
15197 return (flags_before != flags_after);
15198}
15199
15200
15201
15202template <>
15203bool
15205{
15206 // save the flags to determine whether something was changed in the
15207 // course of this function
15208 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
15209
15210 // do nothing in 1d, except setting the coarsening flags correctly
15211 fix_coarsen_flags();
15212
15213 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
15214
15215 return (flags_before != flags_after);
15216}
15217
15218
15219
15220namespace
15221{
15222 // check if the given @param cell marked for coarsening would
15223 // produce an unrefined island. To break up long chains of these
15224 // cells we recursively check our neighbors in case we change this
15225 // cell. This reduces the number of outer iterations dramatically.
15226 template <int dim, int spacedim>
15227 void
15228 possibly_do_not_produce_unrefined_islands(
15230 {
15231 Assert(cell->has_children(), ExcInternalError());
15232
15233 unsigned int n_neighbors = 0;
15234 // count all neighbors that will be refined along the face of our
15235 // cell after the next step
15236 unsigned int count = 0;
15237 for (const unsigned int n : GeometryInfo<dim>::face_indices())
15238 {
15239 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
15240 cell->neighbor(n);
15241 if (neighbor.state() == IteratorState::valid)
15242 {
15243 ++n_neighbors;
15244 if (face_will_be_refined_by_neighbor(cell, n))
15245 ++count;
15246 }
15247 }
15248 // clear coarsen flags if either all existing neighbors will be
15249 // refined or all but one will be and the cell is in the interior
15250 // of the domain
15251 if (count == n_neighbors ||
15252 (count >= n_neighbors - 1 &&
15253 n_neighbors == GeometryInfo<dim>::faces_per_cell))
15254 {
15255 for (unsigned int c = 0; c < cell->n_children(); ++c)
15256 cell->child(c)->clear_coarsen_flag();
15257
15258 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15259 if (!cell->at_boundary(face) &&
15260 (!cell->neighbor(face)->is_active()) &&
15261 (cell_will_be_coarsened(cell->neighbor(face))))
15262 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
15263 cell->neighbor(face));
15264 }
15265 }
15266
15267
15268 // see if the current cell needs to be refined to avoid unrefined
15269 // islands.
15270 //
15271 // there are sometimes chains of cells that induce refinement of
15272 // each other. to avoid running the loop in
15273 // prepare_coarsening_and_refinement over and over again for each
15274 // one of them, at least for the isotropic refinement case we seek
15275 // to flag neighboring elements as well as necessary. this takes
15276 // care of (slightly pathological) cases like
15277 // deal.II/mesh_smoothing_03
15278 template <int dim, int spacedim>
15279 void
15280 possibly_refine_unrefined_island(
15282 const bool allow_anisotropic_smoothing)
15283 {
15284 Assert(cell->is_active(), ExcInternalError());
15285 Assert(cell->refine_flag_set() == false, ExcInternalError());
15286
15287
15288 // now we provide two algorithms. the first one is the standard
15289 // one, coming from the time, where only isotropic refinement was
15290 // possible. it simply counts the neighbors that are or will be
15291 // refined and compares to the number of other ones. the second
15292 // one does this check independently for each direction: if all
15293 // neighbors in one direction (normally two, at the boundary only
15294 // one) are refined, the current cell is flagged to be refined in
15295 // an according direction.
15296
15297 if (allow_anisotropic_smoothing == false)
15298 {
15299 // use first algorithm
15300 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
15301 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15302 if (!cell->at_boundary(face))
15303 {
15304 if (face_will_be_refined_by_neighbor(cell, face))
15305 ++refined_neighbors;
15306 else
15307 ++unrefined_neighbors;
15308 }
15309
15310 if (unrefined_neighbors < refined_neighbors)
15311 {
15312 cell->clear_coarsen_flag();
15313 cell->set_refine_flag();
15314
15315 // ok, so now we have flagged this cell. if we know that
15316 // there were any unrefined neighbors at all, see if any
15317 // of those will have to be refined as well
15318 if (unrefined_neighbors > 0)
15319 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15320 if (!cell->at_boundary(face) &&
15321 (face_will_be_refined_by_neighbor(cell, face) == false) &&
15322 (cell->neighbor(face)->has_children() == false) &&
15323 (cell->neighbor(face)->refine_flag_set() == false))
15324 possibly_refine_unrefined_island<dim, spacedim>(
15325 cell->neighbor(face), allow_anisotropic_smoothing);
15326 }
15327 }
15328 else
15329 {
15330 // variable to store the cell refine case needed to fulfill
15331 // all smoothing requirements
15332 RefinementCase<dim> smoothing_cell_refinement_case =
15334
15335 // use second algorithm, do the check individually for each
15336 // direction
15337 for (unsigned int face_pair = 0;
15338 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
15339 ++face_pair)
15340 {
15341 // variable to store the cell refine case needed to refine
15342 // at the current face pair in the same way as the
15343 // neighbors do...
15344 RefinementCase<dim> directional_cell_refinement_case =
15346
15347 for (unsigned int face_index = 0; face_index < 2; ++face_index)
15348 {
15349 unsigned int face = 2 * face_pair + face_index;
15350 // variable to store the refine case (to come) of the
15351 // face under consideration
15352 RefinementCase<dim - 1> expected_face_ref_case =
15353 RefinementCase<dim - 1>::no_refinement;
15354
15355 if (cell->neighbor(face).state() == IteratorState::valid)
15356 face_will_be_refined_by_neighbor<dim, spacedim>(
15357 cell, face, expected_face_ref_case);
15358 // now extract which refine case would be necessary to
15359 // achieve the same face refinement. set the
15360 // intersection with other requirements for the same
15361 // direction.
15362
15363 // note: using the intersection is not an obvious
15364 // decision, we could also argue that it is more
15365 // natural to use the union. however, intersection is
15366 // the less aggressive tactic and favours a smaller
15367 // number of refined cells over an intensive
15368 // smoothing. this way we try not to lose too much of
15369 // the effort we put in anisotropic refinement
15370 // indicators due to overly aggressive smoothing...
15371 directional_cell_refinement_case =
15372 (directional_cell_refinement_case &
15375 expected_face_ref_case,
15376 face,
15377 cell->face_orientation(face),
15378 cell->face_flip(face),
15379 cell->face_rotation(face)));
15380 } // for both face indices
15381 // if both requirements sum up to something useful, add
15382 // this to the refine case for smoothing. note: if
15383 // directional_cell_refinement_case is isotropic still,
15384 // then something went wrong...
15385 Assert(directional_cell_refinement_case <
15388 smoothing_cell_refinement_case =
15389 smoothing_cell_refinement_case | directional_cell_refinement_case;
15390 } // for all face_pairs
15391 // no we collected contributions from all directions. combine
15392 // the new flags with the existing refine case, but only if
15393 // smoothing is required
15394 if (smoothing_cell_refinement_case)
15395 {
15396 cell->clear_coarsen_flag();
15397 cell->set_refine_flag(cell->refine_flag_set() |
15398 smoothing_cell_refinement_case);
15399 }
15400 }
15401 }
15402} // namespace
15403
15404
15405template <int dim, int spacedim>
15408{
15409 // save the flags to determine whether something was changed in the
15410 // course of this function
15411 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
15412 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
15413
15414 // save the flags at the outset of each loop. we do so in order to
15415 // find out whether something was changed in the present loop, in
15416 // which case we would have to re-run the loop. the other
15417 // possibility to find this out would be to set a flag
15418 // @p{something_changed} to true each time we change something.
15419 // however, sometimes one change in one of the parts of the loop is
15420 // undone by another one, so we might end up in an endless loop. we
15421 // could be tempted to break this loop at an arbitrary number of
15422 // runs, but that would not be a clean solution, since we would
15423 // either have to 1/ break the loop too early, in which case the
15424 // promise that a second call to this function immediately after the
15425 // first one does not change anything, would be broken, or 2/ we do
15426 // as many loops as there are levels. we know that information is
15427 // transported over one level in each run of the loop, so this is
15428 // enough. Unfortunately, each loop is rather expensive, so we chose
15429 // the way presented here
15430 auto coarsen_flags_before_loop = coarsen_flags_before;
15431 auto refine_flags_before_loop = refine_flags_before;
15432
15433 // now for what is done in each loop: we have to fulfill several
15434 // tasks at the same time, namely several mesh smoothing algorithms
15435 // and mesh regularization, by which we mean that the next mesh
15436 // fulfills several requirements such as no double refinement at
15437 // each face or line, etc.
15438 //
15439 // since doing these things at once seems almost impossible (in the
15440 // first year of this library, they were done in two functions, one
15441 // for refinement and one for coarsening, and most things within
15442 // these were done at once, so the code was rather impossible to
15443 // join into this, only, function), we do them one after each
15444 // other. the order in which we do them is such that the important
15445 // tasks, namely regularization, are done last and the least
15446 // important things are done the first. the following order is
15447 // chosen:
15448 //
15449 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
15450 // coarsen flags on level 1 to avoid level 0 cells being created
15451 // by coarsening. As coarsen flags will never be added, this can
15452 // be done once and for all before the actual loop starts.
15453 //
15454 // 1/ do not coarsen a cell if 'most of the neighbors' will be
15455 // refined after the step. This is to prevent occurrence of
15456 // unrefined islands.
15457 //
15458 // 2/ eliminate refined islands in the interior and at the
15459 // boundary. since they don't do much harm besides increasing the
15460 // number of degrees of freedom, doing this has a rather low
15461 // priority.
15462 //
15463 // 3/ limit the level difference of neighboring cells at each
15464 // vertex.
15465 //
15466 // 4/ eliminate unrefined islands. this has higher priority since
15467 // this diminishes the approximation properties not only of the
15468 // unrefined island, but also of the surrounding patch.
15469 //
15470 // 5/ ensure patch level 1. Then the triangulation consists of
15471 // patches, i.e. of cells that are refined once. It follows that
15472 // if at least one of the children of a cell is or will be
15473 // refined than all children need to be refined. This step only
15474 // sets refinement flags and does not set coarsening flags. If
15475 // the patch_level_1 flag is set, then
15476 // eliminate_unrefined_islands, eliminate_refined_inner_islands
15477 // and eliminate_refined_boundary_islands will be fulfilled
15478 // automatically and do not need to be enforced separately.
15479 //
15480 // 6/ take care of the requirement that no double refinement is done
15481 // at each face
15482 //
15483 // 7/ take care that no double refinement is done at each line in 3d
15484 // or higher dimensions.
15485 //
15486 // 8/ make sure that all children of each cell are either flagged
15487 // for coarsening or none of the children is
15488 //
15489 // For some of these steps, it is known that they interact. Namely,
15490 // it is not possible to guarantee that after step 6 another step 5
15491 // would have no effect; the same holds for the opposite order and
15492 // also when taking into account step 7. however, it is important to
15493 // guarantee that step five or six do not undo something that step 5
15494 // did, and step 7 not something of step 6, otherwise the
15495 // requirements will not be satisfied even if the loop
15496 // terminates. this is accomplished by the fact that steps 5 and 6
15497 // only *add* refinement flags and delete coarsening flags
15498 // (therefore, step 6 can't undo something that step 4 already did),
15499 // and step 7 only deletes coarsening flags, never adds some. step 7
15500 // needs also take care that it won't tag cells for refinement for
15501 // which some neighbors are more refined or will be refined.
15502
15503 //------------------------------------
15504 // STEP 0:
15505 // Only if coarsest_level_1 or patch_level_1 is set: clear all
15506 // coarsen flags on level 1 to avoid level 0 cells being created
15507 // by coarsening.
15508 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
15509 n_levels() >= 2)
15510 {
15511 for (const auto &cell : active_cell_iterators_on_level(1))
15512 cell->clear_coarsen_flag();
15513 }
15514
15515 bool mesh_changed_in_this_loop = false;
15516 do
15517 {
15518 //------------------------------------
15519 // STEP 1:
15520 // do not coarsen a cell if 'most of the neighbors' will be
15521 // refined after the step. This is to prevent the occurrence
15522 // of unrefined islands. If patch_level_1 is set, this will
15523 // be automatically fulfilled.
15524 if (smooth_grid & do_not_produce_unrefined_islands &&
15525 !(smooth_grid & patch_level_1))
15526 {
15527 for (const auto &cell : cell_iterators())
15528 {
15529 // only do something if this
15530 // cell will be coarsened
15531 if (!cell->is_active() && cell_will_be_coarsened(cell))
15532 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
15533 }
15534 }
15535
15536
15537 //------------------------------------
15538 // STEP 2:
15539 // eliminate refined islands in the interior and at the
15540 // boundary. since they don't do much harm besides increasing
15541 // the number of degrees of freedom, doing this has a rather
15542 // low priority. If patch_level_1 is set, this will be
15543 // automatically fulfilled.
15544 //
15545 // there is one corner case to consider: if this is a
15546 // distributed triangulation, there may be refined islands on
15547 // the boundary of which we own only part (e.g. a single cell
15548 // in the corner of a domain). the rest of the island is
15549 // ghost cells and it *looks* like the area around it
15550 // (artificial cells) are coarser but this is only because
15551 // they may actually be equally fine on other
15552 // processors. it's hard to detect this case but we can do
15553 // the following: only set coarsen flags to remove this
15554 // refined island if all cells we want to set flags on are
15555 // locally owned
15556 if (smooth_grid & (eliminate_refined_inner_islands |
15557 eliminate_refined_boundary_islands) &&
15558 !(smooth_grid & patch_level_1))
15559 {
15560 for (const auto &cell : cell_iterators())
15561 if (!cell->is_active() ||
15562 (cell->is_active() && cell->refine_flag_set() &&
15563 cell->is_locally_owned()))
15564 {
15565 // check whether all children are active, i.e. not
15566 // refined themselves. This is a precondition that the
15567 // children may be coarsened away. If the cell is only
15568 // flagged for refinement, then all future children
15569 // will be active
15570 bool all_children_active = true;
15571 if (!cell->is_active())
15572 for (unsigned int c = 0; c < cell->n_children(); ++c)
15573 if (!cell->child(c)->is_active() ||
15574 cell->child(c)->is_ghost() ||
15575 cell->child(c)->is_artificial())
15576 {
15577 all_children_active = false;
15578 break;
15579 }
15580
15581 if (all_children_active)
15582 {
15583 // count number of refined and unrefined neighbors
15584 // of cell. neighbors on lower levels are counted
15585 // as unrefined since they can only get to the
15586 // same level as this cell by the next refinement
15587 // cycle
15588 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
15589
15590 // Keep track if this cell is at a periodic
15591 // boundary or not. TODO: We do not currently run
15592 // the algorithm for inner islands at a periodic
15593 // boundary (remains to be implemented), but we
15594 // also don't want to consider them
15595 // boundary_island cells as this can interfere
15596 // with 2:1 refinement across periodic faces.
15597 // Instead: just ignore those cells for this
15598 // smoothing operation below.
15599 bool at_periodic_boundary = false;
15600
15601 for (const unsigned int n :
15602 GeometryInfo<dim>::face_indices())
15603 {
15604 const cell_iterator neighbor = cell->neighbor(n);
15605 if (neighbor.state() == IteratorState::valid)
15606 {
15607 ++total_neighbors;
15608
15609 if (!face_will_be_refined_by_neighbor(cell, n))
15610 ++unrefined_neighbors;
15611 }
15612 else if (cell->has_periodic_neighbor(n))
15613 {
15614 ++total_neighbors;
15615 at_periodic_boundary = true;
15616 }
15617 }
15618
15619 // if all neighbors unrefined: mark this cell for
15620 // coarsening or don't refine if marked for that
15621 //
15622 // also do the distinction between the two
15623 // versions of the eliminate_refined_*_islands
15624 // flag
15625 //
15626 // the last check is whether there are any
15627 // neighbors at all. if not so, then we are (e.g.)
15628 // on the coarsest grid with one cell, for which,
15629 // of course, we do not remove the refine flag.
15630 if ((unrefined_neighbors == total_neighbors) &&
15631 ((!cell->at_boundary() &&
15632 (smooth_grid & eliminate_refined_inner_islands)) ||
15633 (cell->at_boundary() && !at_periodic_boundary &&
15634 (smooth_grid &
15635 eliminate_refined_boundary_islands))) &&
15636 (total_neighbors != 0))
15637 {
15638 if (!cell->is_active())
15639 for (unsigned int c = 0; c < cell->n_children(); ++c)
15640 {
15641 cell->child(c)->clear_refine_flag();
15642 cell->child(c)->set_coarsen_flag();
15643 }
15644 else
15645 cell->clear_refine_flag();
15646 }
15647 }
15648 }
15649 }
15650
15651 //------------------------------------
15652 // STEP 3:
15653 // limit the level difference of neighboring cells at each
15654 // vertex.
15655 //
15656 // in case of anisotropic refinement this does not make
15657 // sense. as soon as one cell is anisotropically refined, an
15658 // Assertion is thrown. therefore we can ignore this problem
15659 // later on
15660 if (smooth_grid & limit_level_difference_at_vertices)
15661 {
15662 Assert(!anisotropic_refinement,
15663 ExcMessage("In case of anisotropic refinement the "
15664 "limit_level_difference_at_vertices flag for "
15665 "mesh smoothing must not be set!"));
15666
15667 // store highest level one of the cells adjacent to a vertex
15668 // belongs to
15669 std::vector<int> vertex_level(vertices.size(), 0);
15670 for (const auto &cell : active_cell_iterators())
15671 {
15672 if (cell->refine_flag_set())
15673 for (const unsigned int vertex :
15675 vertex_level[cell->vertex_index(vertex)] =
15676 std::max(vertex_level[cell->vertex_index(vertex)],
15677 cell->level() + 1);
15678 else if (!cell->coarsen_flag_set())
15679 for (const unsigned int vertex :
15681 vertex_level[cell->vertex_index(vertex)] =
15682 std::max(vertex_level[cell->vertex_index(vertex)],
15683 cell->level());
15684 else
15685 {
15686 // if coarsen flag is set then tentatively assume
15687 // that the cell will be coarsened. this isn't
15688 // always true (the coarsen flag could be removed
15689 // again) and so we may make an error here
15690 Assert(cell->coarsen_flag_set(), ExcInternalError());
15691 for (const unsigned int vertex :
15693 vertex_level[cell->vertex_index(vertex)] =
15694 std::max(vertex_level[cell->vertex_index(vertex)],
15695 cell->level() - 1);
15696 }
15697 }
15698
15699
15700 // loop over all cells in reverse order. do so because we
15701 // can then update the vertex levels on the adjacent
15702 // vertices and maybe already flag additional cells in this
15703 // loop
15704 //
15705 // note that not only may we have to add additional
15706 // refinement flags, but we will also have to remove
15707 // coarsening flags on cells adjacent to vertices that will
15708 // see refinement
15709 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
15710 if (cell->refine_flag_set() == false)
15711 {
15712 for (const unsigned int vertex :
15714 if (vertex_level[cell->vertex_index(vertex)] >=
15715 cell->level() + 1)
15716 {
15717 // remove coarsen flag...
15718 cell->clear_coarsen_flag();
15719
15720 // ...and if necessary also refine the current
15721 // cell, at the same time updating the level
15722 // information about vertices
15723 if (vertex_level[cell->vertex_index(vertex)] >
15724 cell->level() + 1)
15725 {
15726 cell->set_refine_flag();
15727
15728 for (const unsigned int v :
15730 vertex_level[cell->vertex_index(v)] =
15731 std::max(vertex_level[cell->vertex_index(v)],
15732 cell->level() + 1);
15733 }
15734
15735 // continue and see whether we may, for example,
15736 // go into the inner'if'
15737 // above based on a
15738 // different vertex
15739 }
15740 }
15741 }
15742
15743 //-----------------------------------
15744 // STEP 4:
15745 // eliminate unrefined islands. this has higher priority
15746 // since this diminishes the approximation properties not
15747 // only of the unrefined island, but also of the surrounding
15748 // patch.
15749 //
15750 // do the loop from finest to coarsest cells since we may
15751 // trigger a cascade by marking cells for refinement which
15752 // may trigger more cells further down below
15753 if (smooth_grid & eliminate_unrefined_islands)
15754 {
15755 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
15756 // only do something if cell is not already flagged for
15757 // (isotropic) refinement
15758 if (cell->refine_flag_set() !=
15760 possibly_refine_unrefined_island<dim, spacedim>(
15761 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
15762 }
15763
15764 //-------------------------------
15765 // STEP 5:
15766 // ensure patch level 1.
15767 //
15768 // Introduce some terminology:
15769 // - a cell that is refined
15770 // once is a patch of
15771 // level 1 simply called patch.
15772 // - a cell that is globally
15773 // refined twice is called
15774 // a patch of level 2.
15775 // - patch level n says that
15776 // the triangulation consists
15777 // of patches of level n.
15778 // This makes sense only
15779 // if the grid is already at
15780 // least n times globally
15781 // refined.
15782 //
15783 // E.g. from patch level 1 follows: if at least one of the
15784 // children of a cell is or will be refined than enforce all
15785 // children to be refined.
15786
15787 // This step 4 only sets refinement flags and does not set
15788 // coarsening flags.
15789 if (smooth_grid & patch_level_1)
15790 {
15791 // An important assumption (A) is that before calling this
15792 // function the grid was already of patch level 1.
15793
15794 // loop over all cells whose children are all active. (By
15795 // assumption (A) either all or none of the children are
15796 // active). If the refine flag of at least one of the
15797 // children is set then set_refine_flag and
15798 // clear_coarsen_flag of all children.
15799 for (const auto &cell : cell_iterators())
15800 if (!cell->is_active())
15801 {
15802 // ensure the invariant. we can then check whether all
15803 // of its children are further refined or not by
15804 // simply looking at the first child
15805 Assert(cell_is_patch_level_1(cell), ExcInternalError());
15806 if (cell->child(0)->has_children() == true)
15807 continue;
15808
15809 // cell is found to be a patch. combine the refine
15810 // cases of all children
15811 RefinementCase<dim> combined_ref_case =
15813 for (unsigned int i = 0; i < cell->n_children(); ++i)
15814 combined_ref_case =
15815 combined_ref_case | cell->child(i)->refine_flag_set();
15816 if (combined_ref_case != RefinementCase<dim>::no_refinement)
15817 for (unsigned int i = 0; i < cell->n_children(); ++i)
15818 {
15819 cell_iterator child = cell->child(i);
15820
15821 child->clear_coarsen_flag();
15822 child->set_refine_flag(combined_ref_case);
15823 }
15824 }
15825
15826 // The code above dealt with the case where we may get a
15827 // non-patch_level_1 mesh from refinement. Now also deal
15828 // with the case where we could get such a mesh by
15829 // coarsening. Coarsen the children (and remove the
15830 // grandchildren) only if all cell->grandchild(i)
15831 // ->coarsen_flag_set() are set.
15832 //
15833 // for a case where this is a bit tricky, take a look at the
15834 // mesh_smoothing_0[12] testcases
15835 for (const auto &cell : cell_iterators())
15836 {
15837 // check if this cell has active grandchildren. note
15838 // that we know that it is patch_level_1, i.e. if one of
15839 // its children is active then so are all, and it isn't
15840 // going to have any grandchildren at all:
15841 if (cell->is_active() || cell->child(0)->is_active())
15842 continue;
15843
15844 // cell is not active, and so are none of its
15845 // children. check the grandchildren. note that the
15846 // children are also patch_level_1, and so we only ever
15847 // need to check their first child
15848 const unsigned int n_children = cell->n_children();
15849 bool has_active_grandchildren = false;
15850
15851 for (unsigned int i = 0; i < n_children; ++i)
15852 if (cell->child(i)->child(0)->is_active())
15853 {
15854 has_active_grandchildren = true;
15855 break;
15856 }
15857
15858 if (has_active_grandchildren == false)
15859 continue;
15860
15861
15862 // ok, there are active grandchildren. see if either all
15863 // or none of them are flagged for coarsening
15864 unsigned int n_grandchildren = 0;
15865
15866 // count all coarsen flags of the grandchildren.
15867 unsigned int n_coarsen_flags = 0;
15868
15869 // cell is not a patch (of level 1) as it has a
15870 // grandchild. Is cell a patch of level 2?? Therefore:
15871 // find out whether all cell->child(i) are patches
15872 for (unsigned int c = 0; c < n_children; ++c)
15873 {
15874 // get at the child. by assumption (A), and the
15875 // check by which we got here, the child is not
15876 // active
15877 cell_iterator child = cell->child(c);
15878
15879 const unsigned int nn_children = child->n_children();
15880 n_grandchildren += nn_children;
15881
15882 // if child is found to be a patch of active cells
15883 // itself, then add up how many of its children are
15884 // supposed to be coarsened
15885 if (child->child(0)->is_active())
15886 for (unsigned int cc = 0; cc < nn_children; ++cc)
15887 if (child->child(cc)->coarsen_flag_set())
15888 ++n_coarsen_flags;
15889 }
15890
15891 // if not all grandchildren are supposed to be coarsened
15892 // (e.g. because some simply don't have the flag set, or
15893 // because they are not active and therefore cannot
15894 // carry the flag), then remove the coarsen flag from
15895 // all of the active grandchildren. note that there may
15896 // be coarsen flags on the grandgrandchildren -- we
15897 // don't clear them here, but we'll get to them in later
15898 // iterations if necessary
15899 //
15900 // there is nothing we have to do if no coarsen flags
15901 // have been set at all
15902 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
15903 for (unsigned int c = 0; c < n_children; ++c)
15904 {
15905 const cell_iterator child = cell->child(c);
15906 if (child->child(0)->is_active())
15907 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
15908 child->child(cc)->clear_coarsen_flag();
15909 }
15910 }
15911 }
15912
15913 //--------------------------------
15914 //
15915 // at the boundary we could end up with cells with negative
15916 // volume or at least with a part, that is negative, if the
15917 // cell is refined anisotropically. we have to check, whether
15918 // that can happen
15919 this->policy->prevent_distorted_boundary_cells(*this);
15920
15921 //-------------------------------
15922 // STEP 6:
15923 // take care of the requirement that no
15924 // double refinement is done at each face
15925 //
15926 // in case of anisotropic refinement it is only likely, but
15927 // not sure, that the cells, which are more refined along a
15928 // certain face common to two cells are on a higher
15929 // level. therefore we cannot be sure, that the requirement
15930 // of no double refinement is fulfilled after a single pass
15931 // of the following actions. We could just wait for the next
15932 // global loop. when this function terminates, the
15933 // requirement will be fulfilled. However, it might be faster
15934 // to insert an inner loop here.
15935 bool changed = true;
15936 while (changed)
15937 {
15938 changed = false;
15939 active_cell_iterator cell = last_active(), endc = end();
15940
15941 for (; cell != endc; --cell)
15942 if (cell->refine_flag_set())
15943 {
15944 // loop over neighbors of cell
15945 for (const auto i : cell->face_indices())
15946 {
15947 // only do something if the face is not at the
15948 // boundary and if the face will be refined with
15949 // the RefineCase currently flagged for
15950 const bool has_periodic_neighbor =
15951 cell->has_periodic_neighbor(i);
15952 const bool has_neighbor_or_periodic_neighbor =
15953 !cell->at_boundary(i) || has_periodic_neighbor;
15954 if (has_neighbor_or_periodic_neighbor &&
15956 cell->refine_flag_set(), i) !=
15958 {
15959 // 1) if the neighbor has children: nothing to
15960 // worry about. 2) if the neighbor is active
15961 // and a coarser one, ensure, that its
15962 // refine_flag is set 3) if the neighbor is
15963 // active and as refined along the face as our
15964 // current cell, make sure, that no
15965 // coarsen_flag is set. if we remove the
15966 // coarsen flag of our neighbor,
15967 // fix_coarsen_flags() makes sure, that the
15968 // mother cell will not be coarsened
15969 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
15970 {
15971 if ((!has_periodic_neighbor &&
15972 cell->neighbor_is_coarser(i)) ||
15973 (has_periodic_neighbor &&
15974 cell->periodic_neighbor_is_coarser(i)))
15975 {
15976 if (cell->neighbor_or_periodic_neighbor(i)
15977 ->coarsen_flag_set())
15978 cell->neighbor_or_periodic_neighbor(i)
15979 ->clear_coarsen_flag();
15980 // we'll set the refine flag for this
15981 // neighbor below. we note, that we
15982 // have changed something by setting
15983 // the changed flag to true. We do not
15984 // need to do so, if we just removed
15985 // the coarsen flag, as the changed
15986 // flag only indicates the need to
15987 // re-run the inner loop. however, we
15988 // only loop over cells flagged for
15989 // refinement here, so nothing to
15990 // worry about if we remove coarsen
15991 // flags
15992
15993 if (dim == 2)
15994 {
15995 if (smooth_grid &
15996 allow_anisotropic_smoothing)
15997 changed =
15998 has_periodic_neighbor ?
15999 cell->periodic_neighbor(i)
16000 ->flag_for_face_refinement(
16001 cell
16002 ->periodic_neighbor_of_coarser_periodic_neighbor(
16003 i)
16004 .first,
16006 cell->neighbor(i)
16007 ->flag_for_face_refinement(
16008 cell
16009 ->neighbor_of_coarser_neighbor(
16010 i)
16011 .first,
16013 else
16014 {
16015 if (!cell
16016 ->neighbor_or_periodic_neighbor(
16017 i)
16018 ->refine_flag_set())
16019 changed = true;
16020 cell->neighbor_or_periodic_neighbor(i)
16021 ->set_refine_flag();
16022 }
16023 }
16024 else // i.e. if (dim==3)
16025 {
16026 // ugly situations might arise here,
16027 // consider the following situation, which
16028 // shows neighboring cells at the common
16029 // face, where the upper right element is
16030 // coarser at the given face. Now the upper
16031 // child element of the lower left wants to
16032 // refine according to cut_z, such that
16033 // there is a 'horizontal' refinement of the
16034 // face marked with #####
16035 //
16036 // / /
16037 // / /
16038 // *---------------*
16039 // | |
16040 // | |
16041 // | |
16042 // | |
16043 // | |
16044 // | | /
16045 // | |/
16046 // *---------------*
16047 //
16048 //
16049 // *---------------*
16050 // /| /|
16051 // / | ##### / |
16052 // | |
16053 // *---------------*
16054 // /| /|
16055 // / | / |
16056 // | |
16057 // *---------------*
16058 // / /
16059 // / /
16060 //
16061 // this introduces too many hanging nodes
16062 // and the neighboring (coarser) cell (upper
16063 // right) has to be refined. If it is only
16064 // refined according to cut_z, then
16065 // everything is ok:
16066 //
16067 // / /
16068 // / /
16069 // *---------------*
16070 // | |
16071 // | | /
16072 // | |/
16073 // *---------------*
16074 // | |
16075 // | | /
16076 // | |/
16077 // *---------------*
16078 //
16079 //
16080 // *---------------*
16081 // /| /|
16082 // / *---------------*
16083 // /| /|
16084 // *---------------*
16085 // /| /|
16086 // / | / |
16087 // | |
16088 // *---------------*
16089 // / /
16090 // / /
16091 //
16092 // if however the cell wants to refine
16093 // itself in an other way, or if we disallow
16094 // anisotropic smoothing, then simply
16095 // refining the neighbor isotropically is
16096 // not going to work, since this introduces
16097 // a refinement of face ##### with both
16098 // cut_x and cut_y, which is not possible:
16099 //
16100 // / / /
16101 // / / /
16102 // *-------*-------*
16103 // | | |
16104 // | | | /
16105 // | | |/
16106 // *-------*-------*
16107 // | | |
16108 // | | | /
16109 // | | |/
16110 // *-------*-------*
16111 //
16112 //
16113 // *---------------*
16114 // /| /|
16115 // / *---------------*
16116 // /| /|
16117 // *---------------*
16118 // /| /|
16119 // / | / |
16120 // | |
16121 // *---------------*
16122 // / /
16123 // / /
16124 //
16125 // thus, in this case we also need to refine
16126 // our current cell in the new direction:
16127 //
16128 // / / /
16129 // / / /
16130 // *-------*-------*
16131 // | | |
16132 // | | | /
16133 // | | |/
16134 // *-------*-------*
16135 // | | |
16136 // | | | /
16137 // | | |/
16138 // *-------*-------*
16139 //
16140 //
16141 // *-------*-------*
16142 // /| /| /|
16143 // / *-------*-------*
16144 // /| /| /|
16145 // *-------*-------*
16146 // /| / /|
16147 // / | / |
16148 // | |
16149 // *---------------*
16150 // / /
16151 // / /
16152
16153 std::pair<unsigned int, unsigned int>
16154 nb_indices =
16155 has_periodic_neighbor ?
16156 cell
16157 ->periodic_neighbor_of_coarser_periodic_neighbor(
16158 i) :
16159 cell->neighbor_of_coarser_neighbor(i);
16160 unsigned int refined_along_x = 0,
16161 refined_along_y = 0,
16162 to_be_refined_along_x = 0,
16163 to_be_refined_along_y = 0;
16164
16165 const int this_face_index =
16166 cell->face_index(i);
16167
16168 // step 1: detect, along which axis the face
16169 // is currently refined
16170
16171 // first, we need an iterator pointing to
16172 // the parent face. This requires a slight
16173 // detour in case the neighbor is behind a
16174 // periodic face.
16175 const auto parent_face = [&]() {
16176 if (has_periodic_neighbor)
16177 {
16178 const auto neighbor =
16179 cell->periodic_neighbor(i);
16180 const auto parent_face_no =
16181 neighbor
16182 ->periodic_neighbor_of_periodic_neighbor(
16183 nb_indices.first);
16184 auto parent =
16185 neighbor->periodic_neighbor(
16186 nb_indices.first);
16187 return parent->face(parent_face_no);
16188 }
16189 else
16190 return cell->neighbor(i)->face(
16191 nb_indices.first);
16192 }();
16193
16194 if ((this_face_index ==
16195 parent_face->child_index(0)) ||
16196 (this_face_index ==
16197 parent_face->child_index(1)))
16198 {
16199 // this might be an
16200 // anisotropic child. get the
16201 // face refine case of the
16202 // neighbors face and count
16203 // refinements in x and y
16204 // direction.
16205 RefinementCase<dim - 1> frc =
16206 parent_face->refinement_case();
16208 ++refined_along_x;
16210 ++refined_along_y;
16211 }
16212 else
16213 // this has to be an isotropic
16214 // child
16215 {
16216 ++refined_along_x;
16217 ++refined_along_y;
16218 }
16219 // step 2: detect, along which axis the face
16220 // has to be refined given the current
16221 // refine flag
16222 RefinementCase<dim - 1> flagged_frc =
16224 cell->refine_flag_set(),
16225 i,
16226 cell->face_orientation(i),
16227 cell->face_flip(i),
16228 cell->face_rotation(i));
16229 if (flagged_frc &
16231 ++to_be_refined_along_x;
16232 if (flagged_frc &
16234 ++to_be_refined_along_y;
16235
16236 // step 3: set the refine flag of the
16237 // (coarser and active) neighbor.
16238 if ((smooth_grid &
16239 allow_anisotropic_smoothing) ||
16240 cell->neighbor_or_periodic_neighbor(i)
16241 ->refine_flag_set())
16242 {
16243 if (refined_along_x +
16244 to_be_refined_along_x >
16245 1)
16246 changed |=
16247 cell
16248 ->neighbor_or_periodic_neighbor(i)
16249 ->flag_for_face_refinement(
16250 nb_indices.first,
16251 RefinementCase<dim -
16252 1>::cut_axis(0));
16253 if (refined_along_y +
16254 to_be_refined_along_y >
16255 1)
16256 changed |=
16257 cell
16258 ->neighbor_or_periodic_neighbor(i)
16259 ->flag_for_face_refinement(
16260 nb_indices.first,
16261 RefinementCase<dim -
16262 1>::cut_axis(1));
16263 }
16264 else
16265 {
16266 if (cell
16267 ->neighbor_or_periodic_neighbor(i)
16268 ->refine_flag_set() !=
16270 dim>::isotropic_refinement)
16271 changed = true;
16272 cell->neighbor_or_periodic_neighbor(i)
16273 ->set_refine_flag();
16274 }
16275
16276 // step 4: if necessary (see above) add to
16277 // the refine flag of the current cell
16278 cell_iterator nb =
16279 cell->neighbor_or_periodic_neighbor(i);
16280 RefinementCase<dim - 1> nb_frc =
16282 nb->refine_flag_set(),
16283 nb_indices.first,
16284 nb->face_orientation(nb_indices.first),
16285 nb->face_flip(nb_indices.first),
16286 nb->face_rotation(nb_indices.first));
16287 if ((nb_frc & RefinementCase<dim>::cut_x) &&
16288 !((refined_along_x != 0u) ||
16289 (to_be_refined_along_x != 0u)))
16290 changed |= cell->flag_for_face_refinement(
16291 i,
16293 if ((nb_frc & RefinementCase<dim>::cut_y) &&
16294 !((refined_along_y != 0u) ||
16295 (to_be_refined_along_y != 0u)))
16296 changed |= cell->flag_for_face_refinement(
16297 i,
16299 }
16300 } // if neighbor is coarser
16301 else // -> now the neighbor is not coarser
16302 {
16303 cell->neighbor_or_periodic_neighbor(i)
16304 ->clear_coarsen_flag();
16305 const unsigned int nb_nb =
16306 has_periodic_neighbor ?
16307 cell
16308 ->periodic_neighbor_of_periodic_neighbor(
16309 i) :
16310 cell->neighbor_of_neighbor(i);
16311 const cell_iterator neighbor =
16312 cell->neighbor_or_periodic_neighbor(i);
16313 RefinementCase<dim - 1> face_ref_case =
16315 neighbor->refine_flag_set(),
16316 nb_nb,
16317 neighbor->face_orientation(nb_nb),
16318 neighbor->face_flip(nb_nb),
16319 neighbor->face_rotation(nb_nb));
16320 RefinementCase<dim - 1> needed_face_ref_case =
16322 cell->refine_flag_set(),
16323 i,
16324 cell->face_orientation(i),
16325 cell->face_flip(i),
16326 cell->face_rotation(i));
16327 // if the neighbor wants to refine the
16328 // face with cut_x and we want cut_y
16329 // or vice versa, we have to refine
16330 // isotropically at the given face
16331 if ((face_ref_case ==
16333 needed_face_ref_case ==
16335 (face_ref_case ==
16337 needed_face_ref_case ==
16339 {
16340 changed = cell->flag_for_face_refinement(
16341 i, face_ref_case);
16342 neighbor->flag_for_face_refinement(
16343 nb_nb, needed_face_ref_case);
16344 }
16345 }
16346 }
16347 else //-> the neighbor is not active
16348 {
16349 RefinementCase<dim - 1>
16350 face_ref_case = cell->face(i)->refinement_case(),
16351 needed_face_ref_case =
16353 cell->refine_flag_set(),
16354 i,
16355 cell->face_orientation(i),
16356 cell->face_flip(i),
16357 cell->face_rotation(i));
16358 // if the face is refined with cut_x and
16359 // we want cut_y or vice versa, we have to
16360 // refine isotropically at the given face
16361 if ((face_ref_case == RefinementCase<dim>::cut_x &&
16362 needed_face_ref_case ==
16364 (face_ref_case == RefinementCase<dim>::cut_y &&
16365 needed_face_ref_case ==
16367 changed =
16368 cell->flag_for_face_refinement(i,
16369 face_ref_case);
16370 }
16371 }
16372 }
16373 }
16374 }
16375
16376 //------------------------------------
16377 // STEP 7:
16378 // take care that no double refinement is done at each line in 3d or
16379 // higher dimensions.
16380 this->policy->prepare_refinement_dim_dependent(*this);
16381
16382 //------------------------------------
16383 // STEP 8:
16384 // make sure that all children of each cell are either flagged for
16385 // coarsening or none of the children is
16386 fix_coarsen_flags();
16387
16388 // get the refinement and coarsening flags
16389 auto coarsen_flags_after_loop =
16390 internal::extract_raw_coarsen_flags(levels);
16391 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
16392
16393 // find out whether something was changed in this loop
16394 mesh_changed_in_this_loop =
16395 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
16396 (refine_flags_before_loop != refine_flags_after_loop));
16397
16398 // set the flags for the next loop already
16399 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
16400 refine_flags_before_loop.swap(refine_flags_after_loop);
16401 }
16402 while (mesh_changed_in_this_loop);
16403
16404
16405 // find out whether something was really changed in this
16406 // function. Note that @p{..._flags_before_loop} represents the state
16407 // after the last loop, i.e., the present state
16408 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
16409 (refine_flags_before != refine_flags_before_loop));
16410}
16411
16412
16413
16414template <int dim, int spacedim>
16417 const unsigned int magic_number1,
16418 const std::vector<bool> &v,
16419 const unsigned int magic_number2,
16420 std::ostream & out)
16421{
16422 const unsigned int N = v.size();
16423 unsigned char * flags = new unsigned char[N / 8 + 1];
16424 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16425 flags[i] = 0;
16426
16427 for (unsigned int position = 0; position < N; ++position)
16428 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
16429
16430 AssertThrow(out.fail() == false, ExcIO());
16431
16432 // format:
16433 // 0. magic number
16434 // 1. number of flags
16435 // 2. the flags
16436 // 3. magic number
16437 out << magic_number1 << ' ' << N << std::endl;
16438 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16439 out << static_cast<unsigned int>(flags[i]) << ' ';
16440
16441 out << std::endl << magic_number2 << std::endl;
16442
16443 delete[] flags;
16444
16445 AssertThrow(out.fail() == false, ExcIO());
16446}
16447
16448
16449template <int dim, int spacedim>
16452 const unsigned int magic_number1,
16453 std::vector<bool> &v,
16454 const unsigned int magic_number2,
16455 std::istream & in)
16456{
16457 AssertThrow(in.fail() == false, ExcIO());
16458
16459 unsigned int magic_number;
16460 in >> magic_number;
16461 AssertThrow(magic_number == magic_number1, ExcGridReadError());
16462
16463 unsigned int N;
16464 in >> N;
16465 v.resize(N);
16466
16467 unsigned char * flags = new unsigned char[N / 8 + 1];
16468 unsigned short int tmp;
16469 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16470 {
16471 in >> tmp;
16472 flags[i] = tmp;
16473 }
16474
16475 for (unsigned int position = 0; position != N; ++position)
16476 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
16477
16478 in >> magic_number;
16479 AssertThrow(magic_number == magic_number2, ExcGridReadError());
16480
16481 delete[] flags;
16482
16483 AssertThrow(in.fail() == false, ExcIO());
16484}
16485
16486
16487
16488template <int dim, int spacedim>
16491{
16492 std::size_t mem = 0;
16493 mem += sizeof(MeshSmoothing);
16494 mem += MemoryConsumption::memory_consumption(reference_cells);
16495 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
16497 for (const auto &level : levels)
16500 mem += MemoryConsumption::memory_consumption(vertices_used);
16501 mem += sizeof(manifolds);
16502 mem += sizeof(smooth_grid);
16503 mem += MemoryConsumption::memory_consumption(number_cache);
16504 mem += sizeof(faces);
16505 if (faces)
16507
16508 return mem;
16509}
16510
16511
16512
16513template <int dim, int spacedim>
16516 default;
16517
16518
16519// explicit instantiations
16520#include "tria.inst"
16521
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:704
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:394
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:112
static constexpr unsigned char default_combined_face_orientation()
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const unsigned char face_orientation) const
static constexpr unsigned char reversed_combined_line_orientation()
unsigned int n_lines() const
unsigned char get_combined_orientation(const ArrayView< const T > &vertices_0, const ArrayView< const T > &vertices_1) const
Subscriptor & operator=(const Subscriptor &)
constexpr void clear()
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:3826
active_vertex_iterator begin_active_vertex() const
virtual MPI_Comm get_communicator() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4203
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4215
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4273
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > periodic_face_map
Definition tria.h:3806
void fix_coarsen_flags()
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > & get_periodic_face_map() const
void save_user_pointers_line(std::vector< void * > &v) const
void load_refine_flags(std::istream &in)
void save_user_indices_line(std::vector< unsigned int > &v) const
raw_cell_iterator begin_raw(const unsigned int level=0) const
unsigned int n_lines() const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4198
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_raw_faces() const
unsigned int n_active_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const bool check_for_distorted_cells
Definition tria.h:4222
raw_cell_iterator end_raw(const unsigned int level) const
line_iterator end_line() const
std::unique_ptr< std::map< unsigned int, types::boundary_id > > vertex_to_boundary_id_map_1d
Definition tria.h:4250
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
virtual void update_reference_cells()
std::vector< ReferenceCell > reference_cells
Definition tria.h:3737
void update_periodic_face_map()
void clear_despite_subscriptions()
void coarsen_global(const unsigned int times=1)
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
void save_user_flags(std::ostream &out) const
void refine_global(const unsigned int times=1)
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
virtual void create_triangulation_compatibility(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces > faces
Definition tria.h:4192
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
void load_user_indices_line(const std::vector< unsigned int > &v)
void clear_user_flags_hex()
void save_user_pointers_hex(std::vector< void * > &v) const
const std::vector< ReferenceCell > & get_reference_cells() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:3827
void load_user_pointers(const std::vector< void * > &v)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition tria.h:4233
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:3798
unsigned int n_raw_cells(const unsigned int level) const
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:3828
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifolds
Definition tria.h:4210
MeshSmoothing smooth_grid
Definition tria.h:3731
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:3789
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2479
virtual ~Triangulation() override
unsigned int n_vertices() const
void save_user_indices(std::vector< unsigned int > &v) const
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition tria.h:4184
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
unsigned int n_active_hexs() const
virtual std::vector< types::boundary_id > get_boundary_ids() const
void load_user_flags(std::istream &in)
void reset_policy()
void save_coarsen_flags(std::ostream &out) const
active_face_iterator begin_active_face() const
void clear_user_flags_line()
raw_line_iterator begin_raw_line(const unsigned int level=0) const
static void write_bool_vector(const unsigned int magic_number1, const std::vector< bool > &v, const unsigned int magic_number2, std::ostream &out)
void flip_all_direction_flags()
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:1623
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:1630
void delete_children(Triangulation< dim, spacedim > &tria, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count) override
Definition tria.cc:1606
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:1600
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:1637
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:1616
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:1645
virtual std::unique_ptr< Policy< dim, spacedim > > clone()=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)=0
std::vector< std::pair< int, int > > neighbors
std::vector< types::global_cell_index > global_active_cell_indices
std::vector< types::global_cell_index > global_level_cell_indices
std::vector< ReferenceCell > reference_cell
std::vector< types::subdomain_id > level_subdomain_ids
std::vector< types::subdomain_id > subdomain_ids
std::vector< unsigned int > active_cell_indices
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:472
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:160
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:473
Point< 3 > vertices[4]
Point< 2 > second
Definition grid_out.cc:4616
Point< 2 > first
Definition grid_out.cc:4615
unsigned int level
Definition grid_out.cc:4618
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
unsigned int cell_index
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcInternalErrorOnCell(int arg1)
static ::ExceptionBase & ExcIO()
#define DeclException4(Exception4, type1, type2, type3, type4, outsequence)
Definition exceptions.h:579
static ::ExceptionBase & ExcInteriorQuadCantBeBoundary(int arg1, int arg2, int arg3, int arg4, types::boundary_id arg5)
static ::ExceptionBase & ExcQuadInexistant(int arg1, int arg2, int arg3, int arg4)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInconsistentLineInfoOfLine(int arg1, int arg2, std::string arg3)
static ::ExceptionBase & ExcCellHasNegativeMeasure(int arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition exceptions.h:533
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcLineInexistant(int arg1, int arg2)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition exceptions.h:556
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:510
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
Definition exceptions.h:605
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition tria.h:1505
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1496
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1516
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1481
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1457
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1370
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1472
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:285
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
double diameter(const Triangulation< dim, spacedim > &tria)
Definition grid_tools.cc:88
@ valid
Iterator points to a valid object.
std::enable_if_t< std::is_fundamental< T >::value, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:13833
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11095
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:13826
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:1069
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:1261
const types::boundary_id internal_face_boundary_id
Definition types.h:277
const types::subdomain_id invalid_subdomain_id
Definition types.h:298
static const unsigned int invalid_unsigned_int
Definition types.h:213
const types::manifold_id flat_manifold_id
Definition types.h:286
const types::global_dof_index invalid_dof_index
Definition types.h:233
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > pow(const ::VectorizedArray< Number, width > &, const Number p)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:153
unsigned int boundary_id
Definition types.h:141
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
std::vector< CellData< 2 > > boundary_quads
bool check_consistency(const unsigned int dim) const
std::vector< CellData< 1 > > boundary_lines
std::vector< std::vector< CellData< dim > > > cell_infos
std::vector<::CellData< dim > > coarse_cells
std::vector< Point< spacedim > > coarse_cell_vertices
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1551
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2177
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:10972
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11057
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11083
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:10976
static void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)
Definition tria.cc:11042
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11075
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11066
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:2689
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:2629
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition tria.cc:1851
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:10579
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:2079
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:10667
static void delete_children(Triangulation< 3, spacedim > &triangulation, typename Triangulation< 3, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)
Definition tria.cc:2984
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:2651
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:2073
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:6218
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:3979
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:2051
static void create_children(Triangulation< 2, spacedim > &triangulation, unsigned int &next_unused_vertex, typename Triangulation< 2, spacedim >::raw_line_iterator &next_unused_line, typename Triangulation< 2, spacedim >::raw_cell_iterator &next_unused_cell, const typename Triangulation< 2, spacedim >::cell_iterator &cell)
Definition tria.cc:3612
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:10586
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:10900
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition tria.cc:1958
static void delete_children(Triangulation< 1, spacedim > &triangulation, typename Triangulation< 1, spacedim >::cell_iterator &cell, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:2742
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:10677
static void delete_children(Triangulation< 2, spacedim > &triangulation, typename Triangulation< 2, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &)
Definition tria.cc:2846
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition tria.cc:1763
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:4480
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5020
static void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata, Triangulation< dim, spacedim > &tria)
Definition tria.cc:2258
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4711
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition tria.cc:2521
std::vector< std::vector< CellData< dim > > > cell_infos
const ::Triangulation< dim, spacedim > & tria