Reference documentation for deal.II version 9.3.3
\(\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\}}\)
tria.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 1998 - 2021 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
19
21
26#include <deal.II/grid/tria.h>
31
33#include <deal.II/lac/vector.h>
34
35#include <algorithm>
36#include <array>
37#include <cmath>
38#include <functional>
39#include <list>
40#include <map>
41#include <memory>
42#include <numeric>
43
44
46
47
48namespace internal
49{
50 namespace TriangulationImplementation
51 {
53 : n_levels(0)
54 , n_lines(0)
55 , n_active_lines(0)
56 // all other fields are
57 // default constructed
58 {}
59
60
61
62 std::size_t
64 {
69 MemoryConsumption::memory_consumption(n_active_lines_level));
70 }
71
72
74 : n_quads(0)
75 , n_active_quads(0)
76 // all other fields are
77 // default constructed
78 {}
79
80
81
82 std::size_t
84 {
89 MemoryConsumption::memory_consumption(n_active_quads_level));
90 }
91
92
93
95 : n_hexes(0)
96 , n_active_hexes(0)
97 // all other fields are
98 // default constructed
99 {}
100
101
102
103 std::size_t
105 {
110 MemoryConsumption::memory_consumption(n_active_hexes_level));
111 }
112 } // namespace TriangulationImplementation
113} // namespace internal
114
115// anonymous namespace for internal helper functions
116namespace
117{
118 // return whether the given cell is
119 // patch_level_1, i.e. determine
120 // whether either all or none of
121 // its children are further
122 // refined. this function can only
123 // be called for non-active cells.
124 template <int dim, int spacedim>
125 bool
126 cell_is_patch_level_1(
128 {
129 Assert(cell->is_active() == false, ExcInternalError());
130
131 unsigned int n_active_children = 0;
132 for (unsigned int i = 0; i < cell->n_children(); ++i)
133 if (cell->child(i)->is_active())
134 ++n_active_children;
135
136 return (n_active_children == 0) ||
137 (n_active_children == cell->n_children());
138 }
139
140
141
142 // return, whether a given @p cell will be
143 // coarsened, which is the case if all
144 // children are active and have their coarsen
145 // flag set. In case only part of the coarsen
146 // flags are set, remove them.
147 template <int dim, int spacedim>
148 bool
149 cell_will_be_coarsened(
151 {
152 // only cells with children should be
153 // considered for coarsening
154
155 if (cell->has_children())
156 {
157 unsigned int children_to_coarsen = 0;
158 const unsigned int n_children = cell->n_children();
159
160 for (unsigned int c = 0; c < n_children; ++c)
161 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
162 ++children_to_coarsen;
163 if (children_to_coarsen == n_children)
164 return true;
165 else
166 for (unsigned int c = 0; c < n_children; ++c)
167 if (cell->child(c)->is_active())
168 cell->child(c)->clear_coarsen_flag();
169 }
170 // no children, so no coarsening
171 // possible. however, no children also
172 // means that this cell will be in the same
173 // state as if it had children and was
174 // coarsened. So, what should we return -
175 // false or true?
176 // make sure we do not have to do this at
177 // all...
178 Assert(cell->has_children(), ExcInternalError());
179 // ... and then simply return false
180 return false;
181 }
182
183
184 // return, whether the face @p face_no of the
185 // given @p cell will be refined after the
186 // current refinement step, considering
187 // refine and coarsen flags and considering
188 // only those refinemnts that will be caused
189 // by the neighboring cell.
190
191 // this function is used on both active cells
192 // and cells with children. on cells with
193 // children it also of interest to know 'how'
194 // the face will be refined. thus there is an
195 // additional third argument @p
196 // expected_face_ref_case returning just
197 // that. be aware, that this variable will
198 // only contain useful information if this
199 // function is called for an active cell.
200 //
201 // thus, this is an internal function, users
202 // should call one of the two alternatives
203 // following below.
204 template <int dim, int spacedim>
205 bool
206 face_will_be_refined_by_neighbor_internal(
208 const unsigned int face_no,
209 RefinementCase<dim - 1> &expected_face_ref_case)
210 {
211 // first of all: set the default value for
212 // expected_face_ref_case, which is no
213 // refinement at all
214 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
215
216 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
217 cell->neighbor(face_no);
218
219 // If we are at the boundary, there is no
220 // neighbor which could refine the face
221 if (neighbor.state() != IteratorState::valid)
222 return false;
223
224 if (neighbor->has_children())
225 {
226 // if the neighbor is refined, it may be
227 // coarsened. if so, then it won't refine
228 // the face, no matter what else happens
229 if (cell_will_be_coarsened(neighbor))
230 return false;
231 else
232 // if the neighbor is refined, then it
233 // is also refined at our current
234 // face. It will stay so without
235 // coarsening, so return true in that
236 // case.
237 {
238 expected_face_ref_case = cell->face(face_no)->refinement_case();
239 return true;
240 }
241 }
242
243 // now, the neighbor is not refined, but
244 // perhaps it will be
245 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
246 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
247 {
248 // now we need to know, which of the
249 // neighbors faces points towards us
250 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
251 // check, whether the cell will be
252 // refined in a way that refines our
253 // face
254 const RefinementCase<dim - 1> face_ref_case =
256 nb_ref_flag,
257 neighbor_neighbor,
258 neighbor->face_orientation(neighbor_neighbor),
259 neighbor->face_flip(neighbor_neighbor),
260 neighbor->face_rotation(neighbor_neighbor));
261 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
262 {
264 neighbor_face = neighbor->face(neighbor_neighbor);
265 const int this_face_index = cell->face_index(face_no);
266
267 // there are still two basic
268 // possibilities here: the neighbor
269 // might be coarser or as coarse
270 // as we are
271 if (neighbor_face->index() == this_face_index)
272 // the neighbor is as coarse as
273 // we are and will be refined at
274 // the face of consideration, so
275 // return true
276 {
277 expected_face_ref_case = face_ref_case;
278 return true;
279 }
280 else
281 {
282 // the neighbor is coarser.
283 // this is the most complicated
284 // case. It might be, that the
285 // neighbor's face will be
286 // refined, but that we will
287 // not see this, as we are
288 // refined in a similar way.
289
290 // so, the neighbor's face must
291 // have children. check, if our
292 // cell's face is one of these
293 // (it could also be a
294 // grand_child)
295 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
296 if (neighbor_face->child_index(c) == this_face_index)
297 {
298 // if the flagged refine
299 // case of the face is a
300 // subset or the same as
301 // the current refine case,
302 // then the face, as seen
303 // from our cell, won't be
304 // refined by the neighbor
305 if ((neighbor_face->refinement_case() | face_ref_case) ==
306 neighbor_face->refinement_case())
307 return false;
308 else
309 {
310 // if we are active, we
311 // must be an
312 // anisotropic child
313 // and the coming
314 // face_ref_case is
315 // isotropic. Thus,
316 // from our cell we
317 // will see exactly the
318 // opposite refine case
319 // that the face has
320 // now...
321 Assert(
322 face_ref_case ==
325 expected_face_ref_case =
326 ~neighbor_face->refinement_case();
327 return true;
328 }
329 }
330
331 // so, obviously we were not
332 // one of the children, but a
333 // grandchild. This is only
334 // possible in 3d.
335 Assert(dim == 3, ExcInternalError());
336 // In that case, however, no
337 // matter what the neighbor
338 // does, it won't be finer
339 // after the next refinement
340 // step.
341 return false;
342 }
343 } // if face will be refined
344 } // if neighbor is flagged for refinement
345
346 // no cases left, so the neighbor will not
347 // refine the face
348 return false;
349 }
350
351 // version of above function for both active
352 // and non-active cells
353 template <int dim, int spacedim>
354 bool
355 face_will_be_refined_by_neighbor(
357 const unsigned int face_no)
358 {
359 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
360 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
361 }
362
363 // version of above function for active cells
364 // only. Additionally returning the refine
365 // case (to come) of the face under
366 // consideration
367 template <int dim, int spacedim>
368 bool
369 face_will_be_refined_by_neighbor(
371 const unsigned int face_no,
372 RefinementCase<dim - 1> &expected_face_ref_case)
373 {
374 return face_will_be_refined_by_neighbor_internal(cell,
375 face_no,
376 expected_face_ref_case);
377 }
378
379
380
381 template <int dim, int spacedim>
382 bool
383 satisfies_level1_at_vertex_rule(
385 {
386 std::vector<unsigned int> min_adjacent_cell_level(
387 triangulation.n_vertices(), triangulation.n_levels());
388 std::vector<unsigned int> max_adjacent_cell_level(
389 triangulation.n_vertices(), 0);
390
391 for (const auto &cell : triangulation.active_cell_iterators())
392 for (const unsigned int v : cell->vertex_indices())
393 {
394 min_adjacent_cell_level[cell->vertex_index(v)] =
395 std::min<unsigned int>(
396 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
397 max_adjacent_cell_level[cell->vertex_index(v)] =
398 std::max<unsigned int>(
399 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
400 }
401
402 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
403 if (triangulation.vertex_used(k))
404 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
405 return false;
406 return true;
407 }
408
409
410
417 template <int dim, int spacedim>
418 std::vector<unsigned int>
419 count_cells_bounded_by_line(const Triangulation<dim, spacedim> &triangulation)
420 {
421 if (dim >= 2)
422 {
423 std::vector<unsigned int> line_cell_count(triangulation.n_raw_lines(),
424 0);
425 for (const auto &cell : triangulation.cell_iterators())
426 for (unsigned int l = 0; l < cell->n_lines(); ++l)
427 ++line_cell_count[cell->line_index(l)];
428 return line_cell_count;
429 }
430 else
431 return std::vector<unsigned int>();
432 }
433
434
435
442 template <int dim, int spacedim>
443 std::vector<unsigned int>
444 count_cells_bounded_by_quad(const Triangulation<dim, spacedim> &triangulation)
445 {
446 if (dim >= 3)
447 {
448 std::vector<unsigned int> quad_cell_count(triangulation.n_raw_quads(),
449 0);
450 for (const auto &cell : triangulation.cell_iterators())
451 for (unsigned int q : cell->face_indices())
452 ++quad_cell_count[cell->quad_index(q)];
453 return quad_cell_count;
454 }
455 else
456 return {};
457 }
458
459
460
472 void
473 reorder_compatibility(const std::vector<CellData<1>> &, const SubCellData &)
474 {
475 // nothing to do here: the format
476 // hasn't changed for 1d
477 }
478
479
480 void reorder_compatibility(std::vector<CellData<2>> &cells,
481 const SubCellData &)
482 {
483 for (auto &cell : cells)
484 if (cell.vertices.size() == GeometryInfo<2>::vertices_per_cell)
485 std::swap(cell.vertices[2], cell.vertices[3]);
486 }
487
488
489 void reorder_compatibility(std::vector<CellData<3>> &cells,
490 SubCellData & subcelldata)
491 {
492 unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
493 for (auto &cell : cells)
494 if (cell.vertices.size() == GeometryInfo<3>::vertices_per_cell)
495 {
496 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
497 tmp[i] = cell.vertices[i];
498 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
499 cell.vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
500 }
501
502 // now points in boundary quads
503 for (auto &boundary_quad : subcelldata.boundary_quads)
504 if (boundary_quad.vertices.size() == GeometryInfo<2>::vertices_per_cell)
505 std::swap(boundary_quad.vertices[2], boundary_quad.vertices[3]);
506 }
507
508
509
527 template <int dim, int spacedim>
528 unsigned int
529 middle_vertex_index(
531 {
532 if (line->has_children())
533 return line->child(0)->vertex_index(1);
535 }
536
537
538 template <int dim, int spacedim>
539 unsigned int
540 middle_vertex_index(
542 {
543 switch (static_cast<unsigned char>(quad->refinement_case()))
544 {
546 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
547 break;
549 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
550 break;
552 return quad->child(0)->vertex_index(3);
553 break;
554 default:
555 break;
556 }
558 }
559
560
561 template <int dim, int spacedim>
562 unsigned int
563 middle_vertex_index(
565 {
566 switch (static_cast<unsigned char>(hex->refinement_case()))
567 {
569 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
570 break;
572 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
573 break;
575 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
576 break;
578 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
579 break;
581 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
582 break;
584 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
585 break;
587 return hex->child(0)->vertex_index(7);
588 break;
589 default:
590 break;
591 }
593 }
594
595
608 template <class TRIANGULATION>
609 inline typename TRIANGULATION::DistortedCellList
610 collect_distorted_coarse_cells(const TRIANGULATION &)
611 {
612 return typename TRIANGULATION::DistortedCellList();
613 }
614
615
616
625 template <int dim>
627 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
628 {
629 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
630 for (const auto &cell : triangulation.cell_iterators_on_level(0))
631 {
633 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
634 vertices[i] = cell->vertex(i);
635
638
639 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
640 if (determinants[i] <= 1e-9 * std::pow(cell->diameter(), 1. * dim))
641 {
642 distorted_cells.distorted_cells.push_back(cell);
643 break;
644 }
645 }
646
647 return distorted_cells;
648 }
649
650
657 template <int dim>
658 bool
659 has_distorted_children(
660 const typename Triangulation<dim, dim>::cell_iterator &cell)
661 {
662 Assert(cell->has_children(), ExcInternalError());
663
664 for (unsigned int c = 0; c < cell->n_children(); ++c)
665 {
667 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
668 vertices[i] = cell->child(c)->vertex(i);
669
672
673 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
674 if (determinants[i] <=
675 1e-9 * std::pow(cell->child(c)->diameter(), 1. * dim))
676 return true;
677 }
678
679 return false;
680 }
681
682
690 template <int dim, int spacedim>
691 bool
692 has_distorted_children(
694 {
695 return false;
696 }
697
698
699 template <int dim, int spacedim>
700 void
701 update_periodic_face_map_recursively(
702 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
703 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
704 unsigned int n_face_1,
705 unsigned int n_face_2,
706 const std::bitset<3> & orientation,
707 typename std::map<
709 unsigned int>,
710 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
711 unsigned int>,
712 std::bitset<3>>> &periodic_face_map)
713 {
714 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
715 const FaceIterator face_1 = cell_1->face(n_face_1);
716 const FaceIterator face_2 = cell_2->face(n_face_2);
717
718 const bool face_orientation = orientation[0];
719 const bool face_flip = orientation[1];
720 const bool face_rotation = orientation[2];
721
722 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
723 face_rotation == false),
724 ExcMessage("The supplied orientation "
725 "(face_orientation, face_flip, face_rotation) "
726 "is invalid for 1D"));
727
728 Assert((dim != 2) || (face_orientation == true && face_rotation == false),
729 ExcMessage("The supplied orientation "
730 "(face_orientation, face_flip, face_rotation) "
731 "is invalid for 2D"));
732
733 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
734
735 Assert(face_1->at_boundary() && face_2->at_boundary(),
736 ExcMessage("Periodic faces must be on the boundary"));
737
738 // Check if the requirement that each edge can only have at most one hanging
739 // node, and as a consequence neighboring cells can differ by at most
740 // one refinement level is enforced. In 1d, there are no hanging nodes and
741 // so neighboring cells can differ by more than one refinement level.
742 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
744
745 // insert periodic face pair for both cells
746 using CellFace =
747 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
748 unsigned int>;
749 const CellFace cell_face_1(cell_1, n_face_1);
750 const CellFace cell_face_2(cell_2, n_face_2);
751 const std::pair<CellFace, std::bitset<3>> cell_face_orientation_2(
752 cell_face_2, orientation);
753
754 const std::pair<CellFace, std::pair<CellFace, std::bitset<3>>>
755 periodic_faces(cell_face_1, cell_face_orientation_2);
756
757 // Only one periodic neighbor is allowed
758 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
759 periodic_face_map.insert(periodic_faces);
760
761 if (dim == 1)
762 {
763 if (cell_1->has_children())
764 {
765 if (cell_2->has_children())
766 {
767 update_periodic_face_map_recursively<dim, spacedim>(
768 cell_1->child(n_face_1),
769 cell_2->child(n_face_2),
770 n_face_1,
771 n_face_2,
772 orientation,
773 periodic_face_map);
774 }
775 else // only face_1 has children
776 {
777 update_periodic_face_map_recursively<dim, spacedim>(
778 cell_1->child(n_face_1),
779 cell_2,
780 n_face_1,
781 n_face_2,
782 orientation,
783 periodic_face_map);
784 }
785 }
786 }
787 else // dim == 2 || dim == 3
788 {
789 // A lookup table on how to go through the child cells depending on the
790 // orientation:
791 // see Documentation of GeometryInfo for details
792
793 static const int lookup_table_2d[2][2] =
794 // flip:
795 {
796 {0, 1}, // false
797 {1, 0} // true
798 };
799
800 static const int lookup_table_3d[2][2][2][4] =
801 // orientation flip rotation
802 {{{
803 {0, 2, 1, 3}, // false false false
804 {2, 3, 0, 1} // false false true
805 },
806 {
807 {3, 1, 2, 0}, // false true false
808 {1, 0, 3, 2} // false true true
809 }},
810 {{
811 {0, 1, 2, 3}, // true false false
812 {1, 3, 0, 2} // true false true
813 },
814 {
815 {3, 2, 1, 0}, // true true false
816 {2, 0, 3, 1} // true true true
817 }}};
818
819 if (cell_1->has_children())
820 {
821 if (cell_2->has_children())
822 {
823 // In the case that both faces have children, we loop over all
824 // children and apply update_periodic_face_map_recursively
825 // recursively:
826
827 Assert(face_1->n_children() ==
829 face_2->n_children() ==
832
833 for (unsigned int i = 0;
834 i < GeometryInfo<dim>::max_children_per_face;
835 ++i)
836 {
837 // Lookup the index for the second face
838 unsigned int j = 0;
839 switch (dim)
840 {
841 case 2:
842 j = lookup_table_2d[face_flip][i];
843 break;
844 case 3:
845 j = lookup_table_3d[face_orientation][face_flip]
846 [face_rotation][i];
847 break;
848 default:
850 }
851
852 // find subcell ids that belong to the subface indices
853 unsigned int child_cell_1 =
855 cell_1->refinement_case(),
856 n_face_1,
857 i,
858 cell_1->face_orientation(n_face_1),
859 cell_1->face_flip(n_face_1),
860 cell_1->face_rotation(n_face_1),
861 face_1->refinement_case());
862 unsigned int child_cell_2 =
864 cell_2->refinement_case(),
865 n_face_2,
866 j,
867 cell_2->face_orientation(n_face_2),
868 cell_2->face_flip(n_face_2),
869 cell_2->face_rotation(n_face_2),
870 face_2->refinement_case());
871
872 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
873 face_1->child(i),
875 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
876 face_2->child(j),
878
879 // precondition: subcell has the same orientation as cell
880 // (so that the face numbers coincide) recursive call
881 update_periodic_face_map_recursively<dim, spacedim>(
882 cell_1->child(child_cell_1),
883 cell_2->child(child_cell_2),
884 n_face_1,
885 n_face_2,
886 orientation,
887 periodic_face_map);
888 }
889 }
890 else // only face_1 has children
891 {
892 for (unsigned int i = 0;
893 i < GeometryInfo<dim>::max_children_per_face;
894 ++i)
895 {
896 // find subcell ids that belong to the subface indices
897 unsigned int child_cell_1 =
899 cell_1->refinement_case(),
900 n_face_1,
901 i,
902 cell_1->face_orientation(n_face_1),
903 cell_1->face_flip(n_face_1),
904 cell_1->face_rotation(n_face_1),
905 face_1->refinement_case());
906
907 // recursive call
908 update_periodic_face_map_recursively<dim, spacedim>(
909 cell_1->child(child_cell_1),
910 cell_2,
911 n_face_1,
912 n_face_2,
913 orientation,
914 periodic_face_map);
915 }
916 }
917 }
918 }
919 }
920
921
922} // end of anonymous namespace
923
924
925namespace internal
926{
927 namespace TriangulationImplementation
928 {
929 // make sure that if in the following we
930 // write Triangulation<dim,spacedim>
931 // we mean the *class*
932 // ::Triangulation, not the
933 // enclosing namespace
934 // internal::TriangulationImplementation
936
942 int,
943 << "Something went wrong when making cell " << arg1
944 << ". Read the docs and the source code "
945 << "for more information.");
951 int,
952 << "Something went wrong upon construction of cell "
953 << arg1);
964 int,
965 << "Cell " << arg1
966 << " has negative measure. This typically "
967 << "indicates some distortion in the cell, or a mistakenly "
968 << "swapped pair of vertices in the input to "
969 << "Triangulation::create_triangulation().");
978 int,
979 int,
980 int,
981 << "Error while creating cell " << arg1
982 << ": the vertex index " << arg2 << " must be between 0 and "
983 << arg3 << ".");
989 int,
990 int,
991 << "While trying to assign a boundary indicator to a line: "
992 << "the line with end vertices " << arg1 << " and " << arg2
993 << " does not exist.");
999 int,
1000 int,
1001 int,
1002 int,
1003 << "While trying to assign a boundary indicator to a quad: "
1004 << "the quad with bounding lines " << arg1 << ", " << arg2
1005 << ", " << arg3 << ", " << arg4 << " does not exist.");
1012 int,
1013 int,
1015 << "The input data for creating a triangulation contained "
1016 << "information about a line with indices " << arg1 << " and " << arg2
1017 << " that is described to have boundary indicator "
1018 << static_cast<int>(arg3)
1019 << ". However, this is an internal line not located on the "
1020 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1021 << std::endl
1022 << "If this happened at a place where you call "
1023 << "Triangulation::create_triangulation() yourself, you need "
1024 << "to check the SubCellData object you pass to this function."
1025 << std::endl
1026 << std::endl
1027 << "If this happened in a place where you are reading a mesh "
1028 << "from a file, then you need to investigate why such a line "
1029 << "ended up in the input file. A typical case is a geometry "
1030 << "that consisted of multiple parts and for which the mesh "
1031 << "generator program assumes that the interface between "
1032 << "two parts is a boundary when that isn't supposed to be "
1033 << "the case, or where the mesh generator simply assigns "
1034 << "'geometry indicators' to lines at the perimeter of "
1035 << "a part that are not supposed to be interpreted as "
1036 << "'boundary indicators'.");
1043 int,
1044 int,
1045 int,
1046 int,
1048 << "The input data for creating a triangulation contained "
1049 << "information about a quad with indices " << arg1 << ", " << arg2
1050 << ", " << arg3 << ", and " << arg4
1051 << " that is described to have boundary indicator "
1052 << static_cast<int>(arg5)
1053 << ". However, this is an internal quad not located on the "
1054 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1055 << std::endl
1056 << "If this happened at a place where you call "
1057 << "Triangulation::create_triangulation() yourself, you need "
1058 << "to check the SubCellData object you pass to this function."
1059 << std::endl
1060 << std::endl
1061 << "If this happened in a place where you are reading a mesh "
1062 << "from a file, then you need to investigate why such a quad "
1063 << "ended up in the input file. A typical case is a geometry "
1064 << "that consisted of multiple parts and for which the mesh "
1065 << "generator program assumes that the interface between "
1066 << "two parts is a boundary when that isn't supposed to be "
1067 << "the case, or where the mesh generator simply assigns "
1068 << "'geometry indicators' to quads at the surface of "
1069 << "a part that are not supposed to be interpreted as "
1070 << "'boundary indicators'.");
1077 int,
1078 int,
1079 << "In SubCellData the line info of the line with vertex indices " << arg1
1080 << " and " << arg2 << " appears more than once. "
1081 << "This is not allowed.");
1088 int,
1089 int,
1090 std::string,
1091 << "In SubCellData the line info of the line with vertex indices " << arg1
1092 << " and " << arg2 << " appears multiple times with different (valid) "
1093 << arg3 << ". This is not allowed.");
1100 int,
1101 int,
1102 int,
1103 int,
1104 std::string,
1105 << "In SubCellData the quad info of the quad with line indices " << arg1
1106 << ", " << arg2 << ", " << arg3 << " and " << arg4
1107 << " appears multiple times with different (valid) " << arg5
1108 << ". This is not allowed.");
1109
1110 /*
1111 * Reserve space for TriaFaces. Details:
1112 *
1113 * Reserve space for line_orientations.
1114 *
1115 * @note Used only for dim=3.
1116 */
1117 void
1119 const unsigned int new_quads_in_pairs,
1120 const unsigned int new_quads_single)
1121 {
1122 AssertDimension(tria_faces.dim, 3);
1123
1124 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
1125
1126 unsigned int next_free_single = 0;
1127 unsigned int next_free_pair = 0;
1128
1129 // count the number of objects, of unused single objects and of
1130 // unused pairs of objects
1131 unsigned int n_quads = 0;
1132 unsigned int n_unused_pairs = 0;
1133 unsigned int n_unused_singles = 0;
1134 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
1135 {
1136 if (tria_faces.quads.used[i])
1137 ++n_quads;
1138 else if (i + 1 < tria_faces.quads.used.size())
1139 {
1140 if (tria_faces.quads.used[i + 1])
1141 {
1142 ++n_unused_singles;
1143 if (next_free_single == 0)
1144 next_free_single = i;
1145 }
1146 else
1147 {
1148 ++n_unused_pairs;
1149 if (next_free_pair == 0)
1150 next_free_pair = i;
1151 ++i;
1152 }
1153 }
1154 else
1155 ++n_unused_singles;
1156 }
1157 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
1158 tria_faces.quads.used.size(),
1160
1161 // how many single quads are needed in addition to n_unused_quads?
1162 const int additional_single_quads = new_quads_single - n_unused_singles;
1163
1164 unsigned int new_size =
1165 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
1166 if (additional_single_quads > 0)
1167 new_size += additional_single_quads;
1168
1169 // see above...
1170 if (new_size > tria_faces.quads.n_objects())
1171 {
1172 // reserve the field of the derived class
1173 tria_faces.quads_line_orientations.reserve(
1175 tria_faces.quads_line_orientations.insert(
1176 tria_faces.quads_line_orientations.end(),
1178 tria_faces.quads_line_orientations.size(),
1179 true);
1180
1181 tria_faces.quad_reference_cell.reserve(new_size);
1182 tria_faces.quad_reference_cell.insert(
1183 tria_faces.quad_reference_cell.end(),
1184 new_size - tria_faces.quad_reference_cell.size(),
1186 }
1187 }
1188
1189
1190
1204 void
1206 const unsigned int total_cells,
1207 const unsigned int dimension,
1208 const unsigned int space_dimension)
1209 {
1210 // we need space for total_cells cells. Maybe we have more already
1211 // with those cells which are unused, so only allocate new space if
1212 // needed.
1213 //
1214 // note that all arrays should have equal sizes (checked by
1215 // @p{monitor_memory}
1216 if (total_cells > tria_level.refine_flags.size())
1217 {
1218 tria_level.refine_flags.reserve(total_cells);
1219 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
1220 total_cells -
1221 tria_level.refine_flags.size(),
1222 /*RefinementCase::no_refinement=*/0);
1223
1224 tria_level.coarsen_flags.reserve(total_cells);
1225 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
1226 total_cells -
1227 tria_level.coarsen_flags.size(),
1228 false);
1229
1230 tria_level.active_cell_indices.reserve(total_cells);
1231 tria_level.active_cell_indices.insert(
1232 tria_level.active_cell_indices.end(),
1233 total_cells - tria_level.active_cell_indices.size(),
1235
1236 tria_level.subdomain_ids.reserve(total_cells);
1237 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
1238 total_cells -
1239 tria_level.subdomain_ids.size(),
1240 0);
1241
1242 tria_level.level_subdomain_ids.reserve(total_cells);
1243 tria_level.level_subdomain_ids.insert(
1244 tria_level.level_subdomain_ids.end(),
1245 total_cells - tria_level.level_subdomain_ids.size(),
1246 0);
1247
1248 tria_level.global_active_cell_indices.reserve(total_cells);
1249 tria_level.global_active_cell_indices.insert(
1250 tria_level.global_active_cell_indices.end(),
1251 total_cells - tria_level.global_active_cell_indices.size(),
1253
1254 tria_level.global_level_cell_indices.reserve(total_cells);
1255 tria_level.global_level_cell_indices.insert(
1256 tria_level.global_level_cell_indices.end(),
1257 total_cells - tria_level.global_level_cell_indices.size(),
1259
1260 if (dimension < space_dimension)
1261 {
1262 tria_level.direction_flags.reserve(total_cells);
1263 tria_level.direction_flags.insert(
1264 tria_level.direction_flags.end(),
1265 total_cells - tria_level.direction_flags.size(),
1266 true);
1267 }
1268 else
1269 tria_level.direction_flags.clear();
1270
1271 tria_level.parents.reserve((total_cells + 1) / 2);
1272 tria_level.parents.insert(tria_level.parents.end(),
1273 (total_cells + 1) / 2 -
1274 tria_level.parents.size(),
1275 -1);
1276
1277 tria_level.neighbors.reserve(total_cells * (2 * dimension));
1278 tria_level.neighbors.insert(tria_level.neighbors.end(),
1279 total_cells * (2 * dimension) -
1280 tria_level.neighbors.size(),
1281 std::make_pair(-1, -1));
1282
1283 if (tria_level.dim == 2 || tria_level.dim == 3)
1284 {
1285 const unsigned int max_faces_per_cell = 2 * dimension;
1286 tria_level.face_orientations.reserve(total_cells *
1287 max_faces_per_cell);
1288 tria_level.face_orientations.insert(
1289 tria_level.face_orientations.end(),
1290 total_cells * max_faces_per_cell -
1291 tria_level.face_orientations.size(),
1292 true);
1293
1294 tria_level.reference_cell.reserve(total_cells);
1295 tria_level.reference_cell.insert(
1296 tria_level.reference_cell.end(),
1297 total_cells - tria_level.reference_cell.size(),
1298 tria_level.dim == 2 ? ::ReferenceCells::Quadrilateral :
1300 }
1301 }
1302 }
1303
1304
1305
1310 int,
1311 int,
1312 << "The containers have sizes " << arg1 << " and " << arg2
1313 << ", which is not as expected.");
1314
1320 void
1321 monitor_memory(const TriaLevel & tria_level,
1322 const unsigned int true_dimension)
1323 {
1324 (void)tria_level;
1325 (void)true_dimension;
1326 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
1327 tria_level.neighbors.size(),
1328 ExcMemoryInexact(tria_level.refine_flags.size(),
1329 tria_level.neighbors.size()));
1330 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
1331 tria_level.neighbors.size(),
1332 ExcMemoryInexact(tria_level.coarsen_flags.size(),
1333 tria_level.neighbors.size()));
1334 }
1335
1336
1337
1350 void
1352 const unsigned int new_objects_in_pairs,
1353 const unsigned int new_objects_single = 0)
1354 {
1355 if (tria_objects.structdim <= 2)
1356 {
1357 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
1358
1359 tria_objects.next_free_single = 0;
1360 tria_objects.next_free_pair = 0;
1361 tria_objects.reverse_order_next_free_single = false;
1362
1363 // count the number of objects, of unused single objects and of
1364 // unused pairs of objects
1365 unsigned int n_objects = 0;
1366 unsigned int n_unused_pairs = 0;
1367 unsigned int n_unused_singles = 0;
1368 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
1369 {
1370 if (tria_objects.used[i])
1371 ++n_objects;
1372 else if (i + 1 < tria_objects.used.size())
1373 {
1374 if (tria_objects.used[i + 1])
1375 {
1376 ++n_unused_singles;
1377 if (tria_objects.next_free_single == 0)
1378 tria_objects.next_free_single = i;
1379 }
1380 else
1381 {
1382 ++n_unused_pairs;
1383 if (tria_objects.next_free_pair == 0)
1384 tria_objects.next_free_pair = i;
1385 ++i;
1386 }
1387 }
1388 else
1389 ++n_unused_singles;
1390 }
1391 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
1392 tria_objects.used.size(),
1394
1395 // how many single objects are needed in addition to
1396 // n_unused_objects?
1397 const int additional_single_objects =
1398 new_objects_single - n_unused_singles;
1399
1400 unsigned int new_size = tria_objects.used.size() +
1401 new_objects_in_pairs - 2 * n_unused_pairs;
1402 if (additional_single_objects > 0)
1403 new_size += additional_single_objects;
1404
1405 // only allocate space if necessary
1406 if (new_size > tria_objects.n_objects())
1407 {
1408 const unsigned int max_faces_per_cell =
1409 2 * tria_objects.structdim;
1410 const unsigned int max_children_per_cell =
1411 1 << tria_objects.structdim;
1412
1413 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1414 tria_objects.cells.insert(tria_objects.cells.end(),
1415 (new_size - tria_objects.n_objects()) *
1416 max_faces_per_cell,
1417 -1);
1418
1419 tria_objects.used.reserve(new_size);
1420 tria_objects.used.insert(tria_objects.used.end(),
1421 new_size - tria_objects.used.size(),
1422 false);
1423
1424 tria_objects.user_flags.reserve(new_size);
1425 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1426 new_size -
1427 tria_objects.user_flags.size(),
1428 false);
1429
1430 const unsigned int factor = max_children_per_cell / 2;
1431 tria_objects.children.reserve(factor * new_size);
1432 tria_objects.children.insert(tria_objects.children.end(),
1433 factor * new_size -
1434 tria_objects.children.size(),
1435 -1);
1436
1437 if (tria_objects.structdim > 1)
1438 {
1439 tria_objects.refinement_cases.reserve(new_size);
1440 tria_objects.refinement_cases.insert(
1441 tria_objects.refinement_cases.end(),
1442 new_size - tria_objects.refinement_cases.size(),
1443 /*RefinementCase::no_refinement=*/0);
1444 }
1445
1446 // first reserve, then resize. Otherwise the std library can
1447 // decide to allocate more entries.
1448 tria_objects.boundary_or_material_id.reserve(new_size);
1449 tria_objects.boundary_or_material_id.resize(new_size);
1450
1451 tria_objects.user_data.reserve(new_size);
1452 tria_objects.user_data.resize(new_size);
1453
1454 tria_objects.manifold_id.reserve(new_size);
1455 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1456 new_size -
1457 tria_objects.manifold_id.size(),
1459 }
1460
1461 if (n_unused_singles == 0)
1462 {
1463 tria_objects.next_free_single = new_size - 1;
1464 tria_objects.reverse_order_next_free_single = true;
1465 }
1466 }
1467 else
1468 {
1469 const unsigned int new_hexes = new_objects_in_pairs;
1470
1471 const unsigned int new_size =
1472 new_hexes + std::count(tria_objects.used.begin(),
1473 tria_objects.used.end(),
1474 true);
1475
1476 // see above...
1477 if (new_size > tria_objects.n_objects())
1478 {
1479 const unsigned int max_faces_per_cell =
1480 2 * tria_objects.structdim;
1481
1482 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1483 tria_objects.cells.insert(tria_objects.cells.end(),
1484 (new_size - tria_objects.n_objects()) *
1485 max_faces_per_cell,
1486 -1);
1487
1488 tria_objects.used.reserve(new_size);
1489 tria_objects.used.insert(tria_objects.used.end(),
1490 new_size - tria_objects.used.size(),
1491 false);
1492
1493 tria_objects.user_flags.reserve(new_size);
1494 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1495 new_size -
1496 tria_objects.user_flags.size(),
1497 false);
1498
1499 tria_objects.children.reserve(4 * new_size);
1500 tria_objects.children.insert(tria_objects.children.end(),
1501 4 * new_size -
1502 tria_objects.children.size(),
1503 -1);
1504
1505 // for the following fields, we know exactly how many elements
1506 // we need, so first reserve then resize (resize itself, at least
1507 // with some compiler libraries, appears to round up the size it
1508 // actually reserves)
1509 tria_objects.boundary_or_material_id.reserve(new_size);
1510 tria_objects.boundary_or_material_id.resize(new_size);
1511
1512 tria_objects.manifold_id.reserve(new_size);
1513 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1514 new_size -
1515 tria_objects.manifold_id.size(),
1517
1518 tria_objects.user_data.reserve(new_size);
1519 tria_objects.user_data.resize(new_size);
1520
1521 tria_objects.refinement_cases.reserve(new_size);
1522 tria_objects.refinement_cases.insert(
1523 tria_objects.refinement_cases.end(),
1524 new_size - tria_objects.refinement_cases.size(),
1525 /*RefinementCase::no_refinement=*/0);
1526 }
1527 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
1528 }
1529 }
1530
1531
1532
1538 void
1539 monitor_memory(const TriaObjects &tria_object, const unsigned int)
1540 {
1541 Assert(tria_object.n_objects() == tria_object.used.size(),
1542 ExcMemoryInexact(tria_object.n_objects(),
1543 tria_object.used.size()));
1544 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
1545 ExcMemoryInexact(tria_object.n_objects(),
1546 tria_object.user_flags.size()));
1547 Assert(tria_object.n_objects() ==
1548 tria_object.boundary_or_material_id.size(),
1549 ExcMemoryInexact(tria_object.n_objects(),
1550 tria_object.boundary_or_material_id.size()));
1551 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
1552 ExcMemoryInexact(tria_object.n_objects(),
1553 tria_object.manifold_id.size()));
1554 Assert(tria_object.n_objects() == tria_object.user_data.size(),
1555 ExcMemoryInexact(tria_object.n_objects(),
1556 tria_object.user_data.size()));
1557
1558 if (tria_object.structdim == 1)
1559 {
1560 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
1561 ExcMemoryInexact(tria_object.n_objects(),
1562 tria_object.children.size()));
1563 }
1564 else if (tria_object.structdim == 2)
1565 {
1566 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
1567 ExcMemoryInexact(tria_object.n_objects(),
1568 tria_object.children.size()));
1569 }
1570 else if (tria_object.structdim == 3)
1571 {
1572 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
1573 ExcMemoryInexact(tria_object.n_objects(),
1574 tria_object.children.size()));
1575 }
1576 }
1577
1578
1579
1584 template <int dim, int spacedim>
1586 {
1587 public:
1591 virtual ~Policy() = default;
1592
1596 virtual void
1598
1602 virtual void
1606 std::vector<unsigned int> & line_cell_count,
1607 std::vector<unsigned int> &quad_cell_count) = 0;
1608
1614 const bool check_for_distorted_cells) = 0;
1615
1619 virtual void
1622
1626 virtual void
1629
1633 virtual bool
1635 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
1636
1643 virtual std::unique_ptr<Policy<dim, spacedim>>
1644 clone() = 0;
1645 };
1646
1647
1648
1654 template <int dim, int spacedim, typename T>
1655 class PolicyWrapper : public Policy<dim, spacedim>
1656 {
1657 public:
1658 void
1660 {
1661 T::update_neighbors(tria);
1662 }
1663
1664 void
1668 std::vector<unsigned int> & line_cell_count,
1669 std::vector<unsigned int> &quad_cell_count) override
1670 {
1671 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
1672 }
1673
1676 const bool check_for_distorted_cells) override
1677 {
1678 return T::execute_refinement(triangulation, check_for_distorted_cells);
1679 }
1680
1681 void
1684 {
1685 T::prevent_distorted_boundary_cells(triangulation);
1686 }
1687
1688 void
1691 {
1692 T::prepare_refinement_dim_dependent(triangulation);
1693 }
1694
1695 bool
1698 override
1699 {
1700 return T::template coarsening_allowed<dim, spacedim>(cell);
1701 }
1702
1703 std::unique_ptr<Policy<dim, spacedim>>
1704 clone() override
1705 {
1706 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
1707 }
1708 };
1709
1710
1711
1808 {
1820 template <int dim, int spacedim>
1821 static void
1824 const unsigned int level_objects,
1826 {
1827 using line_iterator =
1829
1830 number_cache.n_levels = 0;
1831 if (level_objects > 0)
1832 // find the last level on which there are used cells
1833 for (unsigned int level = 0; level < level_objects; ++level)
1834 if (triangulation.begin(level) != triangulation.end(level))
1835 number_cache.n_levels = level + 1;
1836
1837 // no cells at all?
1838 Assert(number_cache.n_levels > 0, ExcInternalError());
1839
1841 // update the number of lines on the different levels in the
1842 // cache
1843 number_cache.n_lines = 0;
1844 number_cache.n_active_lines = 0;
1845
1846 // for 1d, lines have levels so take count the objects per
1847 // level and globally
1848 if (dim == 1)
1849 {
1850 number_cache.n_lines_level.resize(number_cache.n_levels);
1851 number_cache.n_active_lines_level.resize(number_cache.n_levels);
1852
1853 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
1854 {
1855 // count lines on this level
1856 number_cache.n_lines_level[level] = 0;
1857 number_cache.n_active_lines_level[level] = 0;
1858
1859 line_iterator line = triangulation.begin_line(level),
1860 endc =
1861 (level == number_cache.n_levels - 1 ?
1862 line_iterator(triangulation.end_line()) :
1863 triangulation.begin_line(level + 1));
1864 for (; line != endc; ++line)
1865 {
1866 ++number_cache.n_lines_level[level];
1867 if (line->has_children() == false)
1868 ++number_cache.n_active_lines_level[level];
1869 }
1870
1871 // update total number of lines
1872 number_cache.n_lines += number_cache.n_lines_level[level];
1873 number_cache.n_active_lines +=
1874 number_cache.n_active_lines_level[level];
1875 }
1876 }
1877 else
1878 {
1879 // for dim>1, there are no levels for lines
1880 number_cache.n_lines_level.clear();
1881 number_cache.n_active_lines_level.clear();
1882
1883 line_iterator line = triangulation.begin_line(),
1884 endc = triangulation.end_line();
1885 for (; line != endc; ++line)
1886 {
1887 ++number_cache.n_lines;
1888 if (line->has_children() == false)
1889 ++number_cache.n_active_lines;
1890 }
1891 }
1892 }
1893
1908 template <int dim, int spacedim>
1909 static void
1912 const unsigned int level_objects,
1914 {
1915 // update lines and n_levels in number_cache. since we don't
1916 // access any of these numbers, we can do this in the
1917 // background
1919 static_cast<
1920 void (*)(const Triangulation<dim, spacedim> &,
1921 const unsigned int,
1923 &compute_number_cache<dim, spacedim>),
1925 level_objects,
1927 number_cache));
1928
1929 using quad_iterator =
1931
1933 // update the number of quads on the different levels in the
1934 // cache
1935 number_cache.n_quads = 0;
1936 number_cache.n_active_quads = 0;
1937
1938 // for 2d, quads have levels so take count the objects per
1939 // level and globally
1940 if (dim == 2)
1941 {
1942 // count the number of levels; the function we called above
1943 // on a separate Task for lines also does this and puts it into
1944 // number_cache.n_levels, but this datum may not yet be
1945 // available as we call the function on a separate task
1946 unsigned int n_levels = 0;
1947 if (level_objects > 0)
1948 // find the last level on which there are used cells
1949 for (unsigned int level = 0; level < level_objects; ++level)
1950 if (triangulation.begin(level) != triangulation.end(level))
1951 n_levels = level + 1;
1952
1953 number_cache.n_quads_level.resize(n_levels);
1954 number_cache.n_active_quads_level.resize(n_levels);
1955
1956 for (unsigned int level = 0; level < n_levels; ++level)
1957 {
1958 // count quads on this level
1959 number_cache.n_quads_level[level] = 0;
1960 number_cache.n_active_quads_level[level] = 0;
1961
1962 quad_iterator quad = triangulation.begin_quad(level),
1963 endc =
1964 (level == n_levels - 1 ?
1965 quad_iterator(triangulation.end_quad()) :
1966 triangulation.begin_quad(level + 1));
1967 for (; quad != endc; ++quad)
1968 {
1969 ++number_cache.n_quads_level[level];
1970 if (quad->has_children() == false)
1971 ++number_cache.n_active_quads_level[level];
1972 }
1973
1974 // update total number of quads
1975 number_cache.n_quads += number_cache.n_quads_level[level];
1976 number_cache.n_active_quads +=
1977 number_cache.n_active_quads_level[level];
1978 }
1979 }
1980 else
1981 {
1982 // for dim>2, there are no levels for quads
1983 number_cache.n_quads_level.clear();
1984 number_cache.n_active_quads_level.clear();
1985
1986 quad_iterator quad = triangulation.begin_quad(),
1987 endc = triangulation.end_quad();
1988 for (; quad != endc; ++quad)
1989 {
1990 ++number_cache.n_quads;
1991 if (quad->has_children() == false)
1992 ++number_cache.n_active_quads;
1993 }
1994 }
1995
1996 // wait for the background computation for lines
1997 update_lines.join();
1998 }
1999
2015 template <int dim, int spacedim>
2016 static void
2019 const unsigned int level_objects,
2021 {
2022 // update quads, lines and n_levels in number_cache. since we
2023 // don't access any of these numbers, we can do this in the
2024 // background
2025 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2026 static_cast<
2027 void (*)(const Triangulation<dim, spacedim> &,
2028 const unsigned int,
2030 &compute_number_cache<dim, spacedim>),
2032 level_objects,
2034 number_cache));
2035
2036 using hex_iterator =
2038
2040 // update the number of hexes on the different levels in the
2041 // cache
2042 number_cache.n_hexes = 0;
2043 number_cache.n_active_hexes = 0;
2044
2045 // for 3d, hexes have levels so take count the objects per
2046 // level and globally
2047 if (dim == 3)
2048 {
2049 // count the number of levels; the function we called
2050 // above on a separate Task for quads (recursively, via
2051 // the lines function) also does this and puts it into
2052 // number_cache.n_levels, but this datum may not yet be
2053 // available as we call the function on a separate task
2054 unsigned int n_levels = 0;
2055 if (level_objects > 0)
2056 // find the last level on which there are used cells
2057 for (unsigned int level = 0; level < level_objects; ++level)
2058 if (triangulation.begin(level) != triangulation.end(level))
2059 n_levels = level + 1;
2060
2061 number_cache.n_hexes_level.resize(n_levels);
2062 number_cache.n_active_hexes_level.resize(n_levels);
2063
2064 for (unsigned int level = 0; level < n_levels; ++level)
2065 {
2066 // count hexes on this level
2067 number_cache.n_hexes_level[level] = 0;
2068 number_cache.n_active_hexes_level[level] = 0;
2069
2070 hex_iterator hex = triangulation.begin_hex(level),
2071 endc = (level == n_levels - 1 ?
2072 hex_iterator(triangulation.end_hex()) :
2073 triangulation.begin_hex(level + 1));
2074 for (; hex != endc; ++hex)
2075 {
2076 ++number_cache.n_hexes_level[level];
2077 if (hex->has_children() == false)
2078 ++number_cache.n_active_hexes_level[level];
2079 }
2080
2081 // update total number of hexes
2082 number_cache.n_hexes += number_cache.n_hexes_level[level];
2083 number_cache.n_active_hexes +=
2084 number_cache.n_active_hexes_level[level];
2085 }
2086 }
2087 else
2088 {
2089 // for dim>3, there are no levels for hexes
2090 number_cache.n_hexes_level.clear();
2091 number_cache.n_active_hexes_level.clear();
2092
2093 hex_iterator hex = triangulation.begin_hex(),
2094 endc = triangulation.end_hex();
2095 for (; hex != endc; ++hex)
2096 {
2097 ++number_cache.n_hexes;
2098 if (hex->has_children() == false)
2099 ++number_cache.n_active_hexes;
2100 }
2101 }
2102
2103 // wait for the background computation for quads
2104 update_quads_and_lines.join();
2105 }
2106
2107
2108
2109 template <int spacedim>
2111 {}
2112
2113
2114 template <int dim, int spacedim>
2115 static void
2117 {
2118 // each face can be neighbored on two sides
2119 // by cells. according to the face's
2120 // intrinsic normal we define the left
2121 // neighbor as the one for which the face
2122 // normal points outward, and store that
2123 // one first; the second one is then
2124 // the right neighbor for which the
2125 // face normal points inward. This
2126 // information depends on the type of cell
2127 // and local number of face for the
2128 // 'standard ordering and orientation' of
2129 // faces and then on the face_orientation
2130 // information for the real mesh. Set up a
2131 // table to have fast access to those
2132 // offsets (0 for left and 1 for
2133 // right). Some of the values are invalid
2134 // as they reference too large face
2135 // numbers, but we just leave them at a
2136 // zero value.
2137 //
2138 // Note, that in 2d for lines as faces the
2139 // normal direction given in the
2140 // GeometryInfo class is not consistent. We
2141 // thus define here that the normal for a
2142 // line points to the right if the line
2143 // points upwards.
2144 //
2145 // There is one more point to
2146 // consider, however: if we have
2147 // dim<spacedim, then we may have
2148 // cases where cells are
2149 // inverted. In effect, both
2150 // cells think they are the left
2151 // neighbor of an edge, for
2152 // example, which leads us to
2153 // forget neighborship
2154 // information (a case that shows
2155 // this is
2156 // codim_one/hanging_nodes_02). We
2157 // store whether a cell is
2158 // inverted using the
2159 // direction_flag, so if a cell
2160 // has a false direction_flag,
2161 // then we need to invert our
2162 // selection whether we are a
2163 // left or right neighbor in all
2164 // following computations.
2165 //
2166 // first index: dimension (minus 2)
2167 // second index: local face index
2168 // third index: face_orientation (false and true)
2169 static const unsigned int left_right_offset[2][6][2] = {
2170 // quadrilateral
2171 {{0, 1}, // face 0, face_orientation = false and true
2172 {1, 0}, // face 1, face_orientation = false and true
2173 {1, 0}, // face 2, face_orientation = false and true
2174 {0, 1}, // face 3, face_orientation = false and true
2175 {0, 0}, // face 4, invalid face
2176 {0, 0}}, // face 5, invalid face
2177 // hexahedron
2178 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
2179
2180 // now create a vector of the two active
2181 // neighbors (left and right) for each face
2182 // and fill it by looping over all cells. For
2183 // cases with anisotropic refinement and more
2184 // then one cell neighboring at a given side
2185 // of the face we will automatically get the
2186 // active one on the highest level as we loop
2187 // over cells from lower levels first.
2189 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
2190 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
2191
2192 for (const auto &cell : triangulation.cell_iterators())
2193 for (auto f : cell->face_indices())
2194 {
2196 cell->face(f);
2197
2198 const unsigned int offset =
2199 (cell->direction_flag() ?
2200 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2201 1 -
2202 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2203
2204 adjacent_cells[2 * face->index() + offset] = cell;
2205
2206 // if this cell is not refined, but the
2207 // face is, then we'll have to set our
2208 // cell as neighbor for the child faces
2209 // as well. Fortunately the normal
2210 // orientation of children will be just
2211 // the same.
2212 if (dim == 2)
2213 {
2214 if (cell->is_active() && face->has_children())
2215 {
2216 adjacent_cells[2 * face->child(0)->index() + offset] =
2217 cell;
2218 adjacent_cells[2 * face->child(1)->index() + offset] =
2219 cell;
2220 }
2221 }
2222 else // -> dim == 3
2223 {
2224 // We need the same as in 2d
2225 // here. Furthermore, if the face is
2226 // refined with cut_x or cut_y then
2227 // those children again in the other
2228 // direction, and if this cell is
2229 // refined isotropically (along the
2230 // face) then the neighbor will
2231 // (probably) be refined as cut_x or
2232 // cut_y along the face. For those
2233 // neighboring children cells, their
2234 // neighbor will be the current,
2235 // inactive cell, as our children are
2236 // too fine to be neighbors. Catch that
2237 // case by also acting on inactive
2238 // cells with isotropic refinement
2239 // along the face. If the situation
2240 // described is not present, the data
2241 // will be overwritten later on when we
2242 // visit cells on finer levels, so no
2243 // harm will be done.
2244 if (face->has_children() &&
2245 (cell->is_active() ||
2247 cell->refinement_case(), f) ==
2248 RefinementCase<dim - 1>::isotropic_refinement))
2249 {
2250 for (unsigned int c = 0; c < face->n_children(); ++c)
2251 adjacent_cells[2 * face->child(c)->index() + offset] =
2252 cell;
2253 if (face->child(0)->has_children())
2254 {
2255 adjacent_cells[2 * face->child(0)->child(0)->index() +
2256 offset] = cell;
2257 adjacent_cells[2 * face->child(0)->child(1)->index() +
2258 offset] = cell;
2259 }
2260 if (face->child(1)->has_children())
2261 {
2262 adjacent_cells[2 * face->child(1)->child(0)->index() +
2263 offset] = cell;
2264 adjacent_cells[2 * face->child(1)->child(1)->index() +
2265 offset] = cell;
2266 }
2267 } // if cell active and face refined
2268 } // else -> dim==3
2269 } // for all faces of all cells
2270
2271 // now loop again over all cells and set the
2272 // corresponding neighbor cell. Note, that we
2273 // have to use the opposite of the
2274 // left_right_offset in this case as we want
2275 // the offset of the neighbor, not our own.
2276 for (const auto &cell : triangulation.cell_iterators())
2277 for (auto f : cell->face_indices())
2278 {
2279 const unsigned int offset =
2280 (cell->direction_flag() ?
2281 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2282 1 -
2283 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2284 cell->set_neighbor(
2285 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
2286 }
2287 }
2288
2289
2293 template <int dim, int spacedim>
2294 static void
2296 const std::vector<CellData<dim>> & cells,
2297 const SubCellData & subcelldata,
2299 {
2300 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
2301 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
2302
2303 // Check that all cells have positive volume.
2304#ifndef _MSC_VER
2305 // TODO: The following code does not compile with MSVC. Find a way
2306 // around it
2307 if (dim == spacedim)
2308 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
2309 {
2310 // If we should check for distorted cells, then we permit them
2311 // to exist. If a cell has negative measure, then it must be
2312 // distorted (the converse is not necessarily true); hence
2313 // throw an exception if no such cells should exist.
2315 {
2316 const double cell_measure = GridTools::cell_measure<spacedim>(
2317 vertices,
2318 ArrayView<const unsigned int>(cells[cell_no].vertices));
2320 }
2321 }
2322#endif
2323
2324 // clear old content
2325 tria.levels.clear();
2326 tria.levels.push_back(
2327 std::make_unique<
2329
2330 if (dim > 1)
2331 tria.faces = std::make_unique<
2333
2334 // copy vertices
2335 tria.vertices = vertices;
2336 tria.vertices_used.assign(vertices.size(), true);
2337
2338 // compute connectivity
2339 const auto connectivity = build_connectivity<unsigned int>(cells);
2340 const unsigned int n_cell = cells.size();
2341
2342 // TriaObjects: lines
2343 if (dim >= 2)
2344 {
2345 auto &lines_0 = tria.faces->lines; // data structure to be filled
2346
2347 // get connectivity between quads and lines
2348 const auto & crs = connectivity.entity_to_entities(1, 0);
2349 const unsigned int n_lines = crs.ptr.size() - 1;
2350
2351 // allocate memory
2352 reserve_space_(lines_0, n_lines);
2353
2354 // loop over lines
2355 for (unsigned int line = 0; line < n_lines; ++line)
2356 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
2357 ++i, ++j)
2358 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
2359 crs.col[i]; // set vertex indices
2360 }
2361
2362 // TriaObjects: quads
2363 if (dim == 3)
2364 {
2365 auto &quads_0 = tria.faces->quads; // data structures to be filled
2366 auto &faces = *tria.faces;
2367
2368 // get connectivity between quads and lines
2369 const auto & crs = connectivity.entity_to_entities(2, 1);
2370 const unsigned int n_quads = crs.ptr.size() - 1;
2371
2372 // allocate memory
2373 reserve_space_(quads_0, n_quads);
2374 reserve_space_(faces, 2 /*structdim*/, n_quads);
2375
2376 // loop over all quads -> entity type, line indices/orientations
2377 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
2378 {
2379 // set entity type of quads
2380 faces.quad_reference_cell[q] = connectivity.entity_types(2)[q];
2381
2382 // loop over all its lines
2383 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
2384 ++i, ++j, ++k)
2385 {
2386 // set line index
2387 quads_0.cells[q * GeometryInfo<2>::faces_per_cell + j] =
2388 crs.col[i];
2389
2390 // set line orientations
2391 faces.quads_line_orientations
2393 connectivity.entity_orientations(1)[k];
2394 }
2395 }
2396 }
2397
2398 // TriaObjects/TriaLevel: cell
2399 {
2400 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
2401 auto &level = *tria.levels[0];
2402
2403 // get connectivity between cells/faces and cells/cells
2404 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2405 const auto &nei = connectivity.entity_to_entities(dim, dim);
2406
2407 // in 2D optional: since in in pure QUAD meshes same line
2408 // orientations can be guaranteed
2409 const bool orientation_needed =
2410 dim == 3 ||
2411 (dim == 2 &&
2412 std::any_of(connectivity.entity_orientations(1).begin(),
2413 connectivity.entity_orientations(1).end(),
2414 [](const auto &i) { return i == 0; }));
2415
2416 // allocate memory
2417 reserve_space_(cells_0, n_cell);
2418 reserve_space_(level, spacedim, n_cell, orientation_needed);
2419
2420 // loop over all cells
2421 for (unsigned int cell = 0; cell < n_cell; ++cell)
2422 {
2423 // set material ids
2424 cells_0.boundary_or_material_id[cell].material_id =
2425 cells[cell].material_id;
2426
2427 // set manifold ids
2428 cells_0.manifold_id[cell] = cells[cell].manifold_id;
2429
2430 // set entity types
2431 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
2432
2433 // loop over faces
2434 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2435 ++i, ++j)
2436 {
2437 // set neighbor if not at boundary
2438 if (nei.col[i] != static_cast<unsigned int>(-1))
2439 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
2440 j] = {0, nei.col[i]};
2441
2442 // set face indices
2443 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
2444 crs.col[i];
2445
2446 // set face orientation if needed
2447 if (orientation_needed)
2448 level.face_orientations
2450 connectivity.entity_orientations(dim - 1)[i];
2451 }
2452 }
2453 }
2454
2455 // TriaFaces: boundary id of boundary faces
2456 if (dim > 1)
2457 {
2458 auto &bids_face = dim == 3 ?
2459 tria.faces->quads.boundary_or_material_id :
2460 tria.faces->lines.boundary_or_material_id;
2461
2462 // count number of cells a face is belonging to
2463 std::vector<unsigned int> count(bids_face.size(), 0);
2464
2465 // get connectivity between cells/faces
2466 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2467
2468 // count how many cells are adjacent to the same face
2469 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2470 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
2471 count[crs.col[i]]++;
2472
2473 // loop over all faces
2474 for (unsigned int face = 0; face < count.size(); ++face)
2475 {
2476 if (count[face] != 1) // inner face
2477 continue;
2478
2479 // boundary faces ...
2480 bids_face[face].boundary_id = 0;
2481
2482 if (dim != 3)
2483 continue;
2484
2485 // ... and the lines of quads in 3D
2486 const auto &crs = connectivity.entity_to_entities(2, 1);
2487 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
2488 tria.faces->lines.boundary_or_material_id[crs.col[i]]
2489 .boundary_id = 0;
2490 }
2491 }
2492 else // 1D
2493 {
2494 static const unsigned int t_tba = static_cast<unsigned int>(-1);
2495 static const unsigned int t_inner = static_cast<unsigned int>(-2);
2496
2497 std::vector<unsigned int> type(vertices.size(), t_tba);
2498
2499 const auto &crs = connectivity.entity_to_entities(1, 0);
2500
2501 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2502 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2503 ++i, ++j)
2504 if (type[crs.col[i]] != t_inner)
2505 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
2506
2507 for (unsigned int face = 0; face < type.size(); ++face)
2508 {
2509 // note: we also treat manifolds here!?
2510 (*tria.vertex_to_manifold_id_map_1d)[face] =
2512 if (type[face] != t_inner && type[face] != t_tba)
2513 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
2514 }
2515 }
2516
2517 // SubCellData: line
2518 if (dim >= 2)
2519 process_subcelldata(connectivity.entity_to_entities(1, 0),
2520 tria.faces->lines,
2521 subcelldata.boundary_lines);
2522
2523 // SubCellData: quad
2524 if (dim == 3)
2525 process_subcelldata(connectivity.entity_to_entities(2, 0),
2526 tria.faces->quads,
2527 subcelldata.boundary_quads);
2528 }
2529
2530
2531 template <int structdim, typename T>
2532 static void
2534 const CRS<T> & crs,
2535 TriaObjects & obj,
2536 const std::vector<CellData<structdim>> &boundary_objects_in)
2537 {
2538 AssertDimension(obj.structdim, structdim);
2539
2540 if (boundary_objects_in.size() == 0)
2541 return; // empty subcelldata -> nothing to do
2542
2543 // pre-sort subcelldata
2544 auto boundary_objects = boundary_objects_in;
2545
2546 // ... sort vertices
2547 for (auto &boundary_object : boundary_objects)
2548 std::sort(boundary_object.vertices.begin(),
2549 boundary_object.vertices.end());
2550
2551 // ... sort cells
2552 std::sort(boundary_objects.begin(),
2553 boundary_objects.end(),
2554 [](const auto &a, const auto &b) {
2555 return a.vertices < b.vertices;
2556 });
2557
2558 unsigned int counter = 0;
2559
2560 std::vector<unsigned int> key;
2562
2563 for (unsigned int o = 0; o < obj.n_objects(); ++o)
2564 {
2565 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
2566 auto &manifold_id = obj.manifold_id[o];
2567
2568 // assert that object has not been visited yet and its value
2569 // has not been modified yet
2570 AssertThrow(boundary_id == 0 ||
2575
2576 // create key
2577 key.assign(crs.col.data() + crs.ptr[o],
2578 crs.col.data() + crs.ptr[o + 1]);
2579 std::sort(key.begin(), key.end());
2580
2581 // is subcelldata provided? -> binary search
2582 const auto subcell_object =
2583 std::lower_bound(boundary_objects.begin(),
2584 boundary_objects.end(),
2585 key,
2586 [&](const auto &cell, const auto &key) {
2587 return cell.vertices < key;
2588 });
2589
2590 // no subcelldata provided for this object
2591 if (subcell_object == boundary_objects.end() ||
2592 subcell_object->vertices != key)
2593 continue;
2594
2595 counter++;
2596
2597 // set manifold id
2598 manifold_id = subcell_object->manifold_id;
2599
2600 // set boundary id
2601 if (subcell_object->boundary_id !=
2603 {
2606 boundary_id = subcell_object->boundary_id;
2607 }
2608 }
2609
2610 // make sure that all subcelldata entries have been processed
2611 // TODO: this is not guaranteed, why?
2612 // AssertDimension(counter, boundary_objects_in.size());
2613 }
2614
2615
2616
2617 static void
2619 const unsigned structdim,
2620 const unsigned int size)
2621 {
2622 const unsigned int dim = faces.dim;
2623
2624 const unsigned int max_faces_per_cell = 2 * structdim;
2625
2626 if (dim == 3 && structdim == 2)
2627 {
2628 // quad entity types
2629 faces.quad_reference_cell.assign(size,
2631
2632 // quad line orientations
2633 faces.quads_line_orientations.assign(size * max_faces_per_cell, -1);
2634 }
2635 }
2636
2637
2638
2639 static void
2641 const unsigned int spacedim,
2642 const unsigned int size,
2643 const bool orientation_needed)
2644 {
2645 const unsigned int dim = level.dim;
2646
2647 const unsigned int max_faces_per_cell = 2 * dim;
2648
2649 level.active_cell_indices.assign(size, -1);
2650 level.subdomain_ids.assign(size, 0);
2651 level.level_subdomain_ids.assign(size, 0);
2652
2653 level.refine_flags.assign(size, false);
2654 level.coarsen_flags.assign(size, false);
2655
2656 level.parents.assign((size + 1) / 2, -1);
2657
2658 if (dim < spacedim)
2659 level.direction_flags.assign(size, true);
2660
2661 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
2662
2663 level.reference_cell.assign(size, ::ReferenceCells::Invalid);
2664
2665 if (orientation_needed)
2666 level.face_orientations.assign(size * max_faces_per_cell, -1);
2667
2668 level.global_active_cell_indices.assign(size,
2670 level.global_level_cell_indices.assign(size,
2672 }
2673
2674
2675
2676 static void
2677 reserve_space_(TriaObjects &obj, const unsigned int size)
2678 {
2679 const unsigned int structdim = obj.structdim;
2680
2681 const unsigned int max_children_per_cell = 1 << structdim;
2682 const unsigned int max_faces_per_cell = 2 * structdim;
2683
2684 obj.used.assign(size, true);
2685 obj.boundary_or_material_id.assign(
2686 size,
2688 BoundaryOrMaterialId());
2689 obj.manifold_id.assign(size, -1);
2690 obj.user_flags.assign(size, false);
2691 obj.user_data.resize(size);
2692
2693 if (structdim > 1) // TODO: why?
2694 obj.refinement_cases.assign(size, 0);
2695
2696 obj.children.assign(max_children_per_cell / 2 * size, -1);
2697
2698 obj.cells.assign(max_faces_per_cell * size, -1);
2699
2700 if (structdim <= 2)
2701 {
2702 obj.next_free_single = size - 1;
2703 obj.next_free_pair = 0;
2705 }
2706 else
2707 {
2708 obj.next_free_single = obj.next_free_pair = 0;
2709 }
2710 }
2711
2712
2728 template <int spacedim>
2729 static void delete_children(
2732 std::vector<unsigned int> &,
2733 std::vector<unsigned int> &)
2734 {
2735 const unsigned int dim = 1;
2736
2737 // first we need to reset the
2738 // neighbor pointers of the
2739 // neighbors of this cell's
2740 // children to this cell. This is
2741 // different for one dimension,
2742 // since there neighbors can have a
2743 // refinement level differing from
2744 // that of this cell's children by
2745 // more than one level.
2746
2747 Assert(!cell->child(0)->has_children() &&
2748 !cell->child(1)->has_children(),
2750
2751 // first do it for the cells to the
2752 // left
2753 if (cell->neighbor(0).state() == IteratorState::valid)
2754 if (cell->neighbor(0)->has_children())
2755 {
2757 cell->neighbor(0);
2758 Assert(neighbor->level() == cell->level(), ExcInternalError());
2759
2760 // right child
2761 neighbor = neighbor->child(1);
2762 while (true)
2763 {
2764 Assert(neighbor->neighbor(1) == cell->child(0),
2766 neighbor->set_neighbor(1, cell);
2767
2768 // move on to further
2769 // children on the
2770 // boundary between this
2771 // cell and its neighbor
2772 if (neighbor->has_children())
2773 neighbor = neighbor->child(1);
2774 else
2775 break;
2776 }
2777 }
2778
2779 // now do it for the cells to the
2780 // left
2781 if (cell->neighbor(1).state() == IteratorState::valid)
2782 if (cell->neighbor(1)->has_children())
2783 {
2785 cell->neighbor(1);
2786 Assert(neighbor->level() == cell->level(), ExcInternalError());
2787
2788 // left child
2789 neighbor = neighbor->child(0);
2790 while (true)
2791 {
2792 Assert(neighbor->neighbor(0) == cell->child(1),
2794 neighbor->set_neighbor(0, cell);
2795
2796 // move on to further
2797 // children on the
2798 // boundary between this
2799 // cell and its neighbor
2800 if (neighbor->has_children())
2801 neighbor = neighbor->child(0);
2802 else
2803 break;
2804 }
2805 }
2806
2807
2808 // delete the vertex which will not
2809 // be needed anymore. This vertex
2810 // is the second of the first child
2811 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
2812
2813 // invalidate children. clear user
2814 // pointers, to avoid that they may
2815 // appear at unwanted places later
2816 // on...
2817 for (unsigned int child = 0; child < cell->n_children(); ++child)
2818 {
2819 cell->child(child)->clear_user_data();
2820 cell->child(child)->clear_user_flag();
2821 cell->child(child)->clear_used_flag();
2822 }
2823
2824
2825 // delete pointer to children
2826 cell->clear_children();
2827 cell->clear_user_flag();
2828 }
2829
2830
2831
2832 template <int spacedim>
2833 static void delete_children(
2836 std::vector<unsigned int> & line_cell_count,
2837 std::vector<unsigned int> &)
2838 {
2839 const unsigned int dim = 2;
2840 const RefinementCase<dim> ref_case = cell->refinement_case();
2841
2842 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2844
2845 // vectors to hold all lines which
2846 // may be deleted
2847 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2848 lines_to_delete(0);
2849
2850 lines_to_delete.reserve(4 * 2 + 4);
2851
2852 // now we decrease the counters for
2853 // lines contained in the child
2854 // cells
2855 for (unsigned int c = 0; c < cell->n_children(); ++c)
2856 {
2858 cell->child(c);
2859 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
2860 --line_cell_count[child->line_index(l)];
2861 }
2862
2863
2864 // delete the vertex which will not
2865 // be needed anymore. This vertex
2866 // is the second of the second line
2867 // of the first child, if the cell
2868 // is refined with cut_xy, else there
2869 // is no inner vertex.
2870 // additionally delete unneeded inner
2871 // lines
2872 if (ref_case == RefinementCase<dim>::cut_xy)
2873 {
2875 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
2876
2877 lines_to_delete.push_back(cell->child(0)->line(1));
2878 lines_to_delete.push_back(cell->child(0)->line(3));
2879 lines_to_delete.push_back(cell->child(3)->line(0));
2880 lines_to_delete.push_back(cell->child(3)->line(2));
2881 }
2882 else
2883 {
2884 unsigned int inner_face_no =
2885 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
2886
2887 // the inner line will not be
2888 // used any more
2889 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
2890 }
2891
2892 // invalidate children
2893 for (unsigned int child = 0; child < cell->n_children(); ++child)
2894 {
2895 cell->child(child)->clear_user_data();
2896 cell->child(child)->clear_user_flag();
2897 cell->child(child)->clear_used_flag();
2898 }
2899
2900
2901 // delete pointer to children
2902 cell->clear_children();
2903 cell->clear_refinement_case();
2904 cell->clear_user_flag();
2905
2906 // look at the refinement of outer
2907 // lines. if nobody needs those
2908 // anymore we can add them to the
2909 // list of lines to be deleted.
2910 for (unsigned int line_no = 0;
2911 line_no < GeometryInfo<dim>::lines_per_cell;
2912 ++line_no)
2913 {
2915 cell->line(line_no);
2916
2917 if (line->has_children())
2918 {
2919 // if one of the cell counters is
2920 // zero, the other has to be as well
2921
2922 Assert((line_cell_count[line->child_index(0)] == 0 &&
2923 line_cell_count[line->child_index(1)] == 0) ||
2924 (line_cell_count[line->child_index(0)] > 0 &&
2925 line_cell_count[line->child_index(1)] > 0),
2927
2928 if (line_cell_count[line->child_index(0)] == 0)
2929 {
2930 for (unsigned int c = 0; c < 2; ++c)
2931 Assert(!line->child(c)->has_children(),
2933
2934 // we may delete the line's
2935 // children and the middle vertex
2936 // as no cell references them
2937 // anymore
2939 .vertices_used[line->child(0)->vertex_index(1)] = false;
2940
2941 lines_to_delete.push_back(line->child(0));
2942 lines_to_delete.push_back(line->child(1));
2943
2944 line->clear_children();
2945 }
2946 }
2947 }
2948
2949 // finally, delete unneeded lines
2950
2951 // clear user pointers, to avoid that
2952 // they may appear at unwanted places
2953 // later on...
2954 // same for user flags, then finally
2955 // delete the lines
2956 typename std::vector<
2958 line = lines_to_delete.begin(),
2959 endline = lines_to_delete.end();
2960 for (; line != endline; ++line)
2961 {
2962 (*line)->clear_user_data();
2963 (*line)->clear_user_flag();
2964 (*line)->clear_used_flag();
2965 }
2966 }
2967
2968
2969
2970 template <int spacedim>
2971 static void delete_children(
2974 std::vector<unsigned int> & line_cell_count,
2975 std::vector<unsigned int> & quad_cell_count)
2976 {
2977 const unsigned int dim = 3;
2978
2979 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2981 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
2983
2984 // first of all, we store the RefineCase of
2985 // this cell
2986 const RefinementCase<dim> ref_case = cell->refinement_case();
2987 // vectors to hold all lines and quads which
2988 // may be deleted
2989 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2990 lines_to_delete(0);
2991 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
2992 quads_to_delete(0);
2993
2994 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
2995 quads_to_delete.reserve(6 * 4 + 12);
2996
2997 // now we decrease the counters for lines and
2998 // quads contained in the child cells
2999 for (unsigned int c = 0; c < cell->n_children(); ++c)
3000 {
3002 cell->child(c);
3003 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3004 --line_cell_count[child->line_index(l)];
3005 for (auto f : GeometryInfo<dim>::face_indices())
3006 --quad_cell_count[child->quad_index(f)];
3007 }
3008
3010 // delete interior quads and lines and the
3011 // interior vertex, depending on the
3012 // refinement case of the cell
3013 //
3014 // for append quads and lines: only append
3015 // them to the list of objects to be deleted
3016
3017 switch (ref_case)
3018 {
3020 quads_to_delete.push_back(cell->child(0)->face(1));
3021 break;
3023 quads_to_delete.push_back(cell->child(0)->face(3));
3024 break;
3026 quads_to_delete.push_back(cell->child(0)->face(5));
3027 break;
3029 quads_to_delete.push_back(cell->child(0)->face(1));
3030 quads_to_delete.push_back(cell->child(0)->face(3));
3031 quads_to_delete.push_back(cell->child(3)->face(0));
3032 quads_to_delete.push_back(cell->child(3)->face(2));
3033
3034 lines_to_delete.push_back(cell->child(0)->line(11));
3035 break;
3037 quads_to_delete.push_back(cell->child(0)->face(1));
3038 quads_to_delete.push_back(cell->child(0)->face(5));
3039 quads_to_delete.push_back(cell->child(3)->face(0));
3040 quads_to_delete.push_back(cell->child(3)->face(4));
3041
3042 lines_to_delete.push_back(cell->child(0)->line(5));
3043 break;
3045 quads_to_delete.push_back(cell->child(0)->face(3));
3046 quads_to_delete.push_back(cell->child(0)->face(5));
3047 quads_to_delete.push_back(cell->child(3)->face(2));
3048 quads_to_delete.push_back(cell->child(3)->face(4));
3049
3050 lines_to_delete.push_back(cell->child(0)->line(7));
3051 break;
3053 quads_to_delete.push_back(cell->child(0)->face(1));
3054 quads_to_delete.push_back(cell->child(2)->face(1));
3055 quads_to_delete.push_back(cell->child(4)->face(1));
3056 quads_to_delete.push_back(cell->child(6)->face(1));
3057
3058 quads_to_delete.push_back(cell->child(0)->face(3));
3059 quads_to_delete.push_back(cell->child(1)->face(3));
3060 quads_to_delete.push_back(cell->child(4)->face(3));
3061 quads_to_delete.push_back(cell->child(5)->face(3));
3062
3063 quads_to_delete.push_back(cell->child(0)->face(5));
3064 quads_to_delete.push_back(cell->child(1)->face(5));
3065 quads_to_delete.push_back(cell->child(2)->face(5));
3066 quads_to_delete.push_back(cell->child(3)->face(5));
3067
3068 lines_to_delete.push_back(cell->child(0)->line(5));
3069 lines_to_delete.push_back(cell->child(0)->line(7));
3070 lines_to_delete.push_back(cell->child(0)->line(11));
3071 lines_to_delete.push_back(cell->child(7)->line(0));
3072 lines_to_delete.push_back(cell->child(7)->line(2));
3073 lines_to_delete.push_back(cell->child(7)->line(8));
3074 // delete the vertex which will not
3075 // be needed anymore. This vertex
3076 // is the vertex at the heart of
3077 // this cell, which is the sixth of
3078 // the first child
3079 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
3080 false;
3081 break;
3082 default:
3083 // only remaining case is
3084 // no_refinement, thus an error
3085 Assert(false, ExcInternalError());
3086 break;
3087 }
3088
3089
3090 // invalidate children
3091 for (unsigned int child = 0; child < cell->n_children(); ++child)
3092 {
3093 cell->child(child)->clear_user_data();
3094 cell->child(child)->clear_user_flag();
3095
3096 for (auto f : GeometryInfo<dim>::face_indices())
3097 {
3098 // set flags denoting deviations from
3099 // standard orientation of faces back
3100 // to initialization values
3101 cell->child(child)->set_face_orientation(f, true);
3102 cell->child(child)->set_face_flip(f, false);
3103 cell->child(child)->set_face_rotation(f, false);
3104 }
3105
3106 cell->child(child)->clear_used_flag();
3107 }
3108
3109
3110 // delete pointer to children
3111 cell->clear_children();
3112 cell->clear_refinement_case();
3113 cell->clear_user_flag();
3114
3115 // so far we only looked at inner quads,
3116 // lines and vertices. Now we have to
3117 // consider outer ones as well. here, we have
3118 // to check, whether there are other cells
3119 // still needing these objects. otherwise we
3120 // can delete them. first for quads (and
3121 // their inner lines).
3122
3123 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
3124 {
3126 cell->face(quad_no);
3127
3128 Assert(
3129 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
3130 quad->has_children()) ||
3131 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
3134
3135 switch (quad->refinement_case())
3136 {
3137 case RefinementCase<dim - 1>::no_refinement:
3138 // nothing to do as the quad
3139 // is not refined
3140 break;
3141 case RefinementCase<dim - 1>::cut_x:
3142 case RefinementCase<dim - 1>::cut_y:
3143 {
3144 // if one of the cell counters is
3145 // zero, the other has to be as
3146 // well
3147 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3148 quad_cell_count[quad->child_index(1)] == 0) ||
3149 (quad_cell_count[quad->child_index(0)] > 0 &&
3150 quad_cell_count[quad->child_index(1)] > 0),
3152 // it might be, that the quad is
3153 // refined twice anisotropically,
3154 // first check, whether we may
3155 // delete possible grand_children
3156 unsigned int deleted_grandchildren = 0;
3157 unsigned int number_of_child_refinements = 0;
3158
3159 for (unsigned int c = 0; c < 2; ++c)
3160 if (quad->child(c)->has_children())
3161 {
3162 ++number_of_child_refinements;
3163 // if one of the cell counters is
3164 // zero, the other has to be as
3165 // well
3166 Assert(
3167 (quad_cell_count[quad->child(c)->child_index(0)] ==
3168 0 &&
3169 quad_cell_count[quad->child(c)->child_index(1)] ==
3170 0) ||
3171 (quad_cell_count[quad->child(c)->child_index(0)] >
3172 0 &&
3173 quad_cell_count[quad->child(c)->child_index(1)] >
3174 0),
3176 if (quad_cell_count[quad->child(c)->child_index(0)] ==
3177 0)
3178 {
3179 // Assert, that the two
3180 // anisotropic
3181 // refinements add up to
3182 // isotropic refinement
3183 Assert(quad->refinement_case() +
3184 quad->child(c)->refinement_case() ==
3187 // we may delete the
3188 // quad's children and
3189 // the inner line as no
3190 // cell references them
3191 // anymore
3192 quads_to_delete.push_back(
3193 quad->child(c)->child(0));
3194 quads_to_delete.push_back(
3195 quad->child(c)->child(1));
3196 if (quad->child(c)->refinement_case() ==
3198 lines_to_delete.push_back(
3199 quad->child(c)->child(0)->line(1));
3200 else
3201 lines_to_delete.push_back(
3202 quad->child(c)->child(0)->line(3));
3203 quad->child(c)->clear_children();
3204 quad->child(c)->clear_refinement_case();
3205 ++deleted_grandchildren;
3206 }
3207 }
3208 // if no grandchildren are left, we
3209 // may as well delete the
3210 // refinement of the inner line
3211 // between our children and the
3212 // corresponding vertex
3213 if (number_of_child_refinements > 0 &&
3214 deleted_grandchildren == number_of_child_refinements)
3215 {
3217 middle_line;
3218 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3219 middle_line = quad->child(0)->line(1);
3220 else
3221 middle_line = quad->child(0)->line(3);
3222
3223 lines_to_delete.push_back(middle_line->child(0));
3224 lines_to_delete.push_back(middle_line->child(1));
3226 .vertices_used[middle_vertex_index<dim, spacedim>(
3227 middle_line)] = false;
3228 middle_line->clear_children();
3229 }
3230
3231 // now consider the direct children
3232 // of the given quad
3233 if (quad_cell_count[quad->child_index(0)] == 0)
3234 {
3235 // we may delete the quad's
3236 // children and the inner line
3237 // as no cell references them
3238 // anymore
3239 quads_to_delete.push_back(quad->child(0));
3240 quads_to_delete.push_back(quad->child(1));
3241 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3242 lines_to_delete.push_back(quad->child(0)->line(1));
3243 else
3244 lines_to_delete.push_back(quad->child(0)->line(3));
3245
3246 // if the counters just dropped
3247 // to zero, otherwise the
3248 // children would have been
3249 // deleted earlier, then this
3250 // cell's children must have
3251 // contained the anisotropic
3252 // quad children. thus, if
3253 // those have again anisotropic
3254 // children, which are in
3255 // effect isotropic children of
3256 // the original quad, those are
3257 // still needed by a
3258 // neighboring cell and we
3259 // cannot delete them. instead,
3260 // we have to reset this quad's
3261 // refine case to isotropic and
3262 // set the children
3263 // accordingly.
3264 if (quad->child(0)->has_children())
3265 if (quad->refinement_case() ==
3267 {
3268 // now evereything is
3269 // quite complicated. we
3270 // have the children
3271 // numbered according to
3272 //
3273 // *---*---*
3274 // |n+1|m+1|
3275 // *---*---*
3276 // | n | m |
3277 // *---*---*
3278 //
3279 // from the original
3280 // anisotropic
3281 // refinement. we have to
3282 // reorder them as
3283 //
3284 // *---*---*
3285 // | m |m+1|
3286 // *---*---*
3287 // | n |n+1|
3288 // *---*---*
3289 //
3290 // for isotropic refinement.
3291 //
3292 // this is a bit ugly, of
3293 // course: loop over all
3294 // cells on all levels
3295 // and look for faces n+1
3296 // (switch_1) and m
3297 // (switch_2).
3298 const typename Triangulation<dim, spacedim>::
3299 quad_iterator switch_1 =
3300 quad->child(0)->child(1),
3301 switch_2 =
3302 quad->child(1)->child(0);
3303
3304 Assert(!switch_1->has_children(),
3306 Assert(!switch_2->has_children(),
3308
3309 const int switch_1_index = switch_1->index();
3310 const int switch_2_index = switch_2->index();
3311 for (unsigned int l = 0;
3312 l < triangulation.levels.size();
3313 ++l)
3314 for (unsigned int h = 0;
3315 h <
3316 triangulation.levels[l]->cells.n_objects();
3317 ++h)
3318 for (const unsigned int q :
3320 {
3321 const int index =
3322 triangulation.levels[l]
3323 ->cells.get_bounding_object_indices(
3324 h)[q];
3325 if (index == switch_1_index)
3326 triangulation.levels[l]
3327 ->cells.get_bounding_object_indices(
3328 h)[q] = switch_2_index;
3329 else if (index == switch_2_index)
3330 triangulation.levels[l]
3331 ->cells.get_bounding_object_indices(
3332 h)[q] = switch_1_index;
3333 }
3334 // now we have to copy
3335 // all information of the
3336 // two quads
3337 const int switch_1_lines[4] = {
3338 static_cast<signed int>(
3339 switch_1->line_index(0)),
3340 static_cast<signed int>(
3341 switch_1->line_index(1)),
3342 static_cast<signed int>(
3343 switch_1->line_index(2)),
3344 static_cast<signed int>(
3345 switch_1->line_index(3))};
3346 const bool switch_1_line_orientations[4] = {
3347 switch_1->line_orientation(0),
3348 switch_1->line_orientation(1),
3349 switch_1->line_orientation(2),
3350 switch_1->line_orientation(3)};
3351 const types::boundary_id switch_1_boundary_id =
3352 switch_1->boundary_id();
3353 const unsigned int switch_1_user_index =
3354 switch_1->user_index();
3355 const bool switch_1_user_flag =
3356 switch_1->user_flag_set();
3357
3358 switch_1->set_bounding_object_indices(
3359 {switch_2->line_index(0),
3360 switch_2->line_index(1),
3361 switch_2->line_index(2),
3362 switch_2->line_index(3)});
3363 switch_1->set_line_orientation(
3364 0, switch_2->line_orientation(0));
3365 switch_1->set_line_orientation(
3366 1, switch_2->line_orientation(1));
3367 switch_1->set_line_orientation(
3368 2, switch_2->line_orientation(2));
3369 switch_1->set_line_orientation(
3370 3, switch_2->line_orientation(3));
3371 switch_1->set_boundary_id_internal(
3372 switch_2->boundary_id());
3373 switch_1->set_manifold_id(
3374 switch_2->manifold_id());
3375 switch_1->set_user_index(switch_2->user_index());
3376 if (switch_2->user_flag_set())
3377 switch_1->set_user_flag();
3378 else
3379 switch_1->clear_user_flag();
3380
3381 switch_2->set_bounding_object_indices(
3382 {switch_1_lines[0],
3383 switch_1_lines[1],
3384 switch_1_lines[2],
3385 switch_1_lines[3]});
3386 switch_2->set_line_orientation(
3387 0, switch_1_line_orientations[0]);
3388 switch_2->set_line_orientation(
3389 1, switch_1_line_orientations[1]);
3390 switch_2->set_line_orientation(
3391 2, switch_1_line_orientations[2]);
3392 switch_2->set_line_orientation(
3393 3, switch_1_line_orientations[3]);
3394 switch_2->set_boundary_id_internal(
3395 switch_1_boundary_id);
3396 switch_2->set_manifold_id(
3397 switch_1->manifold_id());
3398 switch_2->set_user_index(switch_1_user_index);
3399 if (switch_1_user_flag)
3400 switch_2->set_user_flag();
3401 else
3402 switch_2->clear_user_flag();
3403
3404 const unsigned int child_0 =
3405 quad->child(0)->child_index(0);
3406 const unsigned int child_2 =
3407 quad->child(1)->child_index(0);
3408 quad->clear_children();
3409 quad->clear_refinement_case();
3410 quad->set_refinement_case(
3412 quad->set_children(0, child_0);
3413 quad->set_children(2, child_2);
3414 std::swap(quad_cell_count[child_0 + 1],
3415 quad_cell_count[child_2]);
3416 }
3417 else
3418 {
3419 // the face was refined
3420 // with cut_y, thus the
3421 // children are already
3422 // in correct order. we
3423 // only have to set them
3424 // correctly, deleting
3425 // the indirection of two
3426 // anisotropic refinement
3427 // and going directly
3428 // from the quad to
3429 // isotropic children
3430 const unsigned int child_0 =
3431 quad->child(0)->child_index(0);
3432 const unsigned int child_2 =
3433 quad->child(1)->child_index(0);
3434 quad->clear_children();
3435 quad->clear_refinement_case();
3436 quad->set_refinement_case(
3438 quad->set_children(0, child_0);
3439 quad->set_children(2, child_2);
3440 }
3441 else
3442 {
3443 quad->clear_children();
3444 quad->clear_refinement_case();
3445 }
3446 }
3447 break;
3448 }
3449 case RefinementCase<dim - 1>::cut_xy:
3450 {
3451 // if one of the cell counters is
3452 // zero, the others have to be as
3453 // well
3454
3455 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3456 quad_cell_count[quad->child_index(1)] == 0 &&
3457 quad_cell_count[quad->child_index(2)] == 0 &&
3458 quad_cell_count[quad->child_index(3)] == 0) ||
3459 (quad_cell_count[quad->child_index(0)] > 0 &&
3460 quad_cell_count[quad->child_index(1)] > 0 &&
3461 quad_cell_count[quad->child_index(2)] > 0 &&
3462 quad_cell_count[quad->child_index(3)] > 0),
3464
3465 if (quad_cell_count[quad->child_index(0)] == 0)
3466 {
3467 // we may delete the quad's
3468 // children, the inner lines
3469 // and the middle vertex as no
3470 // cell references them anymore
3471 lines_to_delete.push_back(quad->child(0)->line(1));
3472 lines_to_delete.push_back(quad->child(3)->line(0));
3473 lines_to_delete.push_back(quad->child(0)->line(3));
3474 lines_to_delete.push_back(quad->child(3)->line(2));
3475
3476 for (unsigned int child = 0; child < quad->n_children();
3477 ++child)
3478 quads_to_delete.push_back(quad->child(child));
3479
3481 .vertices_used[quad->child(0)->vertex_index(3)] =
3482 false;
3483
3484 quad->clear_children();
3485 quad->clear_refinement_case();
3486 }
3487 }
3488 break;
3489
3490 default:
3491 Assert(false, ExcInternalError());
3492 break;
3493 }
3494 }
3495
3496 // now we repeat a similar procedure
3497 // for the outer lines of this cell.
3498
3499 // if in debug mode: check that each
3500 // of the lines for which we consider
3501 // deleting the children in fact has
3502 // children (the bits/coarsening_3d
3503 // test tripped over this initially)
3504 for (unsigned int line_no = 0;
3505 line_no < GeometryInfo<dim>::lines_per_cell;
3506 ++line_no)
3507 {
3509 cell->line(line_no);
3510
3511 Assert(
3512 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
3513 line->has_children()) ||
3514 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
3517
3518 if (line->has_children())
3519 {
3520 // if one of the cell counters is
3521 // zero, the other has to be as well
3522
3523 Assert((line_cell_count[line->child_index(0)] == 0 &&
3524 line_cell_count[line->child_index(1)] == 0) ||
3525 (line_cell_count[line->child_index(0)] > 0 &&
3526 line_cell_count[line->child_index(1)] > 0),
3528
3529 if (line_cell_count[line->child_index(0)] == 0)
3530 {
3531 for (unsigned int c = 0; c < 2; ++c)
3532 Assert(!line->child(c)->has_children(),
3534
3535 // we may delete the line's
3536 // children and the middle vertex
3537 // as no cell references them
3538 // anymore
3540 .vertices_used[line->child(0)->vertex_index(1)] = false;
3541
3542 lines_to_delete.push_back(line->child(0));
3543 lines_to_delete.push_back(line->child(1));
3544
3545 line->clear_children();
3546 }
3547 }
3548 }
3549
3550 // finally, delete unneeded quads and lines
3551
3552 // clear user pointers, to avoid that
3553 // they may appear at unwanted places
3554 // later on...
3555 // same for user flags, then finally
3556 // delete the quads and lines
3557 typename std::vector<
3559 line = lines_to_delete.begin(),
3560 endline = lines_to_delete.end();
3561 for (; line != endline; ++line)
3562 {
3563 (*line)->clear_user_data();
3564 (*line)->clear_user_flag();
3565 (*line)->clear_used_flag();
3566 }
3567
3568 typename std::vector<
3570 quad = quads_to_delete.begin(),
3571 endquad = quads_to_delete.end();
3572 for (; quad != endquad; ++quad)
3573 {
3574 (*quad)->clear_user_data();
3575 (*quad)->clear_children();
3576 (*quad)->clear_refinement_case();
3577 (*quad)->clear_user_flag();
3578 (*quad)->clear_used_flag();
3579 }
3580 }
3581
3582
3600 template <int spacedim>
3601 static void create_children(
3603 unsigned int & next_unused_vertex,
3605 &next_unused_line,
3607 &next_unused_cell,
3608 const typename Triangulation<2, spacedim>::cell_iterator &cell)
3609 {
3610 const unsigned int dim = 2;
3611 // clear refinement flag
3612 const RefinementCase<dim> ref_case = cell->refine_flag_set();
3613 cell->clear_refine_flag();
3614
3615 /* For the refinement process: since we go the levels up from the
3616 lowest, there are (unlike above) only two possibilities: a neighbor
3617 cell is on the same level or one level up (in both cases, it may or
3618 may not be refined later on, but we don't care here).
3619
3620 First:
3621 Set up an array of the 3x3 vertices, which are distributed on the
3622 cell (the array consists of indices into the @p{vertices} std::vector
3623
3624 2--7--3
3625 | | |
3626 4--8--5
3627 | | |
3628 0--6--1
3629
3630 note: in case of cut_x or cut_y not all these vertices are needed for
3631 the new cells
3632
3633 Second:
3634 Set up an array of the new lines (the array consists of iterator
3635 pointers into the lines arrays)
3636
3637 .-6-.-7-. The directions are: .->-.->-.
3638 1 9 3 ^ ^ ^
3639 .-10.11-. .->-.->-.
3640 0 8 2 ^ ^ ^
3641 .-4-.-5-. .->-.->-.
3642
3643 cut_x:
3644 .-4-.-5-.
3645 | | |
3646 0 6 1
3647 | | |
3648 .-2-.-3-.
3649
3650 cut_y:
3651 .---5---.
3652 1 3
3653 .---6---.
3654 0 2
3655 .---4---.
3656
3657
3658 Third:
3659 Set up an array of neighbors:
3660
3661 6 7
3662 .--.--.
3663 1| | |3
3664 .--.--.
3665 0| | |2
3666 .--.--.
3667 4 5
3668
3669 We need this array for two reasons: first to get the lines which will
3670 bound the four subcells (if the neighboring cell is refined, these
3671 lines already exist), and second to update neighborship information.
3672 Since if a neighbor is not refined, its neighborship record only
3673 points to the present, unrefined, cell rather than the children we
3674 are presently creating, we only need the neighborship information
3675 if the neighbor cells are refined. In all other cases, we store
3676 the unrefined neighbor address
3677
3678 We also need for every neighbor (if refined) which number among its
3679 neighbors the present (unrefined) cell has, since that number is to
3680 be replaced and because that also is the number of the subline which
3681 will be the interface between that neighbor and the to be created
3682 cell. We will store this number (between 0 and 3) in the field
3683 @p{neighbors_neighbor}.
3684
3685 It would be sufficient to use the children of the common line to the
3686 neighbor, if we only wanted to get the new sublines and the new
3687 vertex, but because we need to update the neighborship information of
3688 the two refined subcells of the neighbor, we need to search these
3689 anyway.
3690
3691 Convention:
3692 The created children are numbered like this:
3693
3694 .--.--.
3695 |2 . 3|
3696 .--.--.
3697 |0 | 1|
3698 .--.--.
3699 */
3700 // collect the
3701 // indices of the
3702 // eight
3703 // surrounding
3704 // vertices
3705 // 2--7--3
3706 // | | |
3707 // 4--9--5
3708 // | | |
3709 // 0--6--1
3710 int new_vertices[9];
3711 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
3712 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
3713 for (unsigned int line_no = 0; line_no < 4; ++line_no)
3714 if (cell->line(line_no)->has_children())
3715 new_vertices[4 + line_no] =
3716 cell->line(line_no)->child(0)->vertex_index(1);
3717
3718 if (ref_case == RefinementCase<dim>::cut_xy)
3719 {
3720 // find the next
3721 // unused vertex and
3722 // allocate it for
3723 // the new vertex we
3724 // need here
3725 while (triangulation.vertices_used[next_unused_vertex] == true)
3726 ++next_unused_vertex;
3727 Assert(
3728 next_unused_vertex < triangulation.vertices.size(),
3729 ExcMessage(
3730 "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."));
3731 triangulation.vertices_used[next_unused_vertex] = true;
3732
3733 new_vertices[8] = next_unused_vertex;
3734
3735 // if this quad lives
3736 // in 2d, then we can
3737 // compute the new
3738 // central vertex
3739 // location just from
3740 // the surrounding
3741 // ones. If this is
3742 // not the case, then
3743 // we need to ask a
3744 // boundary object
3745 if (dim == spacedim)
3746 {
3747 // triangulation.vertices[next_unused_vertex] = new_point;
3748 triangulation.vertices[next_unused_vertex] = cell->center(true);
3749
3750 // if the user_flag is set, i.e. if the cell is at the
3751 // boundary, use a different calculation of the middle vertex
3752 // here. this is of advantage if the boundary is strongly
3753 // curved (whereas the cell is not) and the cell has a high
3754 // aspect ratio.
3755 if (cell->user_flag_set())
3756 {
3757 // first reset the user_flag and then refine
3758 cell->clear_user_flag();
3759 triangulation.vertices[next_unused_vertex] =
3760 cell->center(true, true);
3761 }
3762 }
3763 else
3764 {
3765 // if this quad lives in a higher dimensional space
3766 // then we don't need to worry if it is at the
3767 // boundary of the manifold -- we always have to use
3768 // the boundary object anyway; so ignore whether the
3769 // user flag is set or not
3770 cell->clear_user_flag();
3771
3772 // determine middle vertex by transfinite interpolation to be
3773 // consistent with what happens to quads in a Triangulation<3,
3774 // 3> when they are refined
3775 triangulation.vertices[next_unused_vertex] =
3776 cell->center(true, true);
3777 }
3778 }
3779
3780
3781 // Now the lines:
3783 unsigned int lmin = 8;
3784 unsigned int lmax = 12;
3785 if (ref_case != RefinementCase<dim>::cut_xy)
3786 {
3787 lmin = 6;
3788 lmax = 7;
3789 }
3790
3791 for (unsigned int l = lmin; l < lmax; ++l)
3792 {
3793 while (next_unused_line->used() == true)
3794 ++next_unused_line;
3795 new_lines[l] = next_unused_line;
3796 ++next_unused_line;
3797
3798 Assert(
3799 new_lines[l]->used() == false,
3800 ExcMessage(
3801 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
3802 }
3803
3804 if (ref_case == RefinementCase<dim>::cut_xy)
3805 {
3806 // .-6-.-7-.
3807 // 1 9 3
3808 // .-10.11-.
3809 // 0 8 2
3810 // .-4-.-5-.
3811
3812 // lines 0-7 already exist, create only the four interior
3813 // lines 8-11
3814 unsigned int l = 0;
3815 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
3816 for (unsigned int c = 0; c < 2; ++c, ++l)
3817 new_lines[l] = cell->line(face_no)->child(c);
3818 Assert(l == 8, ExcInternalError());
3819
3820 new_lines[8]->set_bounding_object_indices(
3821 {new_vertices[6], new_vertices[8]});
3822 new_lines[9]->set_bounding_object_indices(
3823 {new_vertices[8], new_vertices[7]});
3824 new_lines[10]->set_bounding_object_indices(
3825 {new_vertices[4], new_vertices[8]});
3826 new_lines[11]->set_bounding_object_indices(
3827 {new_vertices[8], new_vertices[5]});
3828 }
3829 else if (ref_case == RefinementCase<dim>::cut_x)
3830 {
3831 // .-4-.-5-.
3832 // | | |
3833 // 0 6 1
3834 // | | |
3835 // .-2-.-3-.
3836 new_lines[0] = cell->line(0);
3837 new_lines[1] = cell->line(1);
3838 new_lines[2] = cell->line(2)->child(0);
3839 new_lines[3] = cell->line(2)->child(1);
3840 new_lines[4] = cell->line(3)->child(0);
3841 new_lines[5] = cell->line(3)->child(1);
3842 new_lines[6]->set_bounding_object_indices(
3843 {new_vertices[6], new_vertices[7]});
3844 }
3845 else
3846 {
3848 // .---5---.
3849 // 1 3
3850 // .---6---.
3851 // 0 2
3852 // .---4---.
3853 new_lines[0] = cell->line(0)->child(0);
3854 new_lines[1] = cell->line(0)->child(1);
3855 new_lines[2] = cell->line(1)->child(0);
3856 new_lines[3] = cell->line(1)->child(1);
3857 new_lines[4] = cell->line(2);
3858 new_lines[5] = cell->line(3);
3859 new_lines[6]->set_bounding_object_indices(
3860 {new_vertices[4], new_vertices[5]});
3861 }
3862
3863 for (unsigned int l = lmin; l < lmax; ++l)
3864 {
3865 new_lines[l]->set_used_flag();
3866 new_lines[l]->clear_user_flag();
3867 new_lines[l]->clear_user_data();
3868 new_lines[l]->clear_children();
3869 // interior line
3870 new_lines[l]->set_boundary_id_internal(
3872 new_lines[l]->set_manifold_id(cell->manifold_id());
3873 }
3874
3875 // Now add the four (two)
3876 // new cells!
3879 while (next_unused_cell->used() == true)
3880 ++next_unused_cell;
3881
3882 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
3883 for (unsigned int i = 0; i < n_children; ++i)
3884 {
3885 Assert(
3886 next_unused_cell->used() == false,
3887 ExcMessage(
3888 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
3889 subcells[i] = next_unused_cell;
3890 ++next_unused_cell;
3891 if (i % 2 == 1 && i < n_children - 1)
3892 while (next_unused_cell->used() == true)
3893 ++next_unused_cell;
3894 }
3895
3896 if (ref_case == RefinementCase<dim>::cut_xy)
3897 {
3898 // children:
3899 // .--.--.
3900 // |2 . 3|
3901 // .--.--.
3902 // |0 | 1|
3903 // .--.--.
3904 // lines:
3905 // .-6-.-7-.
3906 // 1 9 3
3907 // .-10.11-.
3908 // 0 8 2
3909 // .-4-.-5-.
3910 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3911 new_lines[8]->index(),
3912 new_lines[4]->index(),
3913 new_lines[10]->index()});
3914 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
3915 new_lines[2]->index(),
3916 new_lines[5]->index(),
3917 new_lines[11]->index()});
3918 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
3919 new_lines[9]->index(),
3920 new_lines[10]->index(),
3921 new_lines[6]->index()});
3922 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
3923 new_lines[3]->index(),
3924 new_lines[11]->index(),
3925 new_lines[7]->index()});
3926 }
3927 else if (ref_case == RefinementCase<dim>::cut_x)
3928 {
3929 // children:
3930 // .--.--.
3931 // | . |
3932 // .0 . 1.
3933 // | | |
3934 // .--.--.
3935 // lines:
3936 // .-4-.-5-.
3937 // | | |
3938 // 0 6 1
3939 // | | |
3940 // .-2-.-3-.
3941 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3942 new_lines[6]->index(),
3943 new_lines[2]->index(),
3944 new_lines[4]->index()});
3945 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
3946 new_lines[1]->index(),
3947 new_lines[3]->index(),
3948 new_lines[5]->index()});
3949 }
3950 else
3951 {
3953 // children:
3954 // .-----.
3955 // | 1 |
3956 // .-----.
3957 // | 0 |
3958 // .-----.
3959 // lines:
3960 // .---5---.
3961 // 1 3
3962 // .---6---.
3963 // 0 2
3964 // .---4---.
3965 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3966 new_lines[2]->index(),
3967 new_lines[4]->index(),
3968 new_lines[6]->index()});
3969 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
3970 new_lines[3]->index(),
3971 new_lines[6]->index(),
3972 new_lines[5]->index()});
3973 }
3974
3975 types::subdomain_id subdomainid = cell->subdomain_id();
3976
3977 for (unsigned int i = 0; i < n_children; ++i)
3978 {
3979 subcells[i]->set_used_flag();
3980 subcells[i]->clear_refine_flag();
3981 subcells[i]->clear_user_flag();
3982 subcells[i]->clear_user_data();
3983 subcells[i]->clear_children();
3984 // inherit material
3985 // properties
3986 subcells[i]->set_material_id(cell->material_id());
3987 subcells[i]->set_manifold_id(cell->manifold_id());
3988 subcells[i]->set_subdomain_id(subdomainid);
3989
3990 if (i % 2 == 0)
3991 subcells[i]->set_parent(cell->index());
3992 }
3993
3994
3995
3996 // set child index for
3997 // even children children
3998 // i=0,2 (0)
3999 for (unsigned int i = 0; i < n_children / 2; ++i)
4000 cell->set_children(2 * i, subcells[2 * i]->index());
4001 // set the refine case
4002 cell->set_refinement_case(ref_case);
4003
4004 // note that the
4005 // refinement flag was
4006 // already cleared at the
4007 // beginning of this function
4008
4009 if (dim < spacedim)
4010 for (unsigned int c = 0; c < n_children; ++c)
4011 cell->child(c)->set_direction_flag(cell->direction_flag());
4012 }
4013
4014
4015
4016 template <int dim, int spacedim>
4019 const bool check_for_distorted_cells)
4020 {
4021 AssertDimension(dim, 2);
4022
4023 // Check whether a new level is needed. We have to check for
4024 // this on the highest level only
4025 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4026 triangulation.levels.size() - 1))
4027 if (cell->refine_flag_set())
4028 {
4029 triangulation.levels.push_back(
4030 std::make_unique<
4032 break;
4033 }
4034
4036 triangulation.begin_line();
4037 line != triangulation.end_line();
4038 ++line)
4039 {
4040 line->clear_user_flag();
4041 line->clear_user_data();
4042 }
4043
4044 unsigned int n_single_lines = 0;
4045 unsigned int n_lines_in_pairs = 0;
4046 unsigned int needed_vertices = 0;
4047
4048 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4049 {
4050 // count number of flagged cells on this level and compute
4051 // how many new vertices and new lines will be needed
4052 unsigned int needed_cells = 0;
4053
4054 for (const auto &cell :
4055 triangulation.active_cell_iterators_on_level(level))
4056 if (cell->refine_flag_set())
4057 {
4058 if (cell->reference_cell() ==
4060 {
4061 needed_cells += 4;
4062 needed_vertices += 0;
4063 n_single_lines += 3;
4064 }
4065 else if (cell->reference_cell() ==
4067 {
4068 needed_cells += 4;
4069 needed_vertices += 1;
4070 n_single_lines += 4;
4071 }
4072 else
4073 {
4075 }
4076
4077 for (const auto line_no : cell->face_indices())
4078 {
4079 auto line = cell->line(line_no);
4080 if (line->has_children() == false)
4081 line->set_user_flag();
4082 }
4083 }
4084
4085
4086 const unsigned int used_cells =
4087 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4088 triangulation.levels[level + 1]->cells.used.end(),
4089 true);
4090
4091
4092 reserve_space(*triangulation.levels[level + 1],
4093 used_cells + needed_cells,
4094 2,
4095 spacedim);
4096
4097 reserve_space(triangulation.levels[level + 1]->cells,
4098 needed_cells,
4099 0);
4100 }
4101
4102 for (auto line = triangulation.begin_line();
4103 line != triangulation.end_line();
4104 ++line)
4105 if (line->user_flag_set())
4106 {
4107 Assert(line->has_children() == false, ExcInternalError());
4108 n_lines_in_pairs += 2;
4109 needed_vertices += 1;
4110 }
4111
4112 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4113
4114 needed_vertices += std::count(triangulation.vertices_used.begin(),
4115 triangulation.vertices_used.end(),
4116 true);
4117
4118 if (needed_vertices > triangulation.vertices.size())
4119 {
4120 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4121 triangulation.vertices_used.resize(needed_vertices, false);
4122 }
4123
4124 unsigned int next_unused_vertex = 0;
4125
4126 {
4128 line = triangulation.begin_active_line(),
4129 endl = triangulation.end_line();
4131 next_unused_line = triangulation.begin_raw_line();
4132
4133 for (; line != endl; ++line)
4134 if (line->user_flag_set())
4135 {
4136 // this line needs to be refined
4137
4138 // find the next unused vertex and set it
4139 // appropriately
4140 while (triangulation.vertices_used[next_unused_vertex] == true)
4141 ++next_unused_vertex;
4142 Assert(
4143 next_unused_vertex < triangulation.vertices.size(),
4144 ExcMessage(
4145 "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."));
4146 triangulation.vertices_used[next_unused_vertex] = true;
4147
4148 triangulation.vertices[next_unused_vertex] = line->center(true);
4149
4150 bool pair_found = false;
4151 (void)pair_found;
4152 for (; next_unused_line != endl; ++next_unused_line)
4153 if (!next_unused_line->used() &&
4154 !(++next_unused_line)->used())
4155 {
4156 --next_unused_line;
4157 pair_found = true;
4158 break;
4159 }
4160 Assert(pair_found, ExcInternalError());
4161
4162 line->set_children(0, next_unused_line->index());
4163
4165 children[2] = {next_unused_line, ++next_unused_line};
4166
4167 Assert(
4168 children[0]->used() == false,
4169 ExcMessage(
4170 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4171 Assert(
4172 children[1]->used() == false,
4173 ExcMessage(
4174 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4175
4176 children[0]->set_bounding_object_indices(
4177 {line->vertex_index(0), next_unused_vertex});
4178 children[1]->set_bounding_object_indices(
4179 {next_unused_vertex, line->vertex_index(1)});
4180
4181 children[0]->set_used_flag();
4182 children[1]->set_used_flag();
4183 children[0]->clear_children();
4184 children[1]->clear_children();
4185 children[0]->clear_user_data();
4186 children[1]->clear_user_data();
4187 children[0]->clear_user_flag();
4188 children[1]->clear_user_flag();
4189
4190
4191 children[0]->set_boundary_id_internal(line->boundary_id());
4192 children[1]->set_boundary_id_internal(line->boundary_id());
4193
4194 children[0]->set_manifold_id(line->manifold_id());
4195 children[1]->set_manifold_id(line->manifold_id());
4196
4197 line->clear_user_flag();
4198 }
4199 }
4200
4201 reserve_space(triangulation.faces->lines, 0, n_single_lines);
4202
4204 cells_with_distorted_children;
4205
4207 next_unused_line = triangulation.begin_raw_line();
4208
4209 const auto create_children = [](auto & triangulation,
4210 unsigned int &next_unused_vertex,
4211 auto & next_unused_line,
4212 auto & next_unused_cell,
4213 const auto & cell) {
4214 const auto ref_case = cell->refine_flag_set();
4215 cell->clear_refine_flag();
4216
4217 unsigned int n_new_vertices = 0;
4218
4219 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4220 n_new_vertices = 6;
4221 else if (cell->reference_cell() ==
4223 n_new_vertices = 9;
4224 else
4226
4227 std::vector<int> new_vertices(n_new_vertices);
4228 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
4229 ++vertex_no)
4230 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4231 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
4232 if (cell->line(line_no)->has_children())
4233 new_vertices[cell->n_vertices() + line_no] =
4234 cell->line(line_no)->child(0)->vertex_index(1);
4235
4236 if (cell->reference_cell() == ::ReferenceCells::Quadrilateral)
4237 {
4238 while (triangulation.vertices_used[next_unused_vertex] == true)
4239 ++next_unused_vertex;
4240 Assert(
4241 next_unused_vertex < triangulation.vertices.size(),
4242 ExcMessage(
4243 "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."));
4244 triangulation.vertices_used[next_unused_vertex] = true;
4245
4246 new_vertices[8] = next_unused_vertex;
4247
4248 if (dim == spacedim)
4249 {
4250 triangulation.vertices[next_unused_vertex] =
4251 cell->center(true);
4252
4253 if (cell->user_flag_set())
4254 {
4255 cell->clear_user_flag();
4256 triangulation.vertices[next_unused_vertex] =
4257 cell->center(true, true);
4258 }
4259 }
4260 else
4261 {
4262 cell->clear_user_flag();
4263
4264 triangulation.vertices[next_unused_vertex] =
4265 cell->center(true, true);
4266 }
4267 }
4268
4269 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
4270 12>
4271 new_lines;
4272 unsigned int lmin = 0;
4273 unsigned int lmax = 0;
4274
4275 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4276 {
4277 lmin = 6;
4278 lmax = 9;
4279 }
4280 else if (cell->reference_cell() ==
4282 {
4283 lmin = 8;
4284 lmax = 12;
4285 }
4286 else
4287 {
4289 }
4290
4291 for (unsigned int l = lmin; l < lmax; ++l)
4292 {
4293 while (next_unused_line->used() == true)
4294 ++next_unused_line;
4295 new_lines[l] = next_unused_line;
4296 ++next_unused_line;
4297
4298 Assert(
4299 new_lines[l]->used() == false,
4300 ExcMessage(
4301 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4302 }
4303
4304 if (true)
4305 {
4306 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4307 {
4308 // add lines in the right order [TODO: clean up]
4309 const auto ref = [&](const unsigned int face_no,
4310 const unsigned int vertex_no) {
4311 if (cell->line(face_no)->child(0)->vertex_index(0) ==
4312 static_cast<unsigned int>(new_vertices[vertex_no]) ||
4313 cell->line(face_no)->child(0)->vertex_index(1) ==
4314 static_cast<unsigned int>(new_vertices[vertex_no]))
4315 {
4316 new_lines[2 * face_no + 0] =
4317 cell->line(face_no)->child(0);
4318 new_lines[2 * face_no + 1] =
4319 cell->line(face_no)->child(1);
4320 }
4321 else
4322 {
4323 new_lines[2 * face_no + 0] =
4324 cell->line(face_no)->child(1);
4325 new_lines[2 * face_no + 1] =
4326 cell->line(face_no)->child(0);
4327 }
4328 };
4329
4330 ref(0, 0);
4331 ref(1, 1);
4332 ref(2, 2);
4333
4334 new_lines[6]->set_bounding_object_indices(
4335 {new_vertices[3], new_vertices[4]});
4336 new_lines[7]->set_bounding_object_indices(
4337 {new_vertices[4], new_vertices[5]});
4338 new_lines[8]->set_bounding_object_indices(
4339 {new_vertices[5], new_vertices[3]});
4340 }
4341 else if (cell->reference_cell() ==
4343 {
4344 unsigned int l = 0;
4345 for (const unsigned int face_no : cell->face_indices())
4346 for (unsigned int c = 0; c < 2; ++c, ++l)
4347 new_lines[l] = cell->line(face_no)->child(c);
4348
4349 new_lines[8]->set_bounding_object_indices(
4350 {new_vertices[6], new_vertices[8]});
4351 new_lines[9]->set_bounding_object_indices(
4352 {new_vertices[8], new_vertices[7]});
4353 new_lines[10]->set_bounding_object_indices(
4354 {new_vertices[4], new_vertices[8]});
4355 new_lines[11]->set_bounding_object_indices(
4356 {new_vertices[8], new_vertices[5]});
4357 }
4358 else
4359 {
4361 }
4362 }
4363
4364
4365 for (unsigned int l = lmin; l < lmax; ++l)
4366 {
4367 new_lines[l]->set_used_flag();
4368 new_lines[l]->clear_user_flag();
4369 new_lines[l]->clear_user_data();
4370 new_lines[l]->clear_children();
4371 // interior line
4372 new_lines[l]->set_boundary_id_internal(
4374 new_lines[l]->set_manifold_id(cell->manifold_id());
4375 }
4376
4379 while (next_unused_cell->used() == true)
4380 ++next_unused_cell;
4381
4382 unsigned int n_children = 0;
4383
4384 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4385 n_children = 4;
4386 else if (cell->reference_cell() ==
4388 n_children = 4;
4389 else
4391
4392 for (unsigned int i = 0; i < n_children; ++i)
4393 {
4394 Assert(
4395 next_unused_cell->used() == false,
4396 ExcMessage(
4397 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4398 subcells[i] = next_unused_cell;
4399 ++next_unused_cell;
4400 if (i % 2 == 1 && i < n_children - 1)
4401 while (next_unused_cell->used() == true)
4402 ++next_unused_cell;
4403 }
4404
4405 if ((dim == 2) &&
4406 (cell->reference_cell() == ::ReferenceCells::Triangle))
4407 {
4408 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4409 new_lines[8]->index(),
4410 new_lines[5]->index()});
4411 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4412 new_lines[2]->index(),
4413 new_lines[6]->index()});
4414 subcells[2]->set_bounding_object_indices({new_lines[7]->index(),
4415 new_lines[3]->index(),
4416 new_lines[4]->index()});
4417 subcells[3]->set_bounding_object_indices({new_lines[6]->index(),
4418 new_lines[7]->index(),
4419 new_lines[8]->index()});
4420
4421 // subcell 0
4422
4423 const auto ref = [&](const unsigned int line_no,
4424 const unsigned int vertex_no,
4425 const unsigned int subcell_no,
4426 const unsigned int subcell_line_no) {
4427 if (new_lines[line_no]->vertex_index(1) !=
4428 static_cast<unsigned int>(new_vertices[vertex_no]))
4429 triangulation.levels[subcells[subcell_no]->level()]
4430 ->face_orientations[subcells[subcell_no]->index() *
4432 subcell_line_no] = 0;
4433 };
4434
4435 ref(0, 3, 0, 0);
4436 ref(8, 5, 0, 1);
4437 ref(5, 0, 0, 2);
4438
4439 ref(1, 1, 1, 0);
4440 ref(2, 4, 1, 1);
4441 ref(6, 3, 1, 2);
4442
4443 ref(7, 4, 2, 0);
4444 ref(3, 2, 2, 1);
4445 ref(4, 5, 2, 2);
4446
4447 ref(6, 4, 3, 0);
4448 ref(7, 5, 3, 1);
4449 ref(8, 3, 3, 2);
4450
4451 // triangulation.levels[subcells[1]->level()]->face_orientations[subcells[1]->index()
4452 // * GeometryInfo<2>::faces_per_cell + 2] = 0;
4453 // triangulation.levels[subcells[2]->level()]->face_orientations[subcells[2]->index()
4454 // * GeometryInfo<2>::faces_per_cell + 0] = 0;
4455 }
4456 else if ((dim == 2) && (cell->reference_cell() ==
4458 {
4459 subcells[0]->set_bounding_object_indices(
4460 {new_lines[0]->index(),
4461 new_lines[8]->index(),
4462 new_lines[4]->index(),
4463 new_lines[10]->index()});
4464 subcells[1]->set_bounding_object_indices(
4465 {new_lines[8]->index(),
4466 new_lines[2]->index(),
4467 new_lines[5]->index(),
4468 new_lines[11]->index()});
4469 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4470 new_lines[9]->index(),
4471 new_lines[10]->index(),
4472 new_lines[6]->index()});
4473 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4474 new_lines[3]->index(),
4475 new_lines[11]->index(),
4476 new_lines[7]->index()});
4477 }
4478 else
4479 {
4481 }
4482
4483 types::subdomain_id subdomainid = cell->subdomain_id();
4484
4485 for (unsigned int i = 0; i < n_children; ++i)
4486 {
4487 subcells[i]->set_used_flag();
4488 subcells[i]->clear_refine_flag();
4489 subcells[i]->clear_user_flag();
4490 subcells[i]->clear_user_data();
4491 subcells[i]->clear_children();
4492 // inherit material
4493 // properties
4494 subcells[i]->set_material_id(cell->material_id());
4495 subcells[i]->set_manifold_id(cell->manifold_id());
4496 subcells[i]->set_subdomain_id(subdomainid);
4497
4498 // TODO: here we assume that all children have the same reference
4499 // cell type as the parent! This is justified for 2D.
4500 triangulation.levels[subcells[i]->level()]
4501 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
4502
4503 if (i % 2 == 0)
4504 subcells[i]->set_parent(cell->index());
4505 }
4506
4507 for (unsigned int i = 0; i < n_children / 2; ++i)
4508 cell->set_children(2 * i, subcells[2 * i]->index());
4509
4510 cell->set_refinement_case(ref_case);
4511
4512 if (dim < spacedim)
4513 for (unsigned int c = 0; c < n_children; ++c)
4514 cell->child(c)->set_direction_flag(cell->direction_flag());
4515 };
4516
4517 for (int level = 0;
4518 level < static_cast<int>(triangulation.levels.size()) - 1;
4519 ++level)
4520 {
4522 next_unused_cell = triangulation.begin_raw(level + 1);
4523
4524 for (const auto &cell :
4525 triangulation.active_cell_iterators_on_level(level))
4526 if (cell->refine_flag_set())
4527 {
4528 if (cell->at_boundary())
4529 cell->set_user_flag();
4530
4532 next_unused_vertex,
4533 next_unused_line,
4534 next_unused_cell,
4535 cell);
4536
4537 if (cell->reference_cell() ==
4539 check_for_distorted_cells &&
4540 has_distorted_children<dim, spacedim>(cell))
4541 cells_with_distorted_children.distorted_cells.push_back(
4542 cell);
4543
4544 triangulation.signals.post_refinement_on_cell(cell);
4545 }
4546 }
4547
4548 return cells_with_distorted_children;
4549 }
4550
4551
4552
4557 template <int spacedim>
4560 const bool /*check_for_distorted_cells*/)
4561 {
4562 const unsigned int dim = 1;
4563
4564 // Check whether a new level is needed. We have to check for
4565 // this on the highest level only
4566 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4567 triangulation.levels.size() - 1))
4568 if (cell->refine_flag_set())
4569 {
4570 triangulation.levels.push_back(
4571 std::make_unique<
4573 break;
4574 }
4575
4576
4577 // check how much space is needed on every level we need not
4578 // check the highest level since either - on the highest level
4579 // no cells are flagged for refinement - there are, but
4580 // prepare_refinement added another empty level
4581 unsigned int needed_vertices = 0;
4582 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4583 {
4584 // count number of flagged
4585 // cells on this level
4586 unsigned int flagged_cells = 0;
4587
4588 for (const auto &acell :
4589 triangulation.active_cell_iterators_on_level(level))
4590 if (acell->refine_flag_set())
4591 ++flagged_cells;
4592
4593 // count number of used cells
4594 // on the next higher level
4595 const unsigned int used_cells =
4596 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4597 triangulation.levels[level + 1]->cells.used.end(),
4598 true);
4599
4600 // reserve space for the used_cells cells already existing
4601 // on the next higher level as well as for the
4602 // 2*flagged_cells that will be created on that level
4603 reserve_space(*triangulation.levels[level + 1],
4605 flagged_cells,
4606 1,
4607 spacedim);
4608 // reserve space for 2*flagged_cells new lines on the next
4609 // higher level
4610 reserve_space(triangulation.levels[level + 1]->cells,
4612 flagged_cells,
4613 0);
4614
4615 needed_vertices += flagged_cells;
4616 }
4617
4618 // add to needed vertices how many
4619 // vertices are already in use
4620 needed_vertices += std::count(triangulation.vertices_used.begin(),
4621 triangulation.vertices_used.end(),
4622 true);
4623 // if we need more vertices: create them, if not: leave the
4624 // array as is, since shrinking is not really possible because
4625 // some of the vertices at the end may be in use
4626 if (needed_vertices > triangulation.vertices.size())
4627 {
4628 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4629 triangulation.vertices_used.resize(needed_vertices, false);
4630 }
4631
4632
4633 // Do REFINEMENT on every level; exclude highest level as
4634 // above
4635
4636 // index of next unused vertex
4637 unsigned int next_unused_vertex = 0;
4638
4639 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4640 {
4642 next_unused_cell = triangulation.begin_raw(level + 1);
4643
4644 for (const auto &cell :
4645 triangulation.active_cell_iterators_on_level(level))
4646 if (cell->refine_flag_set())
4647 {
4648 // clear refinement flag
4649 cell->clear_refine_flag();
4650
4651 // search for next unused
4652 // vertex
4653 while (triangulation.vertices_used[next_unused_vertex] ==
4654 true)
4655 ++next_unused_vertex;
4656 Assert(
4657 next_unused_vertex < triangulation.vertices.size(),
4658 ExcMessage(
4659 "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."));
4660
4661 // Now we always ask the cell itself where to put
4662 // the new point. The cell in turn will query the
4663 // manifold object internally.
4664 triangulation.vertices[next_unused_vertex] =
4665 cell->center(true);
4666
4667 triangulation.vertices_used[next_unused_vertex] = true;
4668
4669 // search for next two unused cell (++ takes care of
4670 // the end of the vector)
4672 first_child,
4673 second_child;
4674 while (next_unused_cell->used() == true)
4675 ++next_unused_cell;
4676 first_child = next_unused_cell;
4677 first_child->set_used_flag();
4678 first_child->clear_user_data();
4679 ++next_unused_cell;
4680 Assert(
4681 next_unused_cell->used() == false,
4682 ExcMessage(
4683 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
4684 second_child = next_unused_cell;
4685 second_child->set_used_flag();
4686 second_child->clear_user_data();
4687
4688 types::subdomain_id subdomainid = cell->subdomain_id();
4689
4690 // insert first child
4691 cell->set_children(0, first_child->index());
4692 first_child->clear_children();
4693 first_child->set_bounding_object_indices(
4694 {cell->vertex_index(0), next_unused_vertex});
4695 first_child->set_material_id(cell->material_id());
4696 first_child->set_manifold_id(cell->manifold_id());
4697 first_child->set_subdomain_id(subdomainid);
4698 first_child->set_direction_flag(cell->direction_flag());
4699
4700 first_child->set_parent(cell->index());
4701
4702 // Set manifold id of the right face. Only do this
4703 // on the first child.
4704 first_child->face(1)->set_manifold_id(cell->manifold_id());
4705
4706 // reset neighborship info (refer to
4707 // internal::TriangulationImplementation::TriaLevel<0> for
4708 // details)
4709 first_child->set_neighbor(1, second_child);
4710 if (cell->neighbor(0).state() != IteratorState::valid)
4711 first_child->set_neighbor(0, cell->neighbor(0));
4712 else if (cell->neighbor(0)->is_active())
4713 {
4714 // since the neighbors level is always <=level,
4715 // if the cell is active, then there are no
4716 // cells to the left which may want to know
4717 // about this new child cell.
4718 Assert(cell->neighbor(0)->level() <= cell->level(),
4720 first_child->set_neighbor(0, cell->neighbor(0));
4721 }
4722 else
4723 // left neighbor is refined
4724 {
4725 // set neighbor to cell on same level
4726 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
4727 first_child->set_neighbor(0,
4728 cell->neighbor(0)->child(nbnb));
4729
4730 // reset neighbor info of all right descendant
4731 // of the left neighbor of cell
4733 left_neighbor = cell->neighbor(0);
4734 while (left_neighbor->has_children())
4735 {
4736 left_neighbor = left_neighbor->child(nbnb);
4737 left_neighbor->set_neighbor(nbnb, first_child);
4738 }
4739 }
4740
4741 // insert second child
4742 second_child->clear_children();
4743 second_child->set_bounding_object_indices(
4744 {next_unused_vertex, cell->vertex_index(1)});
4745 second_child->set_neighbor(0, first_child);
4746 second_child->set_material_id(cell->material_id());
4747 second_child->set_manifold_id(cell->manifold_id());
4748 second_child->set_subdomain_id(subdomainid);
4749 second_child->set_direction_flag(cell->direction_flag());
4750
4751 if (cell->neighbor(1).state() != IteratorState::valid)
4752 second_child->set_neighbor(1, cell->neighbor(1));
4753 else if (cell->neighbor(1)->is_active())
4754 {
4755 Assert(cell->neighbor(1)->level() <= cell->level(),
4757 second_child->set_neighbor(1, cell->neighbor(1));
4758 }
4759 else
4760 // right neighbor is refined same as above
4761 {
4762 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
4763 second_child->set_neighbor(
4764 1, cell->neighbor(1)->child(nbnb));
4765
4767 right_neighbor = cell->neighbor(1);
4768 while (right_neighbor->has_children())
4769 {
4770 right_neighbor = right_neighbor->child(nbnb);
4771 right_neighbor->set_neighbor(nbnb, second_child);
4772 }
4773 }
4774 // inform all listeners that cell refinement is done
4775 triangulation.signals.post_refinement_on_cell(cell);
4776 }
4777 }
4778
4779 // in 1d, we can not have distorted children unless the parent
4780 // was already distorted (that is because we don't use
4781 // boundary information for 1d triangulations). so return an
4782 // empty list
4784 }
4785
4786
4791 template <int spacedim>
4794 const bool check_for_distorted_cells)
4795 {
4796 const unsigned int dim = 2;
4797
4798
4799 // First check whether we can get away with isotropic refinement, or
4800 // whether we need to run through the full anisotropic algorithm
4801 {
4802 bool do_isotropic_refinement = true;
4803 for (const auto &cell : triangulation.active_cell_iterators())
4804 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
4805 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
4806 {
4807 do_isotropic_refinement = false;
4808 break;
4809 }
4810
4811 if (do_isotropic_refinement)
4813 check_for_distorted_cells);
4814 }
4815
4816 // Check whether a new level is needed. We have to check for
4817 // this on the highest level only
4818 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4819 triangulation.levels.size() - 1))
4820 if (cell->refine_flag_set())
4821 {
4822 triangulation.levels.push_back(
4823 std::make_unique<
4825 break;
4826 }
4827
4828 // TODO[WB]: we clear user flags and pointers of lines; we're going
4829 // to use them to flag which lines need refinement
4831 triangulation.begin_line();
4832 line != triangulation.end_line();
4833 ++line)
4834 {
4835 line->clear_user_flag();
4836 line->clear_user_data();
4837 }
4838 // running over all cells and lines count the number
4839 // n_single_lines of lines which can be stored as single
4840 // lines, e.g. inner lines
4841 unsigned int n_single_lines = 0;
4842
4843 // New lines to be created: number lines which are stored in
4844 // pairs (the children of lines must be stored in pairs)
4845 unsigned int n_lines_in_pairs = 0;
4846
4847 // check how much space is needed on every level we need not
4848 // check the highest level since either - on the highest level
4849 // no cells are flagged for refinement - there are, but
4850 // prepare_refinement added another empty level
4851 unsigned int needed_vertices = 0;
4852 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4853 {
4854 // count number of flagged cells on this level and compute
4855 // how many new vertices and new lines will be needed
4856 unsigned int needed_cells = 0;
4857
4858 for (const auto &cell :
4859 triangulation.active_cell_iterators_on_level(level))
4860 if (cell->refine_flag_set())
4861 {
4862 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
4863 {
4864 needed_cells += 4;
4865
4866 // new vertex at center of cell is needed in any
4867 // case
4868 ++needed_vertices;
4869
4870 // the four inner lines can be stored as singles
4871 n_single_lines += 4;
4872 }
4873 else // cut_x || cut_y
4874 {
4875 // set the flag showing that anisotropic
4876 // refinement is used for at least one cell
4877 triangulation.anisotropic_refinement = true;
4878
4879 needed_cells += 2;
4880 // no vertex at center
4881
4882 // the inner line can be stored as single
4883 n_single_lines += 1;
4884 }
4885
4886 // mark all faces (lines) for refinement; checking
4887 // locally whether the neighbor would also like to
4888 // refine them is rather difficult for lines so we
4889 // only flag them and after visiting all cells, we
4890 // decide which lines need refinement;
4891 for (const unsigned int line_no :
4893 {
4895 cell->refine_flag_set(), line_no) ==
4897 {
4899 line = cell->line(line_no);
4900 if (line->has_children() == false)
4901 line->set_user_flag();
4902 }
4903 }
4904 }
4905
4906
4907 // count number of used cells on the next higher level
4908 const unsigned int used_cells =
4909 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4910 triangulation.levels[level + 1]->cells.used.end(),
4911 true);
4912
4913
4914 // reserve space for the used_cells cells already existing
4915 // on the next higher level as well as for the
4916 // needed_cells that will be created on that level
4917 reserve_space(*triangulation.levels[level + 1],
4918 used_cells + needed_cells,
4919 2,
4920 spacedim);
4921
4922 // reserve space for needed_cells new quads on the next
4923 // higher level
4924 reserve_space(triangulation.levels[level + 1]->cells,
4925 needed_cells,
4926 0);
4927 }
4928
4929 // now count the lines which were flagged for refinement
4931 triangulation.begin_line();
4932 line != triangulation.end_line();
4933 ++line)
4934 if (line->user_flag_set())
4935 {
4936 Assert(line->has_children() == false, ExcInternalError());
4937 n_lines_in_pairs += 2;
4938 needed_vertices += 1;
4939 }
4940 // reserve space for n_lines_in_pairs new lines. note, that
4941 // we can't reserve space for the single lines here as well,
4942 // as all the space reserved for lines in pairs would be
4943 // counted as unused and we would end up with too little space
4944 // to store all lines. memory reservation for n_single_lines
4945 // can only be done AFTER we refined the lines of the current
4946 // cells
4947 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4948
4949 // add to needed vertices how many vertices are already in use
4950 needed_vertices += std::count(triangulation.vertices_used.begin(),
4951 triangulation.vertices_used.end(),
4952 true);
4953 // if we need more vertices: create them, if not: leave the
4954 // array as is, since shrinking is not really possible because
4955 // some of the vertices at the end may be in use
4956 if (needed_vertices > triangulation.vertices.size())
4957 {
4958 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4959 triangulation.vertices_used.resize(needed_vertices, false);
4960 }
4961
4962
4963 // Do REFINEMENT on every level; exclude highest level as
4964 // above
4965
4966 // index of next unused vertex
4967 unsigned int next_unused_vertex = 0;
4968
4969 // first the refinement of lines. children are stored
4970 // pairwise
4971 {
4972 // only active objects can be refined further
4974 line = triangulation.begin_active_line(),
4975 endl = triangulation.end_line();
4977 next_unused_line = triangulation.begin_raw_line();
4978
4979 for (; line != endl; ++line)
4980 if (line->user_flag_set())
4981 {
4982 // this line needs to be refined
4983
4984 // find the next unused vertex and set it
4985 // appropriately
4986 while (triangulation.vertices_used[next_unused_vertex] == true)
4987 ++next_unused_vertex;
4988 Assert(
4989 next_unused_vertex < triangulation.vertices.size(),
4990 ExcMessage(
4991 "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."));
4992 triangulation.vertices_used[next_unused_vertex] = true;
4993
4994 triangulation.vertices[next_unused_vertex] = line->center(true);
4995
4996 // now that we created the right point, make up the
4997 // two child lines. To this end, find a pair of
4998 // unused lines
4999 bool pair_found = false;
5000 (void)pair_found;
5001 for (; next_unused_line != endl; ++next_unused_line)
5002 if (!next_unused_line->used() &&
5003 !(++next_unused_line)->used())
5004 {
5005 // go back to the first of the two unused
5006 // lines
5007 --next_unused_line;
5008 pair_found = true;
5009 break;
5010 }
5011 Assert(pair_found, ExcInternalError());
5012
5013 // there are now two consecutive unused lines, such
5014 // that the children of a line will be consecutive.
5015 // then set the child pointer of the present line
5016 line->set_children(0, next_unused_line->index());
5017
5018 // set the two new lines
5020 children[2] = {next_unused_line, ++next_unused_line};
5021 // some tests; if any of the iterators should be
5022 // invalid, then already dereferencing will fail
5023 Assert(
5024 children[0]->used() == false,
5025 ExcMessage(
5026 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5027 Assert(
5028 children[1]->used() == false,
5029 ExcMessage(
5030 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5031
5032 children[0]->set_bounding_object_indices(
5033 {line->vertex_index(0), next_unused_vertex});
5034 children[1]->set_bounding_object_indices(
5035 {next_unused_vertex, line->vertex_index(1)});
5036
5037 children[0]->set_used_flag();
5038 children[1]->set_used_flag();
5039 children[0]->clear_children();
5040 children[1]->clear_children();
5041 children[0]->clear_user_data();
5042 children[1]->clear_user_data();
5043 children[0]->clear_user_flag();
5044 children[1]->clear_user_flag();
5045
5046
5047 children[0]->set_boundary_id_internal(line->boundary_id());
5048 children[1]->set_boundary_id_internal(line->boundary_id());
5049
5050 children[0]->set_manifold_id(line->manifold_id());
5051 children[1]->set_manifold_id(line->manifold_id());
5052
5053 // finally clear flag indicating the need for
5054 // refinement
5055 line->clear_user_flag();
5056 }
5057 }
5058
5059
5060 // Now set up the new cells
5061
5062 // reserve space for inner lines (can be stored as single
5063 // lines)
5064 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5065
5067 cells_with_distorted_children;
5068
5069 // reset next_unused_line, as now also single empty places in
5070 // the vector can be used
5072 next_unused_line = triangulation.begin_raw_line();
5073
5074 for (int level = 0;
5075 level < static_cast<int>(triangulation.levels.size()) - 1;
5076 ++level)
5077 {
5079 next_unused_cell = triangulation.begin_raw(level + 1);
5080
5081 for (const auto &cell :
5082 triangulation.active_cell_iterators_on_level(level))
5083 if (cell->refine_flag_set())
5084 {
5085 // set the user flag to indicate, that at least one
5086 // line is at the boundary
5087
5088 // TODO[Tobias Leicht] find a better place to set
5089 // this flag, so that we do not need so much time to
5090 // check each cell here
5091 if (cell->at_boundary())
5092 cell->set_user_flag();
5093
5094 // actually set up the children and update neighbor
5095 // information
5097 next_unused_vertex,
5098 next_unused_line,
5099 next_unused_cell,
5100 cell);
5101
5102 if (check_for_distorted_cells &&
5103 has_distorted_children<dim, spacedim>(cell))
5104 cells_with_distorted_children.distorted_cells.push_back(
5105 cell);
5106 // inform all listeners that cell refinement is done
5107 triangulation.signals.post_refinement_on_cell(cell);
5108 }
5109 }
5110
5111 return cells_with_distorted_children;
5112 }
5113
5114
5119 template <int spacedim>
5122 const bool check_for_distorted_cells)
5123 {
5124 const unsigned int dim = 3;
5125
5126 // this function probably also works for spacedim>3 but it
5127 // isn't tested. it will probably be necessary to pull new
5128 // vertices onto the manifold just as we do for the other
5129 // functions above.
5130 Assert(spacedim == 3, ExcNotImplemented());
5131
5132 // Check whether a new level is needed. We have to check for
5133 // this on the highest level only
5134 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5135 triangulation.levels.size() - 1))
5136 if (cell->refine_flag_set())
5137 {
5138 triangulation.levels.push_back(
5139 std::make_unique<
5141 break;
5142 }
5143
5144
5145 // first clear user flags for quads and lines; we're going to
5146 // use them to flag which lines and quads need refinement
5147 triangulation.faces->quads.clear_user_data();
5148
5150 triangulation.begin_line();
5151 line != triangulation.end_line();
5152 ++line)
5153 line->clear_user_flag();
5155 triangulation.begin_quad();
5156 quad != triangulation.end_quad();
5157 ++quad)
5158 quad->clear_user_flag();
5159
5160 // create an array of face refine cases. User indices of faces
5161 // will be set to values corresponding with indices in this
5162 // array.
5163 const RefinementCase<dim - 1> face_refinement_cases[4] = {
5164 RefinementCase<dim - 1>::no_refinement,
5165 RefinementCase<dim - 1>::cut_x,
5166 RefinementCase<dim - 1>::cut_y,
5167 RefinementCase<dim - 1>::cut_xy};
5168
5169 // check how much space is needed on every level we need not
5170 // check the highest level since either
5171 // - on the highest level no cells are flagged for refinement
5172 // - there are, but prepare_refinement added another empty
5173 // level which then is the highest level
5174
5175 // variables to hold the number of newly to be created
5176 // vertices, lines and quads. as these are stored globally,
5177 // declare them outside the loop over al levels. we need lines
5178 // and quads in pairs for refinement of old ones and lines and
5179 // quads, that can be stored as single ones, as they are newly
5180 // created in the inside of an existing cell
5181 unsigned int needed_vertices = 0;
5182 unsigned int needed_lines_single = 0;
5183 unsigned int needed_quads_single = 0;
5184 unsigned int needed_lines_pair = 0;
5185 unsigned int needed_quads_pair = 0;
5186 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5187 {
5188 // count number of flagged cells on this level and compute
5189 // how many new vertices and new lines will be needed
5190 unsigned int new_cells = 0;
5191
5192 for (const auto &acell :
5193 triangulation.active_cell_iterators_on_level(level))
5194 if (acell->refine_flag_set())
5195 {
5196 RefinementCase<dim> ref_case = acell->refine_flag_set();
5197
5198 // now for interior vertices, lines and quads, which
5199 // are needed in any case
5200 if (ref_case == RefinementCase<dim>::cut_x ||
5201 ref_case == RefinementCase<dim>::cut_y ||
5202 ref_case == RefinementCase<dim>::cut_z)
5203 {
5204 ++needed_quads_single;
5205 new_cells += 2;
5206 triangulation.anisotropic_refinement = true;
5207 }
5208 else if (ref_case == RefinementCase<dim>::cut_xy ||
5209 ref_case == RefinementCase<dim>::cut_xz ||
5210 ref_case == RefinementCase<dim>::cut_yz)
5211 {
5212 ++needed_lines_single;
5213 needed_quads_single += 4;
5214 new_cells += 4;
5215 triangulation.anisotropic_refinement = true;
5216 }
5217 else if (ref_case == RefinementCase<dim>::cut_xyz)
5218 {
5219 ++needed_vertices;
5220 needed_lines_single += 6;
5221 needed_quads_single += 12;
5222 new_cells += 8;
5223 }
5224 else
5225 {
5226 // we should never get here
5227 Assert(false, ExcInternalError());
5228 }
5229
5230 // mark all faces for refinement; checking locally
5231 // if and how the neighbor would like to refine
5232 // these is difficult so we only flag them and after
5233 // visiting all cells, we decide which faces need
5234 // which refinement;
5235 for (const unsigned int face :
5237 {
5239 aface = acell->face(face);
5240 // get the RefineCase this faces has for the
5241 // given RefineCase of the cell
5242 RefinementCase<dim - 1> face_ref_case =
5244 ref_case,
5245 face,
5246 acell->face_orientation(face),
5247 acell->face_flip(face),
5248 acell->face_rotation(face));
5249 // only do something, if this face has to be
5250 // refined
5251 if (face_ref_case)
5252 {
5253 if (face_ref_case ==
5255 {
5256 if (aface->n_active_descendants() < 4)
5257 // we use user_flags to denote needed
5258 // isotropic refinement
5259 aface->set_user_flag();
5260 }
5261 else if (aface->refinement_case() != face_ref_case)
5262 // we use user_indices to denote needed
5263 // anisotropic refinement. note, that we
5264 // can have at most one anisotropic
5265 // refinement case for this face, as
5266 // otherwise prepare_refinement() would
5267 // have changed one of the cells to yield
5268 // isotropic refinement at this
5269 // face. therefore we set the user_index
5270 // uniquely
5271 {
5272 Assert(aface->refinement_case() ==
5274 dim - 1>::isotropic_refinement ||
5275 aface->refinement_case() ==
5278 aface->set_user_index(face_ref_case);
5279 }
5280 }
5281 } // for all faces
5282
5283 // flag all lines, that have to be refined
5284 for (unsigned int line = 0;
5285 line < GeometryInfo<dim>::lines_per_cell;
5286 ++line)
5288 line) &&
5289 !acell->line(line)->has_children())
5290 acell->line(line)->set_user_flag();
5291
5292 } // if refine_flag set and for all cells on this level
5293
5294
5295 // count number of used cells on the next higher level
5296 const unsigned int used_cells =
5297 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5298 triangulation.levels[level + 1]->cells.used.end(),
5299 true);
5300
5301
5302 // reserve space for the used_cells cells already existing
5303 // on the next higher level as well as for the
5304 // 8*flagged_cells that will be created on that level
5305 reserve_space(*triangulation.levels[level + 1],
5306 used_cells + new_cells,
5307 3,
5308 spacedim);
5309 // reserve space for 8*flagged_cells new hexes on the next
5310 // higher level
5311 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
5312 } // for all levels
5313 // now count the quads and lines which were flagged for
5314 // refinement
5316 triangulation.begin_quad();
5317 quad != triangulation.end_quad();
5318 ++quad)
5319 {
5320 if (quad->user_flag_set())
5321 {
5322 // isotropic refinement: 1 interior vertex, 4 quads
5323 // and 4 interior lines. we store the interior lines
5324 // in pairs in case the face is already or will be
5325 // refined anisotropically
5326 needed_quads_pair += 4;
5327 needed_lines_pair += 4;
5328 needed_vertices += 1;
5329 }
5330 if (quad->user_index())
5331 {
5332 // anisotropic refinement: 1 interior
5333 // line and two quads
5334 needed_quads_pair += 2;
5335 needed_lines_single += 1;
5336 // there is a kind of complicated situation here which
5337 // requires our attention. if the quad is refined
5338 // isotropcally, two of the interior lines will get a
5339 // new mother line - the interior line of our
5340 // anisotropically refined quad. if those two lines
5341 // are not consecutive, we cannot do so and have to
5342 // replace them by two lines that are consecutive. we
5343 // try to avoid that situation, but it may happen
5344 // nevertheless through repeated refinement and
5345 // coarsening. thus we have to check here, as we will
5346 // need some additional space to store those new lines
5347 // in case we need them...
5348 if (quad->has_children())
5349 {
5350 Assert(quad->refinement_case() ==
5353 if ((face_refinement_cases[quad->user_index()] ==
5355 (quad->child(0)->line_index(1) + 1 !=
5356 quad->child(2)->line_index(1))) ||
5357 (face_refinement_cases[quad->user_index()] ==
5359 (quad->child(0)->line_index(3) + 1 !=
5360 quad->child(1)->line_index(3))))
5361 needed_lines_pair += 2;
5362 }
5363 }
5364 }
5365
5367 triangulation.begin_line();
5368 line != triangulation.end_line();
5369 ++line)
5370 if (line->user_flag_set())
5371 {
5372 needed_lines_pair += 2;
5373 needed_vertices += 1;
5374 }
5375
5376 // reserve space for needed_lines new lines stored in pairs
5377 reserve_space(triangulation.faces->lines,
5378 needed_lines_pair,
5379 needed_lines_single);
5380 // reserve space for needed_quads new quads stored in pairs
5382 needed_quads_pair,
5383 needed_quads_single);
5384 reserve_space(triangulation.faces->quads,
5385 needed_quads_pair,
5386 needed_quads_single);
5387
5388
5389 // add to needed vertices how many vertices are already in use
5390 needed_vertices += std::count(triangulation.vertices_used.begin(),
5391 triangulation.vertices_used.end(),
5392 true);
5393 // if we need more vertices: create them, if not: leave the
5394 // array as is, since shrinking is not really possible because
5395 // some of the vertices at the end may be in use
5396 if (needed_vertices > triangulation.vertices.size())
5397 {
5398 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5399 triangulation.vertices_used.resize(needed_vertices, false);
5400 }
5401
5402
5404 // Before we start with the actual refinement, we do some
5405 // sanity checks if in debug mode. especially, we try to catch
5406 // the notorious problem with lines being twice refined,
5407 // i.e. there are cells adjacent at one line ("around the
5408 // edge", but not at a face), with two cells differing by more
5409 // than one refinement level
5410 //
5411 // this check is very simple to implement here, since we have
5412 // all lines flagged if they shall be refined
5413#ifdef DEBUG
5414 for (const auto &cell : triangulation.active_cell_iterators())
5415 if (!cell->refine_flag_set())
5416 for (unsigned int line = 0;
5417 line < GeometryInfo<dim>::lines_per_cell;
5418 ++line)
5419 if (cell->line(line)->has_children())
5420 for (unsigned int c = 0; c < 2; ++c)
5421 Assert(cell->line(line)->child(c)->user_flag_set() == false,
5423#endif
5424
5426 // Do refinement on every level
5427 //
5428 // To make life a bit easier, we first refine those lines and
5429 // quads that were flagged for refinement and then compose the
5430 // newly to be created cells.
5431 //
5432 // index of next unused vertex
5433 unsigned int next_unused_vertex = 0;
5434
5435 // first for lines
5436 {
5437 // only active objects can be refined further
5439 line = triangulation.begin_active_line(),
5440 endl = triangulation.end_line();
5442 next_unused_line = triangulation.begin_raw_line();
5443
5444 for (; line != endl; ++line)
5445 if (line->user_flag_set())
5446 {
5447 // this line needs to be refined
5448
5449 // find the next unused vertex and set it
5450 // appropriately
5451 while (triangulation.vertices_used[next_unused_vertex] == true)
5452 ++next_unused_vertex;
5453 Assert(
5454 next_unused_vertex < triangulation.vertices.size(),
5455 ExcMessage(
5456 "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."));
5457 triangulation.vertices_used[next_unused_vertex] = true;
5458
5459 triangulation.vertices[next_unused_vertex] = line->center(true);
5460
5461 // now that we created the right point, make up the
5462 // two child lines (++ takes care of the end of the
5463 // vector)
5464 next_unused_line =
5465 triangulation.faces->lines.template next_free_pair_object<1>(
5467 Assert(next_unused_line.state() == IteratorState::valid,
5469
5470 // now we found two consecutive unused lines, such
5471 // that the children of a line will be consecutive.
5472 // then set the child pointer of the present line
5473 line->set_children(0, next_unused_line->index());
5474
5475 // set the two new lines
5477 children[2] = {next_unused_line, ++next_unused_line};
5478
5479 // some tests; if any of the iterators should be
5480 // invalid, then already dereferencing will fail
5481 Assert(
5482 children[0]->used() == false,
5483 ExcMessage(
5484 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5485 Assert(
5486 children[1]->used() == false,
5487 ExcMessage(
5488 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5489
5490 children[0]->set_bounding_object_indices(
5491 {line->vertex_index(0), next_unused_vertex});
5492 children[1]->set_bounding_object_indices(
5493 {next_unused_vertex, line->vertex_index(1)});
5494
5495 children[0]->set_used_flag();
5496 children[1]->set_used_flag();
5497 children[0]->clear_children();
5498 children[1]->clear_children();
5499 children[0]->clear_user_data();
5500 children[1]->clear_user_data();
5501 children[0]->clear_user_flag();
5502 children[1]->clear_user_flag();
5503
5504 children[0]->set_boundary_id_internal(line->boundary_id());
5505 children[1]->set_boundary_id_internal(line->boundary_id());
5506
5507 children[0]->set_manifold_id(line->manifold_id());
5508 children[1]->set_manifold_id(line->manifold_id());
5509
5510 // finally clear flag
5511 // indicating the need
5512 // for refinement
5513 line->clear_user_flag();
5514 }
5515 }
5516
5517
5519 // now refine marked quads
5521
5522 // here we encounter several cases:
5523
5524 // a) the quad is unrefined and shall be refined isotropically
5525
5526 // b) the quad is unrefined and shall be refined
5527 // anisotropically
5528
5529 // c) the quad is unrefined and shall be refined both
5530 // anisotropically and isotropically (this is reduced to case
5531 // b) and then case b) for the children again)
5532
5533 // d) the quad is refined anisotropically and shall be refined
5534 // isotropically (this is reduced to case b) for the
5535 // anisotropic children)
5536
5537 // e) the quad is refined isotropically and shall be refined
5538 // anisotropically (this is transformed to case c), however we
5539 // might have to renumber/rename children...)
5540
5541 // we need a loop in cases c) and d), as the anisotropic
5542 // children migt have a lower index than the mother quad
5543 for (unsigned int loop = 0; loop < 2; ++loop)
5544 {
5545 // usually, only active objects can be refined
5546 // further. however, in cases d) and e) that is not true,
5547 // so we have to use 'normal' iterators here
5549 quad = triangulation.begin_quad(),
5550 endq = triangulation.end_quad();
5552 next_unused_line = triangulation.begin_raw_line();
5554 next_unused_quad = triangulation.begin_raw_quad();
5555
5556 for (; quad != endq; ++quad)
5557 {
5558 if (quad->user_index())
5559 {
5560 RefinementCase<dim - 1> aniso_quad_ref_case =
5561 face_refinement_cases[quad->user_index()];
5562 // there is one unlikely event here, where we
5563 // already have refind the face: if the face was
5564 // refined anisotropically and we want to refine
5565 // it isotropically, both children are flagged for
5566 // anisotropic refinement. however, if those
5567 // children were already flagged for anisotropic
5568 // refinement, they might already be processed and
5569 // refined.
5570 if (aniso_quad_ref_case == quad->refinement_case())
5571 continue;
5572
5573 Assert(quad->refinement_case() ==
5575 quad->refinement_case() ==
5578
5579 // this quad needs to be refined anisotropically
5580 Assert(quad->user_index() ==
5582 quad->user_index() ==
5585
5586 // make the new line interior to the quad
5588 new_line;
5589
5590 new_line =
5591 triangulation.faces->lines
5592 .template next_free_single_object<1>(triangulation);
5593 Assert(
5594 new_line->used() == false,
5595 ExcMessage(
5596 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5597
5598 // first collect the
5599 // indices of the vertices:
5600 // *--1--*
5601 // | | |
5602 // | | | cut_x
5603 // | | |
5604 // *--0--*
5605 //
5606 // *-----*
5607 // | |
5608 // 0-----1 cut_y
5609 // | |
5610 // *-----*
5611 unsigned int vertex_indices[2];
5612 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
5613 {
5614 vertex_indices[0] =
5615 quad->line(2)->child(0)->vertex_index(1);
5616 vertex_indices[1] =
5617 quad->line(3)->child(0)->vertex_index(1);
5618 }
5619 else
5620 {
5621 vertex_indices[0] =
5622 quad->line(0)->child(0)->vertex_index(1);
5623 vertex_indices[1] =
5624 quad->line(1)->child(0)->vertex_index(1);
5625 }
5626
5627 new_line->set_bounding_object_indices(
5629 new_line->set_used_flag();
5630 new_line->clear_user_flag();
5631 new_line->clear_user_data();
5632 new_line->clear_children();
5633 new_line->set_boundary_id_internal(quad->boundary_id());
5634 new_line->set_manifold_id(quad->manifold_id());
5635
5636 // child 0 and 1 of a line are switched if the
5637 // line orientation is false. set up a miniature
5638 // table, indicating which child to take for line
5639 // orientations false and true. first index: child
5640 // index in standard orientation, second index:
5641 // line orientation
5642 const unsigned int index[2][2] = {
5643 {1, 0}, // child 0, line_orientation=false and true
5644 {0, 1}}; // child 1, line_orientation=false and true
5645
5646 // find some space (consecutive) for the two newly
5647 // to be created quads.
5649 new_quads[2];
5650
5651 next_unused_quad =
5652 triangulation.faces->quads
5653 .template next_free_pair_object<2>(triangulation);
5654 new_quads[0] = next_unused_quad;
5655 Assert(
5656 new_quads[0]->used() == false,
5657 ExcMessage(
5658 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5659
5660 ++next_unused_quad;
5661 new_quads[1] = next_unused_quad;
5662 Assert(
5663 new_quads[1]->used() == false,
5664 ExcMessage(
5665 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
5666
5667
5668 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
5669 {
5670 new_quads[0]->set_bounding_object_indices(
5671 {static_cast<int>(quad->line_index(0)),
5672 new_line->index(),
5673 quad->line(2)
5674 ->child(index[0][quad->line_orientation(2)])
5675 ->index(),
5676 quad->line(3)
5677 ->child(index[0][quad->line_orientation(3)])
5678 ->index()});
5679 new_quads[1]->set_bounding_object_indices(
5680 {new_line->index(),
5681 static_cast<int>(quad->line_index(1)),
5682 quad->line(2)
5683 ->child(index[1][quad->line_orientation(2)])
5684 ->index(),
5685 quad->line(3)
5686 ->child(index[1][quad->line_orientation(3)])
5687 ->index()});
5688 }
5689 else
5690 {
5691 new_quads[0]->set_bounding_object_indices(
5692 {quad->line(0)
5693 ->child(index[0][quad->line_orientation(0)])
5694 ->index(),
5695 quad->line(1)
5696 ->child(index[0][quad->line_orientation(1)])
5697 ->index(),
5698 static_cast<int>(quad->line_index(2)),
5699 new_line->index()});
5700 new_quads[1]->set_bounding_object_indices(
5701 {quad->line(0)
5702 ->child(index[1][quad->line_orientation(0)])
5703 ->index(),
5704 quad->line(1)
5705 ->child(index[1][quad->line_orientation(1)])
5706 ->index(),
5707 new_line->index(),
5708 static_cast<int>(quad->line_index(3))});
5709 }
5710
5711 for (const auto &new_quad : new_quads)
5712 {
5713 new_quad->set_used_flag();
5714 new_quad->clear_user_flag();
5715 new_quad->clear_user_data();
5716 new_quad->clear_children();
5717 new_quad->set_boundary_id_internal(quad->boundary_id());
5718 new_quad->set_manifold_id(quad->manifold_id());
5719 // set all line orientations to true, change
5720 // this after the loop, as we have to consider
5721 // different lines for each child
5722 for (unsigned int j = 0;
5723 j < GeometryInfo<dim>::lines_per_face;
5724 ++j)
5725 new_quad->set_line_orientation(j, true);
5726 }
5727 // now set the line orientation of children of
5728 // outer lines correctly, the lines in the
5729 // interior of the refined quad are automatically
5730 // oriented conforming to the standard
5731 new_quads[0]->set_line_orientation(
5732 0, quad->line_orientation(0));
5733 new_quads[0]->set_line_orientation(
5734 2, quad->line_orientation(2));
5735 new_quads[1]->set_line_orientation(
5736 1, quad->line_orientation(1));
5737 new_quads[1]->set_line_orientation(
5738 3, quad->line_orientation(3));
5739 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
5740 {
5741 new_quads[0]->set_line_orientation(
5742 3, quad->line_orientation(3));
5743 new_quads[1]->set_line_orientation(
5744 2, quad->line_orientation(2));
5745 }
5746 else
5747 {
5748 new_quads[0]->set_line_orientation(
5749 1, quad->line_orientation(1));
5750 new_quads[1]->set_line_orientation(
5751 0, quad->line_orientation(0));
5752 }
5753
5754 // test, whether this face is refined
5755 // isotropically already. if so, set the correct
5756 // children pointers.
5757 if (quad->refinement_case() ==
5758 RefinementCase<dim - 1>::cut_xy)
5759 {
5760 // we will put a new refinemnt level of
5761 // anisotropic refinement between the
5762 // unrefined and isotropically refined quad
5763 // ending up with the same fine quads but
5764 // introducing anisotropically refined ones as
5765 // children of the unrefined quad and mother
5766 // cells of the original fine ones.
5767
5768 // this process includes the creation of a new
5769 // middle line which we will assign as the
5770 // mother line of two of the existing inner
5771 // lines. If those inner lines are not
5772 // consecutive in memory, we won't find them
5773 // later on, so we have to create new ones
5774 // instead and replace all occurrences of the
5775 // old ones with those new ones. As this is
5776 // kind of ugly, we hope we don't have to do
5777 // it often...
5779 old_child[2];
5780 if (aniso_quad_ref_case ==
5782 {
5783 old_child[0] = quad->child(0)->line(1);
5784 old_child[1] = quad->child(2)->line(1);
5785 }
5786 else
5787 {
5788 Assert(aniso_quad_ref_case ==
5791
5792 old_child[0] = quad->child(0)->line(3);
5793 old_child[1] = quad->child(1)->line(3);
5794 }
5795
5796 if (old_child[0]->index() + 1 != old_child[1]->index())
5797 {
5798 // this is exactly the ugly case we taked
5799 // about. so, no coimplaining, lets get
5800 // two new lines and copy all info
5801 typename Triangulation<dim,
5802 spacedim>::raw_line_iterator
5803 new_child[2];
5804
5805 new_child[0] = new_child[1] =
5806 triangulation.faces->lines
5807 .template next_free_pair_object<1>(
5809 ++new_child[1];
5810
5811 new_child[0]->set_used_flag();
5812 new_child[1]->set_used_flag();
5813
5814 const int old_index_0 = old_child[0]->index(),
5815 old_index_1 = old_child[1]->index(),
5816 new_index_0 = new_child[0]->index(),
5817 new_index_1 = new_child[1]->index();
5818
5819 // loop over all quads and replace the old
5820 // lines
5821 for (unsigned int q = 0;
5822 q < triangulation.faces->quads.n_objects();
5823 ++q)
5824 for (unsigned int l = 0;
5825 l < GeometryInfo<dim>::lines_per_face;
5826 ++l)
5827 {
5828 const int this_index =
5829 triangulation.faces->quads
5830 .get_bounding_object_indices(q)[l];
5831 if (this_index == old_index_0)
5832 triangulation.faces->quads
5833 .get_bounding_object_indices(q)[l] =
5834 new_index_0;
5835 else if (this_index == old_index_1)
5836 triangulation.faces->quads
5837 .get_bounding_object_indices(q)[l] =
5838 new_index_1;
5839 }
5840 // now we have to copy all information of
5841 // the two lines
5842 for (unsigned int i = 0; i < 2; ++i)
5843 {
5844 Assert(!old_child[i]->has_children(),
5846
5847 new_child[i]->set_bounding_object_indices(
5848 {old_child[i]->vertex_index(0),
5849 old_child[i]->vertex_index(1)});
5850 new_child[i]->set_boundary_id_internal(
5851 old_child[i]->boundary_id());
5852 new_child[i]->set_manifold_id(
5853 old_child[i]->manifold_id());
5854 new_child[i]->set_user_index(
5855 old_child[i]->user_index());
5856 if (old_child[i]->user_flag_set())
5857 new_child[i]->set_user_flag();
5858 else
5859 new_child[i]->clear_user_flag();
5860
5861 new_child[i]->clear_children();
5862
5863 old_child[i]->clear_user_flag();
5864 old_child[i]->clear_user_index();
5865 old_child[i]->clear_used_flag();
5866 }
5867 }
5868 // now that we cared about the lines, go on
5869 // with the quads themselves, where we might
5870 // encounter similar situations...
5871 if (aniso_quad_ref_case ==
5873 {
5874 new_line->set_children(
5875 0, quad->child(0)->line_index(1));
5876 Assert(new_line->child(1) ==
5877 quad->child(2)->line(1),
5879 // now evereything is quite
5880 // complicated. we have the children
5881 // numbered according to
5882 //
5883 // *---*---*
5884 // |n+2|n+3|
5885 // *---*---*
5886 // | n |n+1|
5887 // *---*---*
5888 //
5889 // from the original isotropic
5890 // refinement. we have to reorder them as
5891 //
5892 // *---*---*
5893 // |n+1|n+3|
5894 // *---*---*
5895 // | n |n+2|
5896 // *---*---*
5897 //
5898 // such that n and n+1 are consecutive
5899 // children of m and n+2 and n+3 are
5900 // consecutive children of m+1, where m
5901 // and m+1 are given as in
5902 //
5903 // *---*---*
5904 // | | |
5905 // | m |m+1|
5906 // | | |
5907 // *---*---*
5908 //
5909 // this is a bit ugly, of course: loop
5910 // over all cells on all levels and look
5911 // for faces n+1 (switch_1) and n+2
5912 // (switch_2).
5913 const typename Triangulation<dim, spacedim>::
5914 quad_iterator switch_1 = quad->child(1),
5915 switch_2 = quad->child(2);
5916 const int switch_1_index = switch_1->index();
5917 const int switch_2_index = switch_2->index();
5918 for (unsigned int l = 0;
5919 l < triangulation.levels.size();
5920 ++l)
5921 for (unsigned int h = 0;
5922 h <
5923 triangulation.levels[l]->cells.n_objects();
5924 ++h)
5925 for (const unsigned int q :
5927 {
5928 const int face_index =
5929 triangulation.levels[l]
5930 ->cells.get_bounding_object_indices(
5931 h)[q];
5932 if (face_index == switch_1_index)
5933 triangulation.levels[l]
5934 ->cells.get_bounding_object_indices(
5935 h)[q] = switch_2_index;
5936 else if (face_index == switch_2_index)
5937 triangulation.levels[l]
5938 ->cells.get_bounding_object_indices(
5939 h)[q] = switch_1_index;
5940 }
5941 // now we have to copy all information of
5942 // the two quads
5943 const unsigned int switch_1_lines[4] = {
5944 switch_1->line_index(0),
5945 switch_1->line_index(1),
5946 switch_1->line_index(2),
5947 switch_1->line_index(3)};
5948 const bool switch_1_line_orientations[4] = {
5949 switch_1->line_orientation(0),
5950 switch_1->line_orientation(1),
5951 switch_1->line_orientation(2),
5952 switch_1->line_orientation(3)};
5953 const types::boundary_id switch_1_boundary_id =
5954 switch_1->boundary_id();
5955 const unsigned int switch_1_user_index =
5956 switch_1->user_index();
5957 const bool switch_1_user_flag =
5958 switch_1->user_flag_set();
5959 const RefinementCase<dim - 1>
5960 switch_1_refinement_case =
5961 switch_1->refinement_case();
5962 const int switch_1_first_child_pair =
5963 (switch_1_refinement_case ?
5964 switch_1->child_index(0) :
5965 -1);
5966 const int switch_1_second_child_pair =
5967 (switch_1_refinement_case ==
5968 RefinementCase<dim - 1>::cut_xy ?
5969 switch_1->child_index(2) :
5970 -1);
5971
5972 switch_1->set_bounding_object_indices(
5973 {switch_2->line_index(0),
5974 switch_2->line_index(1),
5975 switch_2->line_index(2),
5976 switch_2->line_index(3)});
5977 switch_1->set_line_orientation(
5978 0, switch_2->line_orientation(0));
5979 switch_1->set_line_orientation(
5980 1, switch_2->line_orientation(1));
5981 switch_1->set_line_orientation(
5982 2, switch_2->line_orientation(2));
5983 switch_1->set_line_orientation(
5984 3, switch_2->line_orientation(3));
5985 switch_1->set_boundary_id_internal(
5986 switch_2->boundary_id());
5987 switch_1->set_manifold_id(switch_2->manifold_id());
5988 switch_1->set_user_index(switch_2->user_index());
5989 if (switch_2->user_flag_set())
5990 switch_1->set_user_flag();
5991 else
5992 switch_1->clear_user_flag();
5993 switch_1->clear_refinement_case();
5994 switch_1->set_refinement_case(
5995 switch_2->refinement_case());
5996 switch_1->clear_children();
5997 if (switch_2->refinement_case())
5998 switch_1->set_children(0,
5999 switch_2->child_index(0));
6000 if (switch_2->refinement_case() ==
6001 RefinementCase<dim - 1>::cut_xy)
6002 switch_1->set_children(2,
6003 switch_2->child_index(2));
6004
6005 switch_2->set_bounding_object_indices(
6006 {switch_1_lines[0],
6007 switch_1_lines[1],
6008 switch_1_lines[2],
6009 switch_1_lines[3]});
6010 switch_2->set_line_orientation(
6011 0, switch_1_line_orientations[0]);
6012 switch_2->set_line_orientation(
6013 1, switch_1_line_orientations[1]);
6014 switch_2->set_line_orientation(
6015 2, switch_1_line_orientations[2]);
6016 switch_2->set_line_orientation(
6017 3, switch_1_line_orientations[3]);
6018 switch_2->set_boundary_id_internal(
6019 switch_1_boundary_id);
6020 switch_2->set_manifold_id(switch_1->manifold_id());
6021 switch_2->set_user_index(switch_1_user_index);
6022 if (switch_1_user_flag)
6023 switch_2->set_user_flag();
6024 else
6025 switch_2->clear_user_flag();
6026 switch_2->clear_refinement_case();
6027 switch_2->set_refinement_case(
6028 switch_1_refinement_case);
6029 switch_2->clear_children();
6030 switch_2->set_children(0,
6031 switch_1_first_child_pair);
6032 switch_2->set_children(2,
6033 switch_1_second_child_pair);
6034
6035 new_quads[0]->set_refinement_case(
6037 new_quads[0]->set_children(0, quad->child_index(0));
6038 new_quads[1]->set_refinement_case(
6040 new_quads[1]->set_children(0, quad->child_index(2));
6041 }
6042 else
6043 {
6044 new_quads[0]->set_refinement_case(
6046 new_quads[0]->set_children(0, quad->child_index(0));
6047 new_quads[1]->set_refinement_case(
6049 new_quads[1]->set_children(0, quad->child_index(2));
6050 new_line->set_children(
6051 0, quad->child(0)->line_index(3));
6052 Assert(new_line->child(1) ==
6053 quad->child(1)->line(3),
6055 }
6056 quad->clear_children();
6057 }
6058
6059 // note these quads as children to the present one
6060 quad->set_children(0, new_quads[0]->index());
6061
6062 quad->set_refinement_case(aniso_quad_ref_case);
6063
6064 // finally clear flag indicating the need for
6065 // refinement
6066 quad->clear_user_data();
6067 } // if (anisotropic refinement)
6068
6069 if (quad->user_flag_set())
6070 {
6071 // this quad needs to be refined isotropically
6072
6073 // first of all: we only get here in the first run
6074 // of the loop
6075 Assert(loop == 0, ExcInternalError());
6076
6077 // find the next unused vertex. we'll need this in
6078 // any case
6079 while (triangulation.vertices_used[next_unused_vertex] ==
6080 true)
6081 ++next_unused_vertex;
6082 Assert(
6083 next_unused_vertex < triangulation.vertices.size(),
6084 ExcMessage(
6085 "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."));
6086
6087 // now: if the quad is refined anisotropically
6088 // already, set the anisotropic refinement flag
6089 // for both children. Additionally, we have to
6090 // refine the inner line, as it is an outer line
6091 // of the two (anisotropic) children
6092 const RefinementCase<dim - 1> quad_ref_case =
6093 quad->refinement_case();
6094
6095 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
6096 quad_ref_case == RefinementCase<dim - 1>::cut_y)
6097 {
6098 // set the 'opposite' refine case for children
6099 quad->child(0)->set_user_index(
6100 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
6101 quad->child(1)->set_user_index(
6102 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
6103 // refine the inner line
6105 middle_line;
6106 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
6107 middle_line = quad->child(0)->line(1);
6108 else
6109 middle_line = quad->child(0)->line(3);
6110
6111 // if the face has been refined
6112 // anisotropically in the last refinement step
6113 // it might be, that it is flagged already and
6114 // that the middle line is thus refined
6115 // already. if not create children.
6116 if (!middle_line->has_children())
6117 {
6118 // set the middle vertex
6119 // appropriately. double refinement of
6120 // quads can only happen in the interior
6121 // of the domain, so we need not care
6122 // about boundary quads here
6123 triangulation.vertices[next_unused_vertex] =
6124 middle_line->center(true);
6125 triangulation.vertices_used[next_unused_vertex] =
6126 true;
6127
6128 // now search a slot for the two
6129 // child lines
6130 next_unused_line =
6131 triangulation.faces->lines
6132 .template next_free_pair_object<1>(
6134
6135 // set the child pointer of the present
6136 // line
6137 middle_line->set_children(
6138 0, next_unused_line->index());
6139
6140 // set the two new lines
6141 const typename Triangulation<dim, spacedim>::
6142 raw_line_iterator children[2] = {
6143 next_unused_line, ++next_unused_line};
6144
6145 // some tests; if any of the iterators
6146 // should be invalid, then already
6147 // dereferencing will fail
6148 Assert(
6149 children[0]->used() == false,
6150 ExcMessage(
6151 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6152 Assert(
6153 children[1]->used() == false,
6154 ExcMessage(
6155 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6156
6157 children[0]->set_bounding_object_indices(
6158 {middle_line->vertex_index(0),
6159 next_unused_vertex});
6160 children[1]->set_bounding_object_indices(
6161 {next_unused_vertex,
6162 middle_line->vertex_index(1)});
6163
6164 children[0]->set_used_flag();
6165 children[1]->set_used_flag();
6166 children[0]->clear_children();
6167 children[1]->clear_children();
6168 children[0]->clear_user_data();
6169 children[1]->clear_user_data();
6170 children[0]->clear_user_flag();
6171 children[1]->clear_user_flag();
6172
6173 children[0]->set_boundary_id_internal(
6174 middle_line->boundary_id());
6175 children[1]->set_boundary_id_internal(
6176 middle_line->boundary_id());
6177
6178 children[0]->set_manifold_id(
6179 middle_line->manifold_id());
6180 children[1]->set_manifold_id(
6181 middle_line->manifold_id());
6182 }
6183 // now remove the flag from the quad and go to
6184 // the next quad, the actual refinement of the
6185 // quad takes place later on in this pass of
6186 // the loop or in the next one
6187 quad->clear_user_flag();
6188 continue;
6189 } // if (several refinement cases)
6190
6191 // if we got here, we have an unrefined quad and
6192 // have to do the usual work like in an purely
6193 // isotropic refinement
6194 Assert(quad_ref_case ==
6197
6198 // set the middle vertex appropriately: it might be that
6199 // the quad itself is not at the boundary, but that one of
6200 // its lines actually is. in this case, the newly created
6201 // vertices at the centers of the lines are not
6202 // necessarily the mean values of the adjacent vertices,
6203 // so do not compute the new vertex as the mean value of
6204 // the 4 vertices of the face, but rather as a weighted
6205 // mean value of the 8 vertices which we already have (the
6206 // four old ones, and the four ones inserted as middle
6207 // points for the four lines). summing up some more points
6208 // is generally cheaper than first asking whether one of
6209 // the lines is at the boundary
6210 //
6211 // note that the exact weights are chosen such as to
6212 // minimize the distortion of the four new quads from the
6213 // optimal shape. their description uses the formulas
6214 // underlying the TransfiniteInterpolationManifold
6215 // implementation
6216 triangulation.vertices[next_unused_vertex] =
6217 quad->center(true, true);
6218 triangulation.vertices_used[next_unused_vertex] = true;
6219
6220 // now that we created the right point, make up
6221 // the four lines interior to the quad (++ takes
6222 // care of the end of the vector)
6224 new_lines[4];
6225
6226 for (unsigned int i = 0; i < 4; ++i)
6227 {
6228 if (i % 2 == 0)
6229 // search a free pair of lines for 0. and
6230 // 2. line, so that two of them end up
6231 // together, which is necessary if later on
6232 // we want to refine the quad
6233 // anisotropically and the two lines end up
6234 // as children of new line
6235 next_unused_line =
6236 triangulation.faces->lines
6237 .template next_free_pair_object<1>(triangulation);
6238
6239 new_lines[i] = next_unused_line;
6240 ++next_unused_line;
6241
6242 Assert(
6243 new_lines[i]->used() == false,
6244 ExcMessage(
6245 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6246 }
6247
6248 // set the data of the four lines. first collect
6249 // the indices of the five vertices:
6250 //
6251 // *--3--*
6252 // | | |
6253 // 0--4--1
6254 // | | |
6255 // *--2--*
6256 //
6257 // the lines are numbered as follows:
6258 //
6259 // *--*--*
6260 // | 1 |
6261 // *2-*-3*
6262 // | 0 |
6263 // *--*--*
6264
6265 const unsigned int vertex_indices[5] = {
6266 quad->line(0)->child(0)->vertex_index(1),
6267 quad->line(1)->child(0)->vertex_index(1),
6268 quad->line(2)->child(0)->vertex_index(1),
6269 quad->line(3)->child(0)->vertex_index(1),
6270 next_unused_vertex};
6271
6272 new_lines[0]->set_bounding_object_indices(
6274 new_lines[1]->set_bounding_object_indices(
6276 new_lines[2]->set_bounding_object_indices(
6278 new_lines[3]->set_bounding_object_indices(
6280
6281 for (const auto &new_line : new_lines)
6282 {
6283 new_line->set_used_flag();
6284 new_line->clear_user_flag();
6285 new_line->clear_user_data();
6286 new_line->clear_children();
6287 new_line->set_boundary_id_internal(quad->boundary_id());
6288 new_line->set_manifold_id(quad->manifold_id());
6289 }
6290
6291 // now for the quads. again, first collect some
6292 // data about the indices of the lines, with the
6293 // following numbering:
6294 //
6295 // .-6-.-7-.
6296 // 1 9 3
6297 // .-10.11-.
6298 // 0 8 2
6299 // .-4-.-5-.
6300
6301 // child 0 and 1 of a line are switched if the
6302 // line orientation is false. set up a miniature
6303 // table, indicating which child to take for line
6304 // orientations false and true. first index: child
6305 // index in standard orientation, second index:
6306 // line orientation
6307 const unsigned int index[2][2] = {
6308 {1, 0}, // child 0, line_orientation=false and true
6309 {0, 1}}; // child 1, line_orientation=false and true
6310
6311 const int line_indices[12] = {
6312 quad->line(0)
6313 ->child(index[0][quad->line_orientation(0)])
6314 ->index(),
6315 quad->line(0)
6316 ->child(index[1][quad->line_orientation(0)])
6317 ->index(),
6318 quad->line(1)
6319 ->child(index[0][quad->line_orientation(1)])
6320 ->index(),
6321 quad->line(1)
6322 ->child(index[1][quad->line_orientation(1)])
6323 ->index(),
6324 quad->line(2)
6325 ->child(index[0][quad->line_orientation(2)])
6326 ->index(),
6327 quad->line(2)
6328 ->child(index[1][quad->line_orientation(2)])
6329 ->index(),
6330 quad->line(3)
6331 ->child(index[0][quad->line_orientation(3)])
6332 ->index(),
6333 quad->line(3)
6334 ->child(index[1][quad->line_orientation(3)])
6335 ->index(),
6336 new_lines[0]->index(),
6337 new_lines[1]->index(),
6338 new_lines[2]->index(),
6339 new_lines[3]->index()};
6340
6341 // find some space (consecutive)
6342 // for the first two newly to be
6343 // created quads.
6345 new_quads[4];
6346
6347 next_unused_quad =
6348 triangulation.faces->quads
6349 .template next_free_pair_object<2>(triangulation);
6350
6351 new_quads[0] = next_unused_quad;
6352 Assert(
6353 new_quads[0]->used() == false,
6354 ExcMessage(
6355 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6356
6357 ++next_unused_quad;
6358 new_quads[1] = next_unused_quad;
6359 Assert(
6360 new_quads[1]->used() == false,
6361 ExcMessage(
6362 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6363
6364 next_unused_quad =
6365 triangulation.faces->quads
6366 .template next_free_pair_object<2>(triangulation);
6367 new_quads[2] = next_unused_quad;
6368 Assert(
6369 new_quads[2]->used() == false,
6370 ExcMessage(
6371 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6372
6373 ++next_unused_quad;
6374 new_quads[3] = next_unused_quad;
6375 Assert(
6376 new_quads[3]->used() == false,
6377 ExcMessage(
6378 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6379
6380 // note these quads as children to the present one
6381 quad->set_children(0, new_quads[0]->index());
6382 quad->set_children(2, new_quads[2]->index());
6383 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6384
6385 new_quads[0]->set_bounding_object_indices(
6386 {line_indices[0],
6387 line_indices[8],
6388 line_indices[4],
6389 line_indices[10]});
6390 new_quads[1]->set_bounding_object_indices(
6391 {line_indices[8],
6392 line_indices[2],
6393 line_indices[5],
6394 line_indices[11]});
6395 new_quads[2]->set_bounding_object_indices(
6396 {line_indices[1],
6397 line_indices[9],
6398 line_indices[10],
6399 line_indices[6]});
6400 new_quads[3]->set_bounding_object_indices(
6401 {line_indices[9],
6402 line_indices[3],
6403 line_indices[11],
6404 line_indices[7]});
6405 for (const auto &new_quad : new_quads)
6406 {
6407 new_quad->set_used_flag();
6408 new_quad->clear_user_flag();
6409 new_quad->clear_user_data();
6410 new_quad->clear_children();
6411 new_quad->set_boundary_id_internal(quad->boundary_id());
6412 new_quad->set_manifold_id(quad->manifold_id());
6413 // set all line orientations to true, change
6414 // this after the loop, as we have to consider
6415 // different lines for each child
6416 for (unsigned int j = 0;
6417 j < GeometryInfo<dim>::lines_per_face;
6418 ++j)
6419 new_quad->set_line_orientation(j, true);
6420 }
6421 // now set the line orientation of children of
6422 // outer lines correctly, the lines in the
6423 // interior of the refined quad are automatically
6424 // oriented conforming to the standard
6425 new_quads[0]->set_line_orientation(
6426 0, quad->line_orientation(0));
6427 new_quads[0]->set_line_orientation(
6428 2, quad->line_orientation(2));
6429 new_quads[1]->set_line_orientation(
6430 1, quad->line_orientation(1));
6431 new_quads[1]->set_line_orientation(
6432 2, quad->line_orientation(2));
6433 new_quads[2]->set_line_orientation(
6434 0, quad->line_orientation(0));
6435 new_quads[2]->set_line_orientation(
6436 3, quad->line_orientation(3));
6437 new_quads[3]->set_line_orientation(
6438 1, quad->line_orientation(1));
6439 new_quads[3]->set_line_orientation(
6440 3, quad->line_orientation(3));
6441
6442 // finally clear flag indicating the need for
6443 // refinement
6444 quad->clear_user_flag();
6445 } // if (isotropic refinement)
6446 } // for all quads
6447 } // looped two times over all quads, all quads refined now
6448
6450 // Now, finally, set up the new
6451 // cells
6453
6455 cells_with_distorted_children;
6456
6457 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6458 ++level)
6459 {
6460 // only active objects can be refined further; remember
6461 // that we won't operate on the finest level, so
6462 // triangulation.begin_*(level+1) is allowed
6464 hex = triangulation.begin_active_hex(level),
6465 endh = triangulation.begin_active_hex(level + 1);
6467 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6468
6469 for (; hex != endh; ++hex)
6470 if (hex->refine_flag_set())
6471 {
6472 // this hex needs to be refined
6473
6474 // clear flag indicating the need for refinement. do
6475 // it here already, since we can't do it anymore
6476 // once the cell has children
6477 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6478 hex->clear_refine_flag();
6479 hex->set_refinement_case(ref_case);
6480
6481 // depending on the refine case we might have to
6482 // create additional vertices, lines and quads
6483 // interior of the hex before the actual children
6484 // can be set up.
6485
6486 // in a first step: reserve the needed space for
6487 // lines, quads and hexes and initialize them
6488 // correctly
6489
6490 unsigned int n_new_lines = 0;
6491 unsigned int n_new_quads = 0;
6492 unsigned int n_new_hexes = 0;
6493 switch (ref_case)
6494 {
6498 n_new_lines = 0;
6499 n_new_quads = 1;
6500 n_new_hexes = 2;
6501 break;
6505 n_new_lines = 1;
6506 n_new_quads = 4;
6507 n_new_hexes = 4;
6508 break;
6510 n_new_lines = 6;
6511 n_new_quads = 12;
6512 n_new_hexes = 8;
6513 break;
6514 default:
6515 Assert(false, ExcInternalError());
6516 break;
6517 }
6518
6519 // find some space for the newly to be created
6520 // interior lines and initialize them.
6521 std::vector<
6523 new_lines(n_new_lines);
6524 for (unsigned int i = 0; i < n_new_lines; ++i)
6525 {
6526 new_lines[i] =
6527 triangulation.faces->lines
6528 .template next_free_single_object<1>(triangulation);
6529
6530 Assert(
6531 new_lines[i]->used() == false,
6532 ExcMessage(
6533 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6534 new_lines[i]->set_used_flag();
6535 new_lines[i]->clear_user_flag();
6536 new_lines[i]->clear_user_data();
6537 new_lines[i]->clear_children();
6538 // interior line
6539 new_lines[i]->set_boundary_id_internal(
6541 // they inherit geometry description of the hex they
6542 // belong to
6543 new_lines[i]->set_manifold_id(hex->manifold_id());
6544 }
6545
6546 // find some space for the newly to be created
6547 // interior quads and initialize them.
6548 std::vector<
6550 new_quads(n_new_quads);
6551 for (unsigned int i = 0; i < n_new_quads; ++i)
6552 {
6553 new_quads[i] =
6554 triangulation.faces->quads
6555 .template next_free_single_object<2>(triangulation);
6556
6557 Assert(
6558 new_quads[i]->used() == false,
6559 ExcMessage(
6560 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6561 new_quads[i]->set_used_flag();
6562 new_quads[i]->clear_user_flag();
6563 new_quads[i]->clear_user_data();
6564 new_quads[i]->clear_children();
6565 // interior quad
6566 new_quads[i]->set_boundary_id_internal(
6568 // they inherit geometry description of the hex they
6569 // belong to
6570 new_quads[i]->set_manifold_id(hex->manifold_id());
6571 // set all line orientation flags to true by
6572 // default, change this afterwards, if necessary
6573 for (unsigned int j = 0;
6574 j < GeometryInfo<dim>::lines_per_face;
6575 ++j)
6576 new_quads[i]->set_line_orientation(j, true);
6577 }
6578
6579 types::subdomain_id subdomainid = hex->subdomain_id();
6580
6581 // find some space for the newly to be created hexes
6582 // and initialize them.
6583 std::vector<
6585 new_hexes(n_new_hexes);
6586 for (unsigned int i = 0; i < n_new_hexes; ++i)
6587 {
6588 if (i % 2 == 0)
6589 next_unused_hex =
6590 triangulation.levels[level + 1]->cells.next_free_hex(
6591 triangulation, level + 1);
6592 else
6593 ++next_unused_hex;
6594
6595 new_hexes[i] = next_unused_hex;
6596
6597 Assert(
6598 new_hexes[i]->used() == false,
6599 ExcMessage(
6600 "Internal error: We want to use a cell during refinement that should be unused, but turns out not to be."));
6601 new_hexes[i]->set_used_flag();
6602 new_hexes[i]->clear_user_flag();
6603 new_hexes[i]->clear_user_data();
6604 new_hexes[i]->clear_children();
6605 // inherit material
6606 // properties
6607 new_hexes[i]->set_material_id(hex->material_id());
6608 new_hexes[i]->set_manifold_id(hex->manifold_id());
6609 new_hexes[i]->set_subdomain_id(subdomainid);
6610
6611 if (i % 2)
6612 new_hexes[i]->set_parent(hex->index());
6613 // set the face_orientation flag to true for all
6614 // faces initially, as this is the default value
6615 // which is true for all faces interior to the
6616 // hex. later on go the other way round and
6617 // reset faces that are at the boundary of the
6618 // mother cube
6619 //
6620 // the same is true for the face_flip and
6621 // face_rotation flags. however, the latter two
6622 // are set to false by default as this is the
6623 // standard value
6624 for (const unsigned int f :
6626 {
6627 new_hexes[i]->set_face_orientation(f, true);
6628 new_hexes[i]->set_face_flip(f, false);
6629 new_hexes[i]->set_face_rotation(f, false);
6630 }
6631 }
6632 // note these hexes as children to the present cell
6633 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6634 hex->set_children(2 * i, new_hexes[2 * i]->index());
6635
6636 // we have to take into account whether the
6637 // different faces are oriented correctly or in the
6638 // opposite direction, so store that up front
6639
6640 // face_orientation
6641 const bool f_or[6] = {hex->face_orientation(0),
6642 hex->face_orientation(1),
6643 hex->face_orientation(2),
6644 hex->face_orientation(3),
6645 hex->face_orientation(4),
6646 hex->face_orientation(5)};
6647
6648 // face_flip
6649 const bool f_fl[6] = {hex->face_flip(0),
6650 hex->face_flip(1),
6651 hex->face_flip(2),
6652 hex->face_flip(3),
6653 hex->face_flip(4),
6654 hex->face_flip(5)};
6655
6656 // face_rotation
6657 const bool f_ro[6] = {hex->face_rotation(0),
6658 hex->face_rotation(1),
6659 hex->face_rotation(2),
6660 hex->face_rotation(3),
6661 hex->face_rotation(4),
6662 hex->face_rotation(5)};
6663
6664 // little helper table, indicating, whether the
6665 // child with index 0 or with index 1 can be found
6666 // at the standard origin of an anisotropically
6667 // refined quads in real orientation index 1:
6668 // (RefineCase - 1) index 2: face_flip
6669
6670 // index 3: face rotation
6671 // note: face orientation has no influence
6672 const unsigned int child_at_origin[2][2][2] = {
6673 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
6674 // face_rotation=false and true
6675 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
6676 // face_rotation=false and true
6677 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
6678 // face_rotation=false and true
6679 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
6680 // face_rotation=false and true
6681
6683 //
6684 // in the following we will do the same thing for
6685 // each refinement case: create a new vertex (if
6686 // needed), create new interior lines (if needed),
6687 // create new interior quads and afterwards build
6688 // the children hexes out of these and the existing
6689 // subfaces of the outer quads (which have been
6690 // created above). However, even if the steps are
6691 // quite similar, the actual work strongly depends
6692 // on the actual refinement case. therefore, we use
6693 // separate blocks of code for each of these cases,
6694 // which hopefully increases the readability to some
6695 // extend.
6696
6697 switch (ref_case)
6698 {
6700 {
6702 //
6703 // RefinementCase<dim>::cut_x
6704 //
6705 // the refined cube will look
6706 // like this:
6707 //
6708 // *----*----*
6709 // / / /|
6710 // / / / |
6711 // / / / |
6712 // *----*----* |
6713 // | | | |
6714 // | | | *
6715 // | | | /
6716 // | | | /
6717 // | | |/
6718 // *----*----*
6719 //
6720 // again, first collect some data about the
6721 // indices of the lines, with the following
6722 // numbering:
6723
6724 // face 2: front plane
6725 // (note: x,y exchanged)
6726 // *---*---*
6727 // | | |
6728 // | 0 |
6729 // | | |
6730 // *---*---*
6731 // m0
6732 // face 3: back plane
6733 // (note: x,y exchanged)
6734 // m1
6735 // *---*---*
6736 // | | |
6737 // | 1 |
6738 // | | |
6739 // *---*---*
6740 // face 4: bottom plane
6741 // *---*---*
6742 // / / /
6743 // / 2 /
6744 // / / /
6745 // *---*---*
6746 // m0
6747 // face 5: top plane
6748 // m1
6749 // *---*---*
6750 // / / /
6751 // / 3 /
6752 // / / /
6753 // *---*---*
6754
6755 // set up a list of line iterators first. from
6756 // this, construct lists of line_indices and
6757 // line orientations later on
6758 const typename Triangulation<dim, spacedim>::
6759 raw_line_iterator lines[4] = {
6760 hex->face(2)->child(0)->line(
6761 (hex->face(2)->refinement_case() ==
6763 1 :
6764 3), // 0
6765 hex->face(3)->child(0)->line(
6766 (hex->face(3)->refinement_case() ==
6768 1 :
6769 3), // 1
6770 hex->face(4)->child(0)->line(
6771 (hex->face(4)->refinement_case() ==
6773 1 :
6774 3), // 2
6775 hex->face(5)->child(0)->line(
6776 (hex->face(5)->refinement_case() ==
6778 1 :
6779 3) // 3
6780 };
6781
6782 unsigned int line_indices[4];
6783 for (unsigned int i = 0; i < 4; ++i)
6784 line_indices[i] = lines[i]->index();
6785
6786 // the orientation of lines for the inner quads
6787 // is quite tricky. as these lines are newly
6788 // created ones and thus have no parents, they
6789 // cannot inherit this property. set up an array
6790 // and fill it with the respective values
6791 bool line_orientation[4];
6792
6793 // the middle vertex marked as m0 above is the
6794 // start vertex for lines 0 and 2 in standard
6795 // orientation, whereas m1 is the end vertex of
6796 // lines 1 and 3 in standard orientation
6797 const unsigned int middle_vertices[2] = {
6798 hex->line(2)->child(0)->vertex_index(1),
6799 hex->line(7)->child(0)->vertex_index(1)};
6800
6801 for (unsigned int i = 0; i < 4; ++i)
6802 if (lines[i]->vertex_index(i % 2) ==
6803 middle_vertices[i % 2])
6804 line_orientation[i] = true;
6805 else
6806 {
6807 // it must be the other
6808 // way round then
6809 Assert(lines[i]->vertex_index((i + 1) % 2) ==
6810 middle_vertices[i % 2],
6812 line_orientation[i] = false;
6813 }
6814
6815 // set up the new quad, line numbering is as
6816 // indicated above
6817 new_quads[0]->set_bounding_object_indices(
6818 {line_indices[0],
6819 line_indices[1],
6820 line_indices[2],
6821 line_indices[3]});
6822
6823 new_quads[0]->set_line_orientation(
6824 0, line_orientation[0]);
6825 new_quads[0]->set_line_orientation(
6826 1, line_orientation[1]);
6827 new_quads[0]->set_line_orientation(
6828 2, line_orientation[2]);
6829 new_quads[0]->set_line_orientation(
6830 3, line_orientation[3]);
6831
6832 // the quads are numbered as follows:
6833 //
6834 // planes in the interior of the old hex:
6835 //
6836 // *
6837 // /|
6838 // / | x
6839 // / | *-------* *---------*
6840 // * | | | / /
6841 // | 0 | | | / /
6842 // | * | | / /
6843 // | / *-------*y *---------*x
6844 // | /
6845 // |/
6846 // *
6847 //
6848 // children of the faces of the old hex
6849 //
6850 // *---*---* *---*---*
6851 // /| | | / / /|
6852 // / | | | / 9 / 10/ |
6853 // / | 5 | 6 | / / / |
6854 // * | | | *---*---* |
6855 // | 1 *---*---* | | | 2 *
6856 // | / / / | | | /
6857 // | / 7 / 8 / | 3 | 4 | /
6858 // |/ / / | | |/
6859 // *---*---* *---*---*
6860 //
6861 // note that we have to take care of the
6862 // orientation of faces.
6863 const int quad_indices[11] = {
6864 new_quads[0]->index(), // 0
6865
6866 hex->face(0)->index(), // 1
6867
6868 hex->face(1)->index(), // 2
6869
6870 hex->face(2)->child_index(
6871 child_at_origin[hex->face(2)->refinement_case() -
6872 1][f_fl[2]][f_ro[2]]), // 3
6873 hex->face(2)->child_index(
6874 1 -
6875 child_at_origin[hex->face(2)->refinement_case() -
6876 1][f_fl[2]][f_ro[2]]),
6877
6878 hex->face(3)->child_index(
6879 child_at_origin[hex->face(3)->refinement_case() -
6880 1][f_fl[3]][f_ro[3]]), // 5
6881 hex->face(3)->child_index(
6882 1 -
6883 child_at_origin[hex->face(3)->refinement_case() -
6884 1][f_fl[3]][f_ro[3]]),
6885
6886 hex->face(4)->child_index(
6887 child_at_origin[hex->face(4)->refinement_case() -
6888 1][f_fl[4]][f_ro[4]]), // 7
6889 hex->face(4)->child_index(
6890 1 -
6891 child_at_origin[hex->face(4)->refinement_case() -
6892 1][f_fl[4]][f_ro[4]]),
6893
6894 hex->face(5)->child_index(
6895 child_at_origin[hex->face(5)->refinement_case() -
6896 1][f_fl[5]][f_ro[5]]), // 9
6897 hex->face(5)->child_index(
6898 1 -
6899 child_at_origin[hex->face(5)->refinement_case() -
6900 1][f_fl[5]][f_ro[5]])
6901
6902 };
6903
6904 new_hexes[0]->set_bounding_object_indices(
6905 {quad_indices[1],
6906 quad_indices[0],
6907 quad_indices[3],
6908 quad_indices[5],
6909 quad_indices[7],
6910 quad_indices[9]});
6911 new_hexes[1]->set_bounding_object_indices(
6912 {quad_indices[0],
6913 quad_indices[2],
6914 quad_indices[4],
6915 quad_indices[6],
6916 quad_indices[8],
6917 quad_indices[10]});
6918 break;
6919 }
6920
6922 {
6924 //
6925 // RefinementCase<dim>::cut_y
6926 //
6927 // the refined cube will look like this:
6928 //
6929 // *---------*
6930 // / /|
6931 // *---------* |
6932 // / /| |
6933 // *---------* | |
6934 // | | | |
6935 // | | | *
6936 // | | |/
6937 // | | *
6938 // | |/
6939 // *---------*
6940 //
6941 // again, first collect some data about the
6942 // indices of the lines, with the following
6943 // numbering:
6944
6945 // face 0: left plane
6946 // *
6947 // /|
6948 // * |
6949 // /| |
6950 // * | |
6951 // | 0 |
6952 // | | *
6953 // | |/
6954 // | *m0
6955 // |/
6956 // *
6957 // face 1: right plane
6958 // *
6959 // /|
6960 // m1* |
6961 // /| |
6962 // * | |
6963 // | 1 |
6964 // | | *
6965 // | |/
6966 // | *
6967 // |/
6968 // *
6969 // face 4: bottom plane
6970 // *-------*
6971 // / /
6972 // m0*---2---*
6973 // / /
6974 // *-------*
6975 // face 5: top plane
6976 // *-------*
6977 // / /
6978 // *---3---*m1
6979 // / /
6980 // *-------*
6981
6982 // set up a list of line iterators first. from
6983 // this, construct lists of line_indices and
6984 // line orientations later on
6985 const typename Triangulation<dim, spacedim>::
6986 raw_line_iterator lines[4] = {
6987 hex->face(0)->child(0)->line(
6988 (hex->face(0)->refinement_case() ==
6990 1 :
6991 3), // 0
6992 hex->face(1)->child(0)->line(
6993 (hex->face(1)->refinement_case() ==
6995 1 :
6996 3), // 1
6997 hex->face(4)->child(0)->line(
6998 (hex->face(4)->refinement_case() ==
7000 1 :
7001 3), // 2
7002 hex->face(5)->child(0)->line(
7003 (hex->face(5)->refinement_case() ==
7005 1 :
7006 3) // 3
7007 };
7008
7009 unsigned int line_indices[4];
7010 for (unsigned int i = 0; i < 4; ++i)
7011 line_indices[i] = lines[i]->index();
7012
7013 // the orientation of lines for the inner quads
7014 // is quite tricky. as these lines are newly
7015 // created ones and thus have no parents, they
7016 // cannot inherit this property. set up an array
7017 // and fill it with the respective values
7018 bool line_orientation[4];
7019
7020 // the middle vertex marked as m0 above is the
7021 // start vertex for lines 0 and 2 in standard
7022 // orientation, whereas m1 is the end vertex of
7023 // lines 1 and 3 in standard orientation
7024 const unsigned int middle_vertices[2] = {
7025 hex->line(0)->child(0)->vertex_index(1),
7026 hex->line(5)->child(0)->vertex_index(1)};
7027
7028 for (unsigned int i = 0; i < 4; ++i)
7029 if (lines[i]->vertex_index(i % 2) ==
7030 middle_vertices[i % 2])
7031 line_orientation[i] = true;
7032 else
7033 {
7034 // it must be the other way round then
7035 Assert(lines[i]->vertex_index((i + 1) % 2) ==
7036 middle_vertices[i % 2],
7038 line_orientation[i] = false;
7039 }
7040
7041 // set up the new quad, line numbering is as
7042 // indicated above
7043 new_quads[0]->set_bounding_object_indices(
7044 {line_indices[2],
7045 line_indices[3],
7046 line_indices[0],
7047 line_indices[1]});
7048
7049 new_quads[0]->set_line_orientation(
7050 0, line_orientation[2]);
7051 new_quads[0]->set_line_orientation(
7052 1, line_orientation[3]);
7053 new_quads[0]->set_line_orientation(
7054 2, line_orientation[0]);
7055 new_quads[0]->set_line_orientation(
7056 3, line_orientation[1]);
7057
7058 // the quads are numbered as follows:
7059 //
7060 // planes in the interior of the old hex:
7061 //
7062 // *
7063 // /|
7064 // / | x
7065 // / | *-------* *---------*
7066 // * | | | / /
7067 // | | | 0 | / /
7068 // | * | | / /
7069 // | / *-------*y *---------*x
7070 // | /
7071 // |/
7072 // *
7073 //
7074 // children of the faces of the old hex
7075 //
7076 // *-------* *-------*
7077 // /| | / 10 /|
7078 // * | | *-------* |
7079 // /| | 6 | / 9 /| |
7080 // * |2| | *-------* |4|
7081 // | | *-------* | | | *
7082 // |1|/ 8 / | |3|/
7083 // | *-------* | 5 | *
7084 // |/ 7 / | |/
7085 // *-------* *-------*
7086 //
7087 // note that we have to take care of the
7088 // orientation of faces.
7089 const int quad_indices[11] = {
7090 new_quads[0]->index(), // 0
7091
7092 hex->face(0)->child_index(
7093 child_at_origin[hex->face(0)->refinement_case() -
7094 1][f_fl[0]][f_ro[0]]), // 1
7095 hex->face(0)->child_index(
7096 1 -
7097 child_at_origin[hex->face(0)->refinement_case() -
7098 1][f_fl[0]][f_ro[0]]),
7099
7100 hex->face(1)->child_index(
7101 child_at_origin[hex->face(1)->refinement_case() -
7102 1][f_fl[1]][f_ro[1]]), // 3
7103 hex->face(1)->child_index(
7104 1 -
7105 child_at_origin[hex->face(1)->refinement_case() -
7106 1][f_fl[1]][f_ro[1]]),
7107
7108 hex->face(2)->index(), // 5
7109
7110 hex->face(3)->index(), // 6
7111
7112 hex->face(4)->child_index(
7113 child_at_origin[hex->face(4)->refinement_case() -
7114 1][f_fl[4]][f_ro[4]]), // 7
7115 hex->face(4)->child_index(
7116 1 -
7117 child_at_origin[hex->face(4)->refinement_case() -
7118 1][f_fl[4]][f_ro[4]]),
7119
7120 hex->face(5)->child_index(
7121 child_at_origin[hex->face(5)->refinement_case() -
7122 1][f_fl[5]][f_ro[5]]), // 9
7123 hex->face(5)->child_index(
7124 1 -
7125 child_at_origin[hex->face(5)->refinement_case() -
7126 1][f_fl[5]][f_ro[5]])
7127
7128 };
7129
7130 new_hexes[0]->set_bounding_object_indices(
7131 {quad_indices[1],
7132 quad_indices[3],
7133 quad_indices[5],
7134 quad_indices[0],
7135 quad_indices[7],
7136 quad_indices[9]});
7137 new_hexes[1]->set_bounding_object_indices(
7138 {quad_indices[2],
7139 quad_indices[4],
7140 quad_indices[0],
7141 quad_indices[6],
7142 quad_indices[8],
7143 quad_indices[10]});
7144 break;
7145 }
7146
7148 {
7150 //
7151 // RefinementCase<dim>::cut_z
7152 //
7153 // the refined cube will look like this:
7154 //
7155 // *---------*
7156 // / /|
7157 // / / |
7158 // / / *
7159 // *---------* /|
7160 // | | / |
7161 // | |/ *
7162 // *---------* /
7163 // | | /
7164 // | |/
7165 // *---------*
7166 //
7167 // again, first collect some data about the
7168 // indices of the lines, with the following
7169 // numbering:
7170
7171 // face 0: left plane
7172 // *
7173 // /|
7174 // / |
7175 // / *
7176 // * /|
7177 // | 0 |
7178 // |/ *
7179 // m0* /
7180 // | /
7181 // |/
7182 // *
7183 // face 1: right plane
7184 // *
7185 // /|
7186 // / |
7187 // / *m1
7188 // * /|
7189 // | 1 |
7190 // |/ *
7191 // * /
7192 // | /
7193 // |/
7194 // *
7195 // face 2: front plane
7196 // (note: x,y exchanged)
7197 // *-------*
7198 // | |
7199 // m0*---2---*
7200 // | |
7201 // *-------*
7202 // face 3: back plane
7203 // (note: x,y exchanged)
7204 // *-------*
7205 // | |
7206 // *---3---*m1
7207 // | |
7208 // *-------*
7209
7210 // set up a list of line iterators first. from
7211 // this, construct lists of line_indices and
7212 // line orientations later on
7213 const typename Triangulation<dim, spacedim>::
7214 raw_line_iterator lines[4] = {
7215 hex->face(0)->child(0)->line(
7216 (hex->face(0)->refinement_case() ==
7218 1 :
7219 3), // 0
7220 hex->face(1)->child(0)->line(
7221 (hex->face(1)->refinement_case() ==
7223 1 :
7224 3), // 1
7225 hex->face(2)->child(0)->line(
7226 (hex->face(2)->refinement_case() ==
7228 1 :
7229 3), // 2
7230 hex->face(3)->child(0)->line(
7231 (hex->face(3)->refinement_case() ==
7233 1 :
7234 3) // 3
7235 };
7236
7237 unsigned int line_indices[4];
7238 for (unsigned int i = 0; i < 4; ++i)
7239 line_indices[i] = lines[i]->index();
7240
7241 // the orientation of lines for the inner quads
7242 // is quite tricky. as these lines are newly
7243 // created ones and thus have no parents, they
7244 // cannot inherit this property. set up an array
7245 // and fill it with the respective values
7246 bool line_orientation[4];
7247
7248 // the middle vertex marked as m0 above is the
7249 // start vertex for lines 0 and 2 in standard
7250 // orientation, whereas m1 is the end vertex of
7251 // lines 1 and 3 in standard orientation
7252 const unsigned int middle_vertices[2] = {
7253 middle_vertex_index<dim, spacedim>(hex->line(8)),
7254 middle_vertex_index<dim, spacedim>(hex->line(11))};
7255
7256 for (unsigned int i = 0; i < 4; ++i)
7257 if (lines[i]->vertex_index(i % 2) ==
7258 middle_vertices[i % 2])
7259 line_orientation[i] = true;
7260 else
7261 {
7262 // it must be the other way round then
7263 Assert(lines[i]->vertex_index((i + 1) % 2) ==
7264 middle_vertices[i % 2],
7266 line_orientation[i] = false;
7267 }
7268
7269 // set up the new quad, line numbering is as
7270 // indicated above
7271 new_quads[0]->set_bounding_object_indices(
7272 {line_indices[0],
7273 line_indices[1],
7274 line_indices[2],
7275 line_indices[3]});
7276
7277 new_quads[0]->set_line_orientation(
7278 0, line_orientation[0]);
7279 new_quads[0]->set_line_orientation(
7280 1, line_orientation[1]);
7281 new_quads[0]->set_line_orientation(
7282 2, line_orientation[2]);
7283 new_quads[0]->set_line_orientation(
7284 3, line_orientation[3]);
7285
7286 // the quads are numbered as follows:
7287 //
7288 // planes in the interior of the old hex:
7289 //
7290 // *
7291 // /|
7292 // / | x
7293 // / | *-------* *---------*
7294 // * | | | / /
7295 // | | | | / 0 /
7296 // | * | | / /
7297 // | / *-------*y *---------*x
7298 // | /
7299 // |/
7300 // *
7301 //
7302 // children of the faces of the old hex
7303 //
7304 // *---*---* *-------*
7305 // /| 8 | / /|
7306 // / | | / 10 / |
7307 // / *-------* / / *
7308 // * 2/| | *-------* 4/|
7309 // | / | 7 | | 6 | / |
7310 // |/1 *-------* | |/3 *
7311 // * / / *-------* /
7312 // | / 9 / | | /
7313 // |/ / | 5 |/
7314 // *-------* *---*---*
7315 //
7316 // note that we have to take care of the
7317 // orientation of faces.
7318 const int quad_indices[11] = {
7319 new_quads[0]->index(), // 0
7320
7321 hex->face(0)->child_index(
7322 child_at_origin[hex->face(0)->refinement_case() -
7323 1][f_fl[0]][f_ro[0]]), // 1
7324 hex->face(0)->child_index(
7325 1 -
7326 child_at_origin[hex->face(0)->refinement_case() -
7327 1][f_fl[0]][f_ro[0]]),
7328
7329 hex->face(1)->child_index(
7330 child_at_origin[hex->face(1)->refinement_case() -
7331 1][f_fl[1]][f_ro[1]]), // 3
7332 hex->face(1)->child_index(
7333 1 -
7334 child_at_origin[hex->face(1)->refinement_case() -
7335 1][f_fl[1]][f_ro[1]]),
7336
7337 hex->face(2)->child_index(
7338 child_at_origin[hex->face(2)->refinement_case() -
7339 1][f_fl[2]][f_ro[2]]), // 5
7340 hex->face(2)->child_index(
7341 1 -
7342 child_at_origin[hex->face(2)->refinement_case() -
7343 1][f_fl[2]][f_ro[2]]),
7344
7345 hex->face(3)->child_index(
7346 child_at_origin[hex->face(3)->refinement_case() -
7347 1][f_fl[3]][f_ro[3]]), // 7
7348 hex->face(3)->child_index(
7349 1 -
7350 child_at_origin[hex->face(3)->refinement_case() -
7351 1][f_fl[3]][f_ro[3]]),
7352
7353 hex->face(4)->index(), // 9
7354
7355 hex->face(5)->index() // 10
7356 };
7357
7358 new_hexes[0]->set_bounding_object_indices(
7359 {quad_indices[1],
7360 quad_indices[3],
7361 quad_indices[5],
7362 quad_indices[7],
7363 quad_indices[9],
7364 quad_indices[0]});
7365 new_hexes[1]->set_bounding_object_indices(
7366 {quad_indices[2],
7367 quad_indices[4],
7368 quad_indices[6],
7369 quad_indices[8],
7370 quad_indices[0],
7371 quad_indices[10]});
7372 break;
7373 }
7374
7376 {
7378 //
7379 // RefinementCase<dim>::cut_xy
7380 //
7381 // the refined cube will look like this:
7382 //
7383 // *----*----*
7384 // / / /|
7385 // *----*----* |
7386 // / / /| |
7387 // *----*----* | |
7388 // | | | | |
7389 // | | | | *
7390 // | | | |/
7391 // | | | *
7392 // | | |/
7393 // *----*----*
7394 //
7395
7396 // first, create the new internal line
7397 new_lines[0]->set_bounding_object_indices(
7398 {middle_vertex_index<dim, spacedim>(hex->face(4)),
7399 middle_vertex_index<dim, spacedim>(hex->face(5))});
7400
7401 // again, first collect some data about the
7402 // indices of the lines, with the following
7403 // numbering:
7404
7405 // face 0: left plane
7406 // *
7407 // /|
7408 // * |
7409 // /| |
7410 // * | |
7411 // | 0 |
7412 // | | *
7413 // | |/
7414 // | *
7415 // |/
7416 // *
7417 // face 1: right plane
7418 // *
7419 // /|
7420 // * |
7421 // /| |
7422 // * | |
7423 // | 1 |
7424 // | | *
7425 // | |/
7426 // | *
7427 // |/
7428 // *
7429 // face 2: front plane
7430 // (note: x,y exchanged)
7431 // *---*---*
7432 // | | |
7433 // | 2 |
7434 // | | |
7435 // *-------*
7436 // face 3: back plane
7437 // (note: x,y exchanged)
7438 // *---*---*
7439 // | | |
7440 // | 3 |
7441 // | | |
7442 // *---*---*
7443 // face 4: bottom plane
7444 // *---*---*
7445 // / 5 /
7446 // *-6-*-7-*
7447 // / 4 /
7448 // *---*---*
7449 // face 5: top plane
7450 // *---*---*
7451 // / 9 /
7452 // *10-*-11*
7453 // / 8 /
7454 // *---*---*
7455 // middle planes
7456 // *-------* *---*---*
7457 // / / | | |
7458 // / / | 12 |
7459 // / / | | |
7460 // *-------* *---*---*
7461
7462 // set up a list of line iterators first. from
7463 // this, construct lists of line_indices and
7464 // line orientations later on
7465 const typename Triangulation<
7466 dim,
7467 spacedim>::raw_line_iterator lines[13] = {
7468 hex->face(0)->child(0)->line(
7469 (hex->face(0)->refinement_case() ==
7471 1 :
7472 3), // 0
7473 hex->face(1)->child(0)->line(
7474 (hex->face(1)->refinement_case() ==
7476 1 :
7477 3), // 1
7478 hex->face(2)->child(0)->line(
7479 (hex->face(2)->refinement_case() ==
7481 1 :
7482 3), // 2
7483 hex->face(3)->child(0)->line(
7484 (hex->face(3)->refinement_case() ==
7486 1 :
7487 3), // 3
7488
7489 hex->face(4)
7490 ->isotropic_child(
7492 0, f_or[4], f_fl[4], f_ro[4]))
7493 ->line(
7495 1, f_or[4], f_fl[4], f_ro[4])), // 4
7496 hex->face(4)
7497 ->isotropic_child(
7499 3, f_or[4], f_fl[4], f_ro[4]))
7500 ->line(
7502 0, f_or[4], f_fl[4], f_ro[4])), // 5
7503 hex->face(4)
7504 ->isotropic_child(
7506 0, f_or[4], f_fl[4], f_ro[4]))
7507 ->line(
7509 3, f_or[4], f_fl[4], f_ro[4])), // 6
7510 hex->face(4)
7511 ->isotropic_child(
7513 3, f_or[4], f_fl[4], f_ro[4]))
7514 ->line(
7516 2, f_or[4], f_fl[4], f_ro[4])), // 7
7517
7518 hex->face(5)
7519 ->isotropic_child(
7521 0, f_or[5], f_fl[5], f_ro[5]))
7522 ->line(
7524 1, f_or[5], f_fl[5], f_ro[5])), // 8
7525 hex->face(5)
7526 ->isotropic_child(
7528 3, f_or[5], f_fl[5], f_ro[5]))
7529 ->line(
7531 0, f_or[5], f_fl[5], f_ro[5])), // 9
7532 hex->face(5)
7533 ->isotropic_child(
7535 0, f_or[5], f_fl[5], f_ro[5]))
7536 ->line(
7538 3, f_or[5], f_fl[5], f_ro[5])), // 10
7539 hex->face(5)
7540 ->isotropic_child(
7542 3, f_or[5], f_fl[5], f_ro[5]))
7543 ->line(
7545 2, f_or[5], f_fl[5], f_ro[5])), // 11
7546
7547 new_lines[0] // 12
7548 };
7549
7550 unsigned int line_indices[13];
7551 for (unsigned int i = 0; i < 13; ++i)
7552 line_indices[i] = lines[i]->index();
7553
7554 // the orientation of lines for the inner quads
7555 // is quite tricky. as these lines are newly
7556 // created ones and thus have no parents, they
7557 // cannot inherit this property. set up an array
7558 // and fill it with the respective values
7559 bool line_orientation[13];
7560
7561 // the middle vertices of the lines of our
7562 // bottom face
7563 const unsigned int middle_vertices[4] = {
7564 hex->line(0)->child(0)->vertex_index(1),
7565 hex->line(1)->child(0)->vertex_index(1),
7566 hex->line(2)->child(0)->vertex_index(1),
7567 hex->line(3)->child(0)->vertex_index(1),
7568 };
7569
7570 // note: for lines 0 to 3 the orientation of the
7571 // line is 'true', if vertex 0 is on the bottom
7572 // face
7573 for (unsigned int i = 0; i < 4; ++i)
7574 if (lines[i]->vertex_index(0) == middle_vertices[i])
7575 line_orientation[i] = true;
7576 else
7577 {
7578 // it must be the other way round then
7579 Assert(lines[i]->vertex_index(1) ==
7580 middle_vertices[i],
7582 line_orientation[i] = false;
7583 }
7584
7585 // note: for lines 4 to 11 (inner lines of the
7586 // outer quads) the following holds: the second
7587 // vertex of the even lines in standard
7588 // orientation is the vertex in the middle of
7589 // the quad, whereas for odd lines the first
7590 // vertex is the same middle vertex.
7591 for (unsigned int i = 4; i < 12; ++i)
7592 if (lines[i]->vertex_index((i + 1) % 2) ==
7593 middle_vertex_index<dim, spacedim>(
7594 hex->face(3 + i / 4)))
7595 line_orientation[i] = true;
7596 else
7597 {
7598 // it must be the other way
7599 // round then
7600 Assert(lines[i]->vertex_index(i % 2) ==
7601 (middle_vertex_index<dim, spacedim>(
7602 hex->face(3 + i / 4))),
7604 line_orientation[i] = false;
7605 }
7606 // for the last line the line orientation is
7607 // always true, since it was just constructed
7608 // that way
7609 line_orientation[12] = true;
7610
7611 // set up the 4 quads, numbered as follows (left
7612 // quad numbering, right line numbering
7613 // extracted from above)
7614 //
7615 // * *
7616 // /| 9|
7617 // * | * |
7618 // y/| | 8| 3
7619 // * |1| * | |
7620 // | | |x | 12|
7621 // |0| * | | *
7622 // | |/ 2 |5
7623 // | * | *
7624 // |/ |4
7625 // * *
7626 //
7627 // x
7628 // *---*---* *10-*-11*
7629 // | | | | | |
7630 // | 2 | 3 | 0 12 1
7631 // | | | | | |
7632 // *---*---*y *-6-*-7-*
7633
7634 new_quads[0]->set_bounding_object_indices(
7635 {line_indices[2],
7636 line_indices[12],
7637 line_indices[4],
7638 line_indices[8]});
7639 new_quads[1]->set_bounding_object_indices(
7640 {line_indices[12],
7641 line_indices[3],
7642 line_indices[5],
7643 line_indices[9]});
7644 new_quads[2]->set_bounding_object_indices(
7645 {line_indices[6],
7646 line_indices[10],
7647 line_indices[0],
7648 line_indices[12]});
7649 new_quads[3]->set_bounding_object_indices(
7650 {line_indices[7],
7651 line_indices[11],
7652 line_indices[12],
7653 line_indices[1]});
7654
7655 new_quads[0]->set_line_orientation(
7656 0, line_orientation[2]);
7657 new_quads[0]->set_line_orientation(
7658 2, line_orientation[4]);
7659 new_quads[0]->set_line_orientation(
7660 3, line_orientation[8]);
7661
7662 new_quads[1]->set_line_orientation(
7663 1, line_orientation[3]);
7664 new_quads[1]->set_line_orientation(
7665 2, line_orientation[5]);
7666 new_quads[1]->set_line_orientation(
7667 3, line_orientation[9]);
7668
7669 new_quads[2]->set_line_orientation(
7670 0, line_orientation[6]);
7671 new_quads[2]->set_line_orientation(
7672 1, line_orientation[10]);
7673 new_quads[2]->set_line_orientation(
7674 2, line_orientation[0]);
7675
7676 new_quads[3]->set_line_orientation(
7677 0, line_orientation[7]);
7678 new_quads[3]->set_line_orientation(
7679 1, line_orientation[11]);
7680 new_quads[3]->set_line_orientation(
7681 3, line_orientation[1]);
7682
7683 // the quads are numbered as follows:
7684 //
7685 // planes in the interior of the old hex:
7686 //
7687 // *
7688 // /|
7689 // * | x
7690 // /| | *---*---* *---------*
7691 // * |1| | | | / /
7692 // | | | | 2 | 3 | / /
7693 // |0| * | | | / /
7694 // | |/ *---*---*y *---------*x
7695 // | *
7696 // |/
7697 // *
7698 //
7699 // children of the faces of the old hex
7700 //
7701 // *---*---* *---*---*
7702 // /| | | /18 / 19/|
7703 // * |10 | 11| /---/---* |
7704 // /| | | | /16 / 17/| |
7705 // * |5| | | *---*---* |7|
7706 // | | *---*---* | | | | *
7707 // |4|/14 / 15/ | | |6|/
7708 // | *---/---/ | 8 | 9 | *
7709 // |/12 / 13/ | | |/
7710 // *---*---* *---*---*
7711 //
7712 // note that we have to take care of the
7713 // orientation of faces.
7714 const int quad_indices[20] = {
7715 new_quads[0]->index(), // 0
7716 new_quads[1]->index(),
7717 new_quads[2]->index(),
7718 new_quads[3]->index(),
7719
7720 hex->face(0)->child_index(
7721 child_at_origin[hex->face(0)->refinement_case() -
7722 1][f_fl[0]][f_ro[0]]), // 4
7723 hex->face(0)->child_index(
7724 1 -
7725 child_at_origin[hex->face(0)->refinement_case() -
7726 1][f_fl[0]][f_ro[0]]),
7727
7728 hex->face(1)->child_index(
7729 child_at_origin[hex->face(1)->refinement_case() -
7730 1][f_fl[1]][f_ro[1]]), // 6
7731 hex->face(1)->child_index(
7732 1 -
7733 child_at_origin[hex->face(1)->refinement_case() -
7734 1][f_fl[1]][f_ro[1]]),
7735
7736 hex->face(2)->child_index(
7737 child_at_origin[hex->face(2)->refinement_case() -
7738 1][f_fl[2]][f_ro[2]]), // 8
7739 hex->face(2)->child_index(
7740 1 -
7741 child_at_origin[hex->face(2)->refinement_case() -
7742 1][f_fl[2]][f_ro[2]]),
7743
7744 hex->face(3)->child_index(
7745 child_at_origin[hex->face(3)->refinement_case() -
7746 1][f_fl[3]][f_ro[3]]), // 10
7747 hex->face(3)->child_index(
7748 1 -
7749 child_at_origin[hex->face(3)->refinement_case() -
7750 1][f_fl[3]][f_ro[3]]),
7751
7752 hex->face(4)->isotropic_child_index(
7754 0, f_or[4], f_fl[4], f_ro[4])), // 12
7755 hex->face(4)->isotropic_child_index(
7757 1, f_or[4], f_fl[4], f_ro[4])),
7758 hex->face(4)->isotropic_child_index(
7760 2, f_or[4], f_fl[4], f_ro[4])),
7761 hex->face(4)->isotropic_child_index(
7763 3, f_or[4], f_fl[4], f_ro[4])),
7764
7765 hex->face(5)->isotropic_child_index(
7767 0, f_or[5], f_fl[5], f_ro[5])), // 16
7768 hex->face(5)->isotropic_child_index(
7770 1, f_or[5], f_fl[5], f_ro[5])),
7771 hex->face(5)->isotropic_child_index(
7773 2, f_or[5], f_fl[5], f_ro[5])),
7774 hex->face(5)->isotropic_child_index(
7776 3, f_or[5], f_fl[5], f_ro[5]))};
7777
7778 new_hexes[0]->set_bounding_object_indices(
7779 {quad_indices[4],
7780 quad_indices[0],
7781 quad_indices[8],
7782 quad_indices[2],
7783 quad_indices[12],
7784 quad_indices[16]});
7785 new_hexes[1]->set_bounding_object_indices(
7786 {quad_indices[0],
7787 quad_indices[6],
7788 quad_indices[9],
7789 quad_indices[3],
7790 quad_indices[13],
7791 quad_indices[17]});
7792 new_hexes[2]->set_bounding_object_indices(
7793 {quad_indices[5],
7794 quad_indices[1],
7795 quad_indices[2],
7796 quad_indices[10],
7797 quad_indices[14],
7798 quad_indices[18]});
7799 new_hexes[3]->set_bounding_object_indices(
7800 {quad_indices[1],
7801 quad_indices[7],
7802 quad_indices[3],
7803 quad_indices[11],
7804 quad_indices[15],
7805 quad_indices[19]});
7806 break;
7807 }
7808
7810 {
7812 //
7813 // RefinementCase<dim>::cut_xz
7814 //
7815 // the refined cube will look like this:
7816 //
7817 // *----*----*
7818 // / / /|
7819 // / / / |
7820 // / / / *
7821 // *----*----* /|
7822 // | | | / |
7823 // | | |/ *
7824 // *----*----* /
7825 // | | | /
7826 // | | |/
7827 // *----*----*
7828 //
7829
7830 // first, create the new internal line
7831 new_lines[0]->set_bounding_object_indices(
7832 {middle_vertex_index<dim, spacedim>(hex->face(2)),
7833 middle_vertex_index<dim, spacedim>(hex->face(3))});
7834
7835 // again, first collect some data about the
7836 // indices of the lines, with the following
7837 // numbering:
7838
7839 // face 0: left plane
7840 // *
7841 // /|
7842 // / |
7843 // / *
7844 // * /|
7845 // | 0 |
7846 // |/ *
7847 // * /
7848 // | /
7849 // |/
7850 // *
7851 // face 1: right plane
7852 // *
7853 // /|
7854 // / |
7855 // / *
7856 // * /|
7857 // | 1 |
7858 // |/ *
7859 // * /
7860 // | /
7861 // |/
7862 // *
7863 // face 2: front plane
7864 // (note: x,y exchanged)
7865 // *---*---*
7866 // | 5 |
7867 // *-6-*-7-*
7868 // | 4 |
7869 // *---*---*
7870 // face 3: back plane
7871 // (note: x,y exchanged)
7872 // *---*---*
7873 // | 9 |
7874 // *10-*-11*
7875 // | 8 |
7876 // *---*---*
7877 // face 4: bottom plane
7878 // *---*---*
7879 // / / /
7880 // / 2 /
7881 // / / /
7882 // *---*---*
7883 // face 5: top plane
7884 // *---*---*
7885 // / / /
7886 // / 3 /
7887 // / / /
7888 // *---*---*
7889 // middle planes
7890 // *---*---* *-------*
7891 // / / / | |
7892 // / 12 / | |
7893 // / / / | |
7894 // *---*---* *-------*
7895
7896 // set up a list of line iterators first. from
7897 // this, construct lists of line_indices and
7898 // line orientations later on
7899 const typename Triangulation<
7900 dim,
7901 spacedim>::raw_line_iterator lines[13] = {
7902 hex->face(0)->child(0)->line(
7903 (hex->face(0)->refinement_case() ==
7905 1 :
7906 3), // 0
7907 hex->face(1)->child(0)->line(
7908 (hex->face(1)->refinement_case() ==
7910 1 :
7911 3), // 1
7912 hex->face(4)->child(0)->line(
7913 (hex->face(4)->refinement_case() ==
7915 1 :
7916 3), // 2
7917 hex->face(5)->child(0)->line(
7918 (hex->face(5)->refinement_case() ==
7920 1 :
7921 3), // 3
7922
7923 hex->face(2)
7924 ->isotropic_child(
7926 0, f_or[2], f_fl[2], f_ro[2]))
7927 ->line(
7929 3, f_or[2], f_fl[2], f_ro[2])), // 4
7930 hex->face(2)
7931 ->isotropic_child(
7933 3, f_or[2], f_fl[2], f_ro[2]))
7934 ->line(
7936 2, f_or[2], f_fl[2], f_ro[2])), // 5
7937 hex->face(2)
7938 ->isotropic_child(
7940 0, f_or[2], f_fl[2], f_ro[2]))
7941 ->line(
7943 1, f_or[2], f_fl[2], f_ro[2])), // 6
7944 hex->face(2)
7945 ->isotropic_child(
7947 3, f_or[2], f_fl[2], f_ro[2]))
7948 ->line(
7950 0, f_or[2], f_fl[2], f_ro[2])), // 7
7951
7952 hex->face(3)
7953 ->isotropic_child(
7955 0, f_or[3], f_fl[3], f_ro[3]))
7956 ->line(
7958 3, f_or[3], f_fl[3], f_ro[3])), // 8
7959 hex->face(3)
7960 ->isotropic_child(
7962 3, f_or[3], f_fl[3], f_ro[3]))
7963 ->line(
7965 2, f_or[3], f_fl[3], f_ro[3])), // 9
7966 hex->face(3)
7967 ->isotropic_child(
7969 0, f_or[3], f_fl[3], f_ro[3]))
7970 ->line(
7972 1, f_or[3], f_fl[3], f_ro[3])), // 10
7973 hex->face(3)
7974 ->isotropic_child(
7976 3, f_or[3], f_fl[3], f_ro[3]))
7977 ->line(
7979 0, f_or[3], f_fl[3], f_ro[3])), // 11
7980
7981 new_lines[0] // 12
7982 };
7983
7984 unsigned int line_indices[13];
7985 for (unsigned int i = 0; i < 13; ++i)
7986 line_indices[i] = lines[i]->index();
7987
7988 // the orientation of lines for the inner quads
7989 // is quite tricky. as these lines are newly
7990 // created ones and thus have no parents, they
7991 // cannot inherit this property. set up an array
7992 // and fill it with the respective values
7993 bool line_orientation[13];
7994
7995 // the middle vertices of the
7996 // lines of our front face
7997 const unsigned int middle_vertices[4] = {
7998 hex->line(8)->child(0)->vertex_index(1),
7999 hex->line(9)->child(0)->vertex_index(1),
8000 hex->line(2)->child(0)->vertex_index(1),
8001 hex->line(6)->child(0)->vertex_index(1),
8002 };
8003
8004 // note: for lines 0 to 3 the orientation of the
8005 // line is 'true', if vertex 0 is on the front
8006 for (unsigned int i = 0; i < 4; ++i)
8007 if (lines[i]->vertex_index(0) == middle_vertices[i])
8008 line_orientation[i] = true;
8009 else
8010 {
8011 // it must be the other way round then
8012 Assert(lines[i]->vertex_index(1) ==
8013 middle_vertices[i],
8015 line_orientation[i] = false;
8016 }
8017
8018 // note: for lines 4 to 11 (inner lines of the
8019 // outer quads) the following holds: the second
8020 // vertex of the even lines in standard
8021 // orientation is the vertex in the middle of
8022 // the quad, whereas for odd lines the first
8023 // vertex is the same middle vertex.
8024 for (unsigned int i = 4; i < 12; ++i)
8025 if (lines[i]->vertex_index((i + 1) % 2) ==
8026 middle_vertex_index<dim, spacedim>(
8027 hex->face(1 + i / 4)))
8028 line_orientation[i] = true;
8029 else
8030 {
8031 // it must be the other way
8032 // round then
8033 Assert(lines[i]->vertex_index(i % 2) ==
8034 (middle_vertex_index<dim, spacedim>(
8035 hex->face(1 + i / 4))),
8037 line_orientation[i] = false;
8038 }
8039 // for the last line the line orientation is
8040 // always true, since it was just constructed
8041 // that way
8042 line_orientation[12] = true;
8043
8044 // set up the 4 quads, numbered as follows (left
8045 // quad numbering, right line numbering
8046 // extracted from above), the drawings denote
8047 // middle planes
8048 //
8049 // * *
8050 // /| /|
8051 // / | 3 9
8052 // y/ * / *
8053 // * 3/| * /|
8054 // | / |x 5 12|8
8055 // |/ * |/ *
8056 // * 2/ * /
8057 // | / 4 2
8058 // |/ |/
8059 // * *
8060 //
8061 // y
8062 // *----*----* *-10-*-11-*
8063 // / / / / / /
8064 // / 0 / 1 / 0 12 1
8065 // / / / / / /
8066 // *----*----*x *--6-*--7-*
8067
8068 new_quads[0]->set_bounding_object_indices(
8069 {line_indices[0],
8070 line_indices[12],
8071 line_indices[6],
8072 line_indices[10]});
8073 new_quads[1]->set_bounding_object_indices(
8074 {line_indices[12],
8075 line_indices[1],
8076 line_indices[7],
8077 line_indices[11]});
8078 new_quads[2]->set_bounding_object_indices(
8079 {line_indices[4],
8080 line_indices[8],
8081 line_indices[2],
8082 line_indices[12]});
8083 new_quads[3]->set_bounding_object_indices(
8084 {line_indices[5],
8085 line_indices[9],
8086 line_indices[12],
8087 line_indices[3]});
8088
8089 new_quads[0]->set_line_orientation(
8090 0, line_orientation[0]);
8091 new_quads[0]->set_line_orientation(
8092 2, line_orientation[6]);
8093 new_quads[0]->set_line_orientation(
8094 3, line_orientation[10]);
8095
8096 new_quads[1]->set_line_orientation(
8097 1, line_orientation[1]);
8098 new_quads[1]->set_line_orientation(
8099 2, line_orientation[7]);
8100 new_quads[1]->set_line_orientation(
8101 3, line_orientation[11]);
8102
8103 new_quads[2]->set_line_orientation(
8104 0, line_orientation[4]);
8105 new_quads[2]->set_line_orientation(
8106 1, line_orientation[8]);
8107 new_quads[2]->set_line_orientation(
8108 2, line_orientation[2]);
8109
8110 new_quads[3]->set_line_orientation(
8111 0, line_orientation[5]);
8112 new_quads[3]->set_line_orientation(
8113 1, line_orientation[9]);
8114 new_quads[3]->set_line_orientation(
8115 3, line_orientation[3]);
8116
8117 // the quads are numbered as follows:
8118 //
8119 // planes in the interior of the old hex:
8120 //
8121 // *
8122 // /|
8123 // / | x
8124 // /3 * *-------* *----*----*
8125 // * /| | | / / /
8126 // | / | | | / 0 / 1 /
8127 // |/ * | | / / /
8128 // * 2/ *-------*y *----*----*x
8129 // | /
8130 // |/
8131 // *
8132 //
8133 // children of the faces
8134 // of the old hex
8135 // *---*---* *---*---*
8136 // /|13 | 15| / / /|
8137 // / | | | /18 / 19/ |
8138 // / *---*---* / / / *
8139 // * 5/| | | *---*---* 7/|
8140 // | / |12 | 14| | 9 | 11| / |
8141 // |/4 *---*---* | | |/6 *
8142 // * / / / *---*---* /
8143 // | /16 / 17/ | | | /
8144 // |/ / / | 8 | 10|/
8145 // *---*---* *---*---*
8146 //
8147 // note that we have to take care of the
8148 // orientation of faces.
8149 const int quad_indices[20] = {
8150 new_quads[0]->index(), // 0
8151 new_quads[1]->index(),
8152 new_quads[2]->index(),
8153 new_quads[3]->index(),
8154
8155 hex->face(0)->child_index(
8156 child_at_origin[hex->face(0)->refinement_case() -
8157 1][f_fl[0]][f_ro[0]]), // 4
8158 hex->face(0)->child_index(
8159 1 -
8160 child_at_origin[hex->face(0)->refinement_case() -
8161 1][f_fl[0]][f_ro[0]]),
8162
8163 hex->face(1)->child_index(
8164 child_at_origin[hex->face(1)->refinement_case() -
8165 1][f_fl[1]][f_ro[1]]), // 6
8166 hex->face(1)->child_index(
8167 1 -
8168 child_at_origin[hex->face(1)->refinement_case() -
8169 1][f_fl[1]][f_ro[1]]),
8170
8171 hex->face(2)->isotropic_child_index(
8173 0, f_or[2], f_fl[2], f_ro[2])), // 8
8174 hex->face(2)->isotropic_child_index(
8176 1, f_or[2], f_fl[2], f_ro[2])),
8177 hex->face(2)->isotropic_child_index(
8179 2, f_or[2], f_fl[2], f_ro[2])),
8180 hex->face(2)->isotropic_child_index(
8182 3, f_or[2], f_fl[2], f_ro[2])),
8183
8184 hex->face(3)->isotropic_child_index(
8186 0, f_or[3], f_fl[3], f_ro[3])), // 12
8187 hex->face(3)->isotropic_child_index(
8189 1, f_or[3], f_fl[3], f_ro[3])),
8190 hex->face(3)->isotropic_child_index(
8192 2, f_or[3], f_fl[3], f_ro[3])),
8193 hex->face(3)->isotropic_child_index(
8195 3, f_or[3], f_fl[3], f_ro[3])),
8196
8197 hex->face(4)->child_index(
8198 child_at_origin[hex->face(4)->refinement_case() -
8199 1][f_fl[4]][f_ro[4]]), // 16
8200 hex->face(4)->child_index(
8201 1 -
8202 child_at_origin[hex->face(4)->refinement_case() -
8203 1][f_fl[4]][f_ro[4]]),
8204
8205 hex->face(5)->child_index(
8206 child_at_origin[hex->face(5)->refinement_case() -
8207 1][f_fl[5]][f_ro[5]]), // 18
8208 hex->face(5)->child_index(
8209 1 -
8210 child_at_origin[hex->face(5)->refinement_case() -
8211 1][f_fl[5]][f_ro[5]])};
8212
8213 // due to the exchange of x and y for the front
8214 // and back face, we order the children
8215 // according to
8216 //
8217 // *---*---*
8218 // | 1 | 3 |
8219 // *---*---*
8220 // | 0 | 2 |
8221 // *---*---*
8222 new_hexes[0]->set_bounding_object_indices(
8223 {quad_indices[4],
8224 quad_indices[2],
8225 quad_indices[8],
8226 quad_indices[12],
8227 quad_indices[16],
8228 quad_indices[0]});
8229 new_hexes[1]->set_bounding_object_indices(
8230 {quad_indices[5],
8231 quad_indices[3],
8232 quad_indices[9],
8233 quad_indices[13],
8234 quad_indices[0],
8235 quad_indices[18]});
8236 new_hexes[2]->set_bounding_object_indices(
8237 {quad_indices[2],
8238 quad_indices[6],
8239 quad_indices[10],
8240 quad_indices[14],
8241 quad_indices[17],
8242 quad_indices[1]});
8243 new_hexes[3]->set_bounding_object_indices(
8244 {quad_indices[3],
8245 quad_indices[7],
8246 quad_indices[11],
8247 quad_indices[15],
8248 quad_indices[1],
8249 quad_indices[19]});
8250 break;
8251 }
8252
8254 {
8256 //
8257 // RefinementCase<dim>::cut_yz
8258 //
8259 // the refined cube will look like this:
8260 //
8261 // *---------*
8262 // / /|
8263 // *---------* |
8264 // / /| |
8265 // *---------* |/|
8266 // | | * |
8267 // | |/| *
8268 // *---------* |/
8269 // | | *
8270 // | |/
8271 // *---------*
8272 //
8273
8274 // first, create the new
8275 // internal line
8276 new_lines[0]->set_bounding_object_indices(
8277
8278 {middle_vertex_index<dim, spacedim>(hex->face(0)),
8279 middle_vertex_index<dim, spacedim>(hex->face(1))});
8280
8281 // again, first collect some data about the
8282 // indices of the lines, with the following
8283 // numbering: (note that face 0 and 1 each are
8284 // shown twice for better readability)
8285
8286 // face 0: left plane
8287 // * *
8288 // /| /|
8289 // * | * |
8290 // /| * /| *
8291 // * 5/| * |7|
8292 // | * | | * |
8293 // |/| * |6| *
8294 // * 4/ * |/
8295 // | * | *
8296 // |/ |/
8297 // * *
8298 // face 1: right plane
8299 // * *
8300 // /| /|
8301 // * | * |
8302 // /| * /| *
8303 // * 9/| * |11
8304 // | * | | * |
8305 // |/| * |10 *
8306 // * 8/ * |/
8307 // | * | *
8308 // |/ |/
8309 // * *
8310 // face 2: front plane
8311 // (note: x,y exchanged)
8312 // *-------*
8313 // | |
8314 // *---0---*
8315 // | |
8316 // *-------*
8317 // face 3: back plane
8318 // (note: x,y exchanged)
8319 // *-------*
8320 // | |
8321 // *---1---*
8322 // | |
8323 // *-------*
8324 // face 4: bottom plane
8325 // *-------*
8326 // / /
8327 // *---2---*
8328 // / /
8329 // *-------*
8330 // face 5: top plane
8331 // *-------*
8332 // / /
8333 // *---3---*
8334 // / /
8335 // *-------*
8336 // middle planes
8337 // *-------* *-------*
8338 // / / | |
8339 // *---12--* | |
8340 // / / | |
8341 // *-------* *-------*
8342
8343 // set up a list of line iterators first. from
8344 // this, construct lists of line_indices and
8345 // line orientations later on
8346 const typename Triangulation<
8347 dim,
8348 spacedim>::raw_line_iterator lines[13] = {
8349 hex->face(2)->child(0)->line(
8350 (hex->face(2)->refinement_case() ==
8352 1 :
8353 3), // 0
8354 hex->face(3)->child(0)->line(
8355 (hex->face(3)->refinement_case() ==
8357 1 :
8358 3), // 1
8359 hex->face(4)->child(0)->line(
8360 (hex->face(4)->refinement_case() ==
8362 1 :
8363 3), // 2
8364 hex->face(5)->child(0)->line(
8365 (hex->face(5)->refinement_case() ==
8367 1 :
8368 3), // 3
8369
8370 hex->face(0)
8371 ->isotropic_child(
8373 0, f_or[0], f_fl[0], f_ro[0]))
8374 ->line(
8376 1, f_or[0], f_fl[0], f_ro[0])), // 4
8377 hex->face(0)
8378 ->isotropic_child(
8380 3, f_or[0], f_fl[0], f_ro[0]))
8381 ->line(
8383 0, f_or[0], f_fl[0], f_ro[0])), // 5
8384 hex->face(0)
8385 ->isotropic_child(
8387 0, f_or[0], f_fl[0], f_ro[0]))
8388 ->line(
8390 3, f_or[0], f_fl[0], f_ro[0])), // 6
8391 hex->face(0)
8392 ->isotropic_child(
8394 3, f_or[0], f_fl[0], f_ro[0]))
8395 ->line(
8397 2, f_or[0], f_fl[0], f_ro[0])), // 7
8398
8399 hex->face(1)
8400 ->isotropic_child(
8402 0, f_or[1], f_fl[1], f_ro[1]))
8403 ->line(
8405 1, f_or[1], f_fl[1], f_ro[1])), // 8
8406 hex->face(1)
8407 ->isotropic_child(
8409 3, f_or[1], f_fl[1], f_ro[1]))
8410 ->line(
8412 0, f_or[1], f_fl[1], f_ro[1])), // 9
8413 hex->face(1)
8414 ->isotropic_child(
8416 0, f_or[1], f_fl[1], f_ro[1]))
8417 ->line(
8419 3, f_or[1], f_fl[1], f_ro[1])), // 10
8420 hex->face(1)
8421 ->isotropic_child(
8423 3, f_or[1], f_fl[1], f_ro[1]))
8424 ->line(
8426 2, f_or[1], f_fl[1], f_ro[1])), // 11
8427
8428 new_lines[0] // 12
8429 };
8430
8431 unsigned int line_indices[13];
8432
8433 for (unsigned int i = 0; i < 13; ++i)
8434 line_indices[i] = lines[i]->index();
8435
8436 // the orientation of lines for the inner quads
8437 // is quite tricky. as these lines are newly
8438 // created ones and thus have no parents, they
8439 // cannot inherit this property. set up an array
8440 // and fill it with the respective values
8441 bool line_orientation[13];
8442
8443 // the middle vertices of the lines of our front
8444 // face
8445 const unsigned int middle_vertices[4] = {
8446 hex->line(8)->child(0)->vertex_index(1),
8447 hex->line(10)->child(0)->vertex_index(1),
8448 hex->line(0)->child(0)->vertex_index(1),
8449 hex->line(4)->child(0)->vertex_index(1),
8450 };
8451
8452 // note: for lines 0 to 3 the orientation of the
8453 // line is 'true', if vertex 0 is on the front
8454 for (unsigned int i = 0; i < 4; ++i)
8455 if (lines[i]->vertex_index(0) == middle_vertices[i])
8456 line_orientation[i] = true;
8457 else
8458 {
8459 // it must be the other way round then
8460 Assert(lines[i]->vertex_index(1) ==
8461 middle_vertices[i],
8463 line_orientation[i] = false;
8464 }
8465
8466 // note: for lines 4 to 11 (inner lines of the
8467 // outer quads) the following holds: the second
8468 // vertex of the even lines in standard
8469 // orientation is the vertex in the middle of
8470 // the quad, whereas for odd lines the first
8471 // vertex is the same middle vertex.
8472 for (unsigned int i = 4; i < 12; ++i)
8473 if (lines[i]->vertex_index((i + 1) % 2) ==
8474 middle_vertex_index<dim, spacedim>(
8475 hex->face(i / 4 - 1)))
8476 line_orientation[i] = true;
8477 else
8478 {
8479 // it must be the other way
8480 // round then
8481 Assert(lines[i]->vertex_index(i % 2) ==
8482 (middle_vertex_index<dim, spacedim>(
8483 hex->face(i / 4 - 1))),
8485 line_orientation[i] = false;
8486 }
8487 // for the last line the line orientation is
8488 // always true, since it was just constructed
8489 // that way
8490 line_orientation[12] = true;
8491
8492 // set up the 4 quads, numbered as follows (left
8493 // quad numbering, right line numbering
8494 // extracted from above)
8495 //
8496 // x
8497 // *-------* *---3---*
8498 // | 3 | 5 9
8499 // *-------* *---12--*
8500 // | 2 | 4 8
8501 // *-------*y *---2---*
8502 //
8503 // y
8504 // *---------* *----1----*
8505 // / 1 / 7 11
8506 // *---------* *----12---*
8507 // / 0 / 6 10
8508 // *---------*x *----0----*
8509
8510 new_quads[0]->set_bounding_object_indices(
8511 {line_indices[6],
8512 line_indices[10],
8513 line_indices[0],
8514 line_indices[12]});
8515 new_quads[1]->set_bounding_object_indices(
8516 {line_indices[7],
8517 line_indices[11],
8518 line_indices[12],
8519 line_indices[1]});
8520 new_quads[2]->set_bounding_object_indices(
8521 {line_indices[2],
8522 line_indices[12],
8523 line_indices[4],
8524 line_indices[8]});
8525 new_quads[3]->set_bounding_object_indices(
8526 {line_indices[12],
8527 line_indices[3],
8528 line_indices[5],
8529 line_indices[9]});
8530
8531 new_quads[0]->set_line_orientation(
8532 0, line_orientation[6]);
8533 new_quads[0]->set_line_orientation(
8534 1, line_orientation[10]);
8535 new_quads[0]->set_line_orientation(
8536 2, line_orientation[0]);
8537
8538 new_quads[1]->set_line_orientation(
8539 0, line_orientation[7]);
8540 new_quads[1]->set_line_orientation(
8541 1, line_orientation[11]);
8542 new_quads[1]->set_line_orientation(
8543 3, line_orientation[1]);
8544
8545 new_quads[2]->set_line_orientation(
8546 0, line_orientation[2]);
8547 new_quads[2]->set_line_orientation(
8548 2, line_orientation[4]);
8549 new_quads[2]->set_line_orientation(
8550 3, line_orientation[8]);
8551
8552 new_quads[3]->set_line_orientation(
8553 1, line_orientation[3]);
8554 new_quads[3]->set_line_orientation(
8555 2, line_orientation[5]);
8556 new_quads[3]->set_line_orientation(
8557 3, line_orientation[9]);
8558
8559 // the quads are numbered as follows:
8560 //
8561 // planes in the interior of the old hex:
8562 //
8563 // *
8564 // /|
8565 // / | x
8566 // / | *-------* *---------*
8567 // * | | 3 | / 1 /
8568 // | | *-------* *---------*
8569 // | * | 2 | / 0 /
8570 // | / *-------*y *---------*x
8571 // | /
8572 // |/
8573 // *
8574 //
8575 // children of the faces
8576 // of the old hex
8577 // *-------* *-------*
8578 // /| | / 19 /|
8579 // * | 15 | *-------* |
8580 // /|7*-------* / 18 /|11
8581 // * |/| | *-------* |/|
8582 // |6* | 14 | | 10* |
8583 // |/|5*-------* | 13 |/|9*
8584 // * |/ 17 / *-------* |/
8585 // |4*-------* | |8*
8586 // |/ 16 / | 12 |/
8587 // *-------* *-------*
8588 //
8589 // note that we have to take care of the
8590 // orientation of faces.
8591 const int quad_indices[20] = {
8592 new_quads[0]->index(), // 0
8593 new_quads[1]->index(),
8594 new_quads[2]->index(),
8595 new_quads[3]->index(),
8596
8597 hex->face(0)->isotropic_child_index(
8599 0, f_or[0], f_fl[0], f_ro[0])), // 4
8600 hex->face(0)->isotropic_child_index(
8602 1, f_or[0], f_fl[0], f_ro[0])),
8603 hex->face(0)->isotropic_child_index(
8605 2, f_or[0], f_fl[0], f_ro[0])),
8606 hex->face(0)->isotropic_child_index(
8608 3, f_or[0], f_fl[0], f_ro[0])),
8609
8610 hex->face(1)->isotropic_child_index(
8612 0, f_or[1], f_fl[1], f_ro[1])), // 8
8613 hex->face(1)->isotropic_child_index(
8615 1, f_or[1], f_fl[1], f_ro[1])),
8616 hex->face(1)->isotropic_child_index(
8618 2, f_or[1], f_fl[1], f_ro[1])),
8619 hex->face(1)->isotropic_child_index(
8621 3, f_or[1], f_fl[1], f_ro[1])),
8622
8623 hex->face(2)->child_index(
8624 child_at_origin[hex->face(2)->refinement_case() -
8625 1][f_fl[2]][f_ro[2]]), // 12
8626 hex->face(2)->child_index(
8627 1 -
8628 child_at_origin[hex->face(2)->refinement_case() -
8629 1][f_fl[2]][f_ro[2]]),
8630
8631 hex->face(3)->child_index(
8632 child_at_origin[hex->face(3)->refinement_case() -
8633 1][f_fl[3]][f_ro[3]]), // 14
8634 hex->face(3)->child_index(
8635 1 -
8636 child_at_origin[hex->face(3)->refinement_case() -
8637 1][f_fl[3]][f_ro[3]]),
8638
8639 hex->face(4)->child_index(
8640 child_at_origin[hex->face(4)->refinement_case() -
8641 1][f_fl[4]][f_ro[4]]), // 16
8642 hex->face(4)->child_index(
8643 1 -
8644 child_at_origin[hex->face(4)->refinement_case() -
8645 1][f_fl[4]][f_ro[4]]),
8646
8647 hex->face(5)->child_index(
8648 child_at_origin[hex->face(5)->refinement_case() -
8649 1][f_fl[5]][f_ro[5]]), // 18
8650 hex->face(5)->child_index(
8651 1 -
8652 child_at_origin[hex->face(5)->refinement_case() -
8653 1][f_fl[5]][f_ro[5]])};
8654
8655 new_hexes[0]->set_bounding_object_indices(
8656 {quad_indices[4],
8657 quad_indices[8],
8658 quad_indices[12],
8659 quad_indices[2],
8660 quad_indices[16],
8661 quad_indices[0]});
8662 new_hexes[1]->set_bounding_object_indices(
8663 {quad_indices[5],
8664 quad_indices[9],
8665 quad_indices[2],
8666 quad_indices[14],
8667 quad_indices[17],
8668 quad_indices[1]});
8669 new_hexes[2]->set_bounding_object_indices(
8670 {quad_indices[6],
8671 quad_indices[10],
8672 quad_indices[13],
8673 quad_indices[3],
8674 quad_indices[0],
8675 quad_indices[18]});
8676 new_hexes[3]->set_bounding_object_indices(
8677 {quad_indices[7],
8678 quad_indices[11],
8679 quad_indices[3],
8680 quad_indices[15],
8681 quad_indices[1],
8682 quad_indices[19]});
8683 break;
8684 }
8685
8687 {
8689 //
8690 // RefinementCase<dim>::cut_xyz
8691 // isotropic refinement
8692 //
8693 // the refined cube will look
8694 // like this:
8695 //
8696 // *----*----*
8697 // / / /|
8698 // *----*----* |
8699 // / / /| *
8700 // *----*----* |/|
8701 // | | | * |
8702 // | | |/| *
8703 // *----*----* |/
8704 // | | | *
8705 // | | |/
8706 // *----*----*
8707 //
8708
8709 // find the next unused vertex and set it
8710 // appropriately
8711 while (
8712 triangulation.vertices_used[next_unused_vertex] ==
8713 true)
8714 ++next_unused_vertex;
8715 Assert(
8716 next_unused_vertex < triangulation.vertices.size(),
8717 ExcMessage(
8718 "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."));
8719 triangulation.vertices_used[next_unused_vertex] =
8720 true;
8721
8722 // the new vertex is definitely in the interior,
8723 // so we need not worry about the
8724 // boundary. However we need to worry about
8725 // Manifolds. Let the cell compute its own
8726 // center, by querying the underlying manifold
8727 // object.
8728 triangulation.vertices[next_unused_vertex] =
8729 hex->center(true, true);
8730
8731 // set the data of the six lines. first collect
8732 // the indices of the seven vertices (consider
8733 // the two planes to be crossed to form the
8734 // planes cutting the hex in two vertically and
8735 // horizontally)
8736 //
8737 // *--3--* *--5--*
8738 // / / / | | |
8739 // 0--6--1 0--6--1
8740 // / / / | | |
8741 // *--2--* *--4--*
8742 // the lines are numbered
8743 // as follows:
8744 // *--*--* *--*--*
8745 // / 1 / | 5 |
8746 // *2-*-3* *2-*-3*
8747 // / 0 / | 4 |
8748 // *--*--* *--*--*
8749 //
8750 const unsigned int vertex_indices[7] = {
8751 middle_vertex_index<dim, spacedim>(hex->face(0)),
8752 middle_vertex_index<dim, spacedim>(hex->face(1)),
8753 middle_vertex_index<dim, spacedim>(hex->face(2)),
8754 middle_vertex_index<dim, spacedim>(hex->face(3)),
8755 middle_vertex_index<dim, spacedim>(hex->face(4)),
8756 middle_vertex_index<dim, spacedim>(hex->face(5)),
8757 next_unused_vertex};
8758
8759 new_lines[0]->set_bounding_object_indices(
8761 new_lines[1]->set_bounding_object_indices(
8763 new_lines[2]->set_bounding_object_indices(
8765 new_lines[3]->set_bounding_object_indices(
8767 new_lines[4]->set_bounding_object_indices(
8769 new_lines[5]->set_bounding_object_indices(
8771
8772 // again, first collect some data about the
8773 // indices of the lines, with the following
8774 // numbering: (note that face 0 and 1 each are
8775 // shown twice for better readability)
8776
8777 // face 0: left plane
8778 // * *
8779 // /| /|
8780 // * | * |
8781 // /| * /| *
8782 // * 1/| * |3|
8783 // | * | | * |
8784 // |/| * |2| *
8785 // * 0/ * |/
8786 // | * | *
8787 // |/ |/
8788 // * *
8789 // face 1: right plane
8790 // * *
8791 // /| /|
8792 // * | * |
8793 // /| * /| *
8794 // * 5/| * |7|
8795 // | * | | * |
8796 // |/| * |6| *
8797 // * 4/ * |/
8798 // | * | *
8799 // |/ |/
8800 // * *
8801 // face 2: front plane
8802 // (note: x,y exchanged)
8803 // *---*---*
8804 // | 11 |
8805 // *-8-*-9-*
8806 // | 10 |
8807 // *---*---*
8808 // face 3: back plane
8809 // (note: x,y exchanged)
8810 // *---*---*
8811 // | 15 |
8812 // *12-*-13*
8813 // | 14 |
8814 // *---*---*
8815 // face 4: bottom plane
8816 // *---*---*
8817 // / 17 /
8818 // *18-*-19*
8819 // / 16 /
8820 // *---*---*
8821 // face 5: top plane
8822 // *---*---*
8823 // / 21 /
8824 // *22-*-23*
8825 // / 20 /
8826 // *---*---*
8827 // middle planes
8828 // *---*---* *---*---*
8829 // / 25 / | 29 |
8830 // *26-*-27* *26-*-27*
8831 // / 24 / | 28 |
8832 // *---*---* *---*---*
8833
8834 // set up a list of line iterators first. from
8835 // this, construct lists of line_indices and
8836 // line orientations later on
8837 const typename Triangulation<
8838 dim,
8839 spacedim>::raw_line_iterator lines[30] = {
8840 hex->face(0)
8841 ->isotropic_child(
8843 0, f_or[0], f_fl[0], f_ro[0]))
8844 ->line(
8846 1, f_or[0], f_fl[0], f_ro[0])), // 0
8847 hex->face(0)
8848 ->isotropic_child(
8850 3, f_or[0], f_fl[0], f_ro[0]))
8851 ->line(
8853 0, f_or[0], f_fl[0], f_ro[0])), // 1
8854 hex->face(0)
8855 ->isotropic_child(
8857 0, f_or[0], f_fl[0], f_ro[0]))
8858 ->line(
8860 3, f_or[0], f_fl[0], f_ro[0])), // 2
8861 hex->face(0)
8862 ->isotropic_child(
8864 3, f_or[0], f_fl[0], f_ro[0]))
8865 ->line(
8867 2, f_or[0], f_fl[0], f_ro[0])), // 3
8868
8869 hex->face(1)
8870 ->isotropic_child(
8872 0, f_or[1], f_fl[1], f_ro[1]))
8873 ->line(
8875 1, f_or[1], f_fl[1], f_ro[1])), // 4
8876 hex->face(1)
8877 ->isotropic_child(
8879 3, f_or[1], f_fl[1], f_ro[1]))
8880 ->line(
8882 0, f_or[1], f_fl[1], f_ro[1])), // 5
8883 hex->face(1)
8884 ->isotropic_child(
8886 0, f_or[1], f_fl[1], f_ro[1]))
8887 ->line(
8889 3, f_or[1], f_fl[1], f_ro[1])), // 6
8890 hex->face(1)
8891 ->isotropic_child(
8893 3, f_or[1], f_fl[1], f_ro[1]))
8894 ->line(
8896 2, f_or[1], f_fl[1], f_ro[1])), // 7
8897
8898 hex->face(2)
8899 ->isotropic_child(
8901 0, f_or[2], f_fl[2], f_ro[2]))
8902 ->line(
8904 1, f_or[2], f_fl[2], f_ro[2])), // 8
8905 hex->face(2)
8906 ->isotropic_child(
8908 3, f_or[2], f_fl[2], f_ro[2]))
8909 ->line(
8911 0, f_or[2], f_fl[2], f_ro[2])), // 9
8912 hex->face(2)
8913 ->isotropic_child(
8915 0, f_or[2], f_fl[2], f_ro[2]))
8916 ->line(
8918 3, f_or[2], f_fl[2], f_ro[2])), // 10
8919 hex->face(2)
8920 ->isotropic_child(
8922 3, f_or[2], f_fl[2], f_ro[2]))
8923 ->line(
8925 2, f_or[2], f_fl[2], f_ro[2])), // 11
8926
8927 hex->face(3)
8928 ->isotropic_child(
8930 0, f_or[3], f_fl[3], f_ro[3]))
8931 ->line(
8933 1, f_or[3], f_fl[3], f_ro[3])), // 12
8934 hex->face(3)
8935 ->isotropic_child(
8937 3, f_or[3], f_fl[3], f_ro[3]))
8938 ->line(
8940 0, f_or[3], f_fl[3], f_ro[3])), // 13
8941 hex->face(3)
8942 ->isotropic_child(
8944 0, f_or[3], f_fl[3], f_ro[3]))
8945 ->line(
8947 3, f_or[3], f_fl[3], f_ro[3])), // 14
8948 hex->face(3)
8949 ->isotropic_child(
8951 3, f_or[3], f_fl[3], f_ro[3]))
8952 ->line(
8954 2, f_or[3], f_fl[3], f_ro[3])), // 15
8955
8956 hex->face(4)
8957 ->isotropic_child(
8959 0, f_or[4], f_fl[4], f_ro[4]))
8960 ->line(
8962 1, f_or[4], f_fl[4], f_ro[4])), // 16
8963 hex->face(4)
8964 ->isotropic_child(
8966 3, f_or[4], f_fl[4], f_ro[4]))
8967 ->line(
8969 0, f_or[4], f_fl[4], f_ro[4])), // 17
8970 hex->face(4)
8971 ->isotropic_child(
8973 0, f_or[4], f_fl[4], f_ro[4]))
8974 ->line(
8976 3, f_or[4], f_fl[4], f_ro[4])), // 18
8977 hex->face(4)
8978 ->isotropic_child(
8980 3, f_or[4], f_fl[4], f_ro[4]))
8981 ->line(
8983 2, f_or[4], f_fl[4], f_ro[4])), // 19
8984
8985 hex->face(5)
8986 ->isotropic_child(
8988 0, f_or[5], f_fl[5], f_ro[5]))
8989 ->line(
8991 1, f_or[5], f_fl[5], f_ro[5])), // 20
8992 hex->face(5)
8993 ->isotropic_child(
8995 3, f_or[5], f_fl[5], f_ro[5]))
8996 ->line(
8998 0, f_or[5], f_fl[5], f_ro[5])), // 21
8999 hex->face(5)
9000 ->isotropic_child(
9002 0, f_or[5], f_fl[5], f_ro[5]))
9003 ->line(
9005 3, f_or[5], f_fl[5], f_ro[5])), // 22
9006 hex->face(5)
9007 ->isotropic_child(
9009 3, f_or[5], f_fl[5], f_ro[5]))
9010 ->line(
9012 2, f_or[5], f_fl[5], f_ro[5])), // 23
9013
9014 new_lines[0], // 24
9015 new_lines[1], // 25
9016 new_lines[2], // 26
9017 new_lines[3], // 27
9018 new_lines[4], // 28
9019 new_lines[5] // 29
9020 };
9021
9022 unsigned int line_indices[30];
9023 for (unsigned int i = 0; i < 30; ++i)
9024 line_indices[i] = lines[i]->index();
9025
9026 // the orientation of lines for the inner quads
9027 // is quite tricky. as these lines are newly
9028 // created ones and thus have no parents, they
9029 // cannot inherit this property. set up an array
9030 // and fill it with the respective values
9031 bool line_orientation[30];
9032
9033 // note: for the first 24 lines (inner lines of
9034 // the outer quads) the following holds: the
9035 // second vertex of the even lines in standard
9036 // orientation is the vertex in the middle of
9037 // the quad, whereas for odd lines the first
9038 // vertex is the same middle vertex.
9039 for (unsigned int i = 0; i < 24; ++i)
9040 if (lines[i]->vertex_index((i + 1) % 2) ==
9041 vertex_indices[i / 4])
9042 line_orientation[i] = true;
9043 else
9044 {
9045 // it must be the other way
9046 // round then
9047 Assert(lines[i]->vertex_index(i % 2) ==
9048 vertex_indices[i / 4],
9050 line_orientation[i] = false;
9051 }
9052 // for the last 6 lines the line orientation is
9053 // always true, since they were just constructed
9054 // that way
9055 for (unsigned int i = 24; i < 30; ++i)
9056 line_orientation[i] = true;
9057
9058 // set up the 12 quads, numbered as follows
9059 // (left quad numbering, right line numbering
9060 // extracted from above)
9061 //
9062 // * *
9063 // /| 21|
9064 // * | * 15
9065 // y/|3* 20| *
9066 // * |/| * |/|
9067 // |2* |x 11 * 14
9068 // |/|1* |/| *
9069 // * |/ * |17
9070 // |0* 10 *
9071 // |/ |16
9072 // * *
9073 //
9074 // x
9075 // *---*---* *22-*-23*
9076 // | 5 | 7 | 1 29 5
9077 // *---*---* *26-*-27*
9078 // | 4 | 6 | 0 28 4
9079 // *---*---*y *18-*-19*
9080 //
9081 // y
9082 // *----*----* *-12-*-13-*
9083 // / 10 / 11 / 3 25 7
9084 // *----*----* *-26-*-27-*
9085 // / 8 / 9 / 2 24 6
9086 // *----*----*x *--8-*--9-*
9087
9088 new_quads[0]->set_bounding_object_indices(
9089 {line_indices[10],
9090 line_indices[28],
9091 line_indices[16],
9092 line_indices[24]});
9093 new_quads[1]->set_bounding_object_indices(
9094 {line_indices[28],
9095 line_indices[14],
9096 line_indices[17],
9097 line_indices[25]});
9098 new_quads[2]->set_bounding_object_indices(
9099 {line_indices[11],
9100 line_indices[29],
9101 line_indices[24],
9102 line_indices[20]});
9103 new_quads[3]->set_bounding_object_indices(
9104 {line_indices[29],
9105 line_indices[15],
9106 line_indices[25],
9107 line_indices[21]});
9108 new_quads[4]->set_bounding_object_indices(
9109 {line_indices[18],
9110 line_indices[26],
9111 line_indices[0],
9112 line_indices[28]});
9113 new_quads[5]->set_bounding_object_indices(
9114 {line_indices[26],
9115 line_indices[22],
9116 line_indices[1],
9117 line_indices[29]});
9118 new_quads[6]->set_bounding_object_indices(
9119 {line_indices[19],
9120 line_indices[27],
9121 line_indices[28],
9122 line_indices[4]});
9123 new_quads[7]->set_bounding_object_indices(
9124 {line_indices[27],
9125 line_indices[23],
9126 line_indices[29],
9127 line_indices[5]});
9128 new_quads[8]->set_bounding_object_indices(
9129 {line_indices[2],
9130 line_indices[24],
9131 line_indices[8],
9132 line_indices[26]});
9133 new_quads[9]->set_bounding_object_indices(
9134 {line_indices[24],
9135 line_indices[6],
9136 line_indices[9],
9137 line_indices[27]});
9138 new_quads[10]->set_bounding_object_indices(
9139 {line_indices[3],
9140 line_indices[25],
9141 line_indices[26],
9142 line_indices[12]});
9143 new_quads[11]->set_bounding_object_indices(
9144 {line_indices[25],
9145 line_indices[7],
9146 line_indices[27],
9147 line_indices[13]});
9148
9149 // now reset the line_orientation flags of outer
9150 // lines as they cannot be set in a loop (at
9151 // least not easily)
9152 new_quads[0]->set_line_orientation(
9153 0, line_orientation[10]);
9154 new_quads[0]->set_line_orientation(
9155 2, line_orientation[16]);
9156
9157 new_quads[1]->set_line_orientation(
9158 1, line_orientation[14]);
9159 new_quads[1]->set_line_orientation(
9160 2, line_orientation[17]);
9161
9162 new_quads[2]->set_line_orientation(
9163 0, line_orientation[11]);
9164 new_quads[2]->set_line_orientation(
9165 3, line_orientation[20]);
9166
9167 new_quads[3]->set_line_orientation(
9168 1, line_orientation[15]);
9169 new_quads[3]->set_line_orientation(
9170 3, line_orientation[21]);
9171
9172 new_quads[4]->set_line_orientation(
9173 0, line_orientation[18]);
9174 new_quads[4]->set_line_orientation(
9175 2, line_orientation[0]);
9176
9177 new_quads[5]->set_line_orientation(
9178 1, line_orientation[22]);
9179 new_quads[5]->set_line_orientation(
9180 2, line_orientation[1]);
9181
9182 new_quads[6]->set_line_orientation(
9183 0, line_orientation[19]);
9184 new_quads[6]->set_line_orientation(
9185 3, line_orientation[4]);
9186
9187 new_quads[7]->set_line_orientation(
9188 1, line_orientation[23]);
9189 new_quads[7]->set_line_orientation(
9190 3, line_orientation[5]);
9191
9192 new_quads[8]->set_line_orientation(
9193 0, line_orientation[2]);
9194 new_quads[8]->set_line_orientation(
9195 2, line_orientation[8]);
9196
9197 new_quads[9]->set_line_orientation(
9198 1, line_orientation[6]);
9199 new_quads[9]->set_line_orientation(
9200 2, line_orientation[9]);
9201
9202 new_quads[10]->set_line_orientation(
9203 0, line_orientation[3]);
9204 new_quads[10]->set_line_orientation(
9205 3, line_orientation[12]);
9206
9207 new_quads[11]->set_line_orientation(
9208 1, line_orientation[7]);
9209 new_quads[11]->set_line_orientation(
9210 3, line_orientation[13]);
9211
9213 // create the eight new hexes
9214 //
9215 // again first collect some data. here, we need
9216 // the indices of a whole lotta quads.
9217
9218 // the quads are numbered as follows:
9219 //
9220 // planes in the interior of the old hex:
9221 //
9222 // *
9223 // /|
9224 // * |
9225 // /|3* *---*---* *----*----*
9226 // * |/| | 5 | 7 | / 10 / 11 /
9227 // |2* | *---*---* *----*----*
9228 // |/|1* | 4 | 6 | / 8 / 9 /
9229 // * |/ *---*---*y *----*----*x
9230 // |0*
9231 // |/
9232 // *
9233 //
9234 // children of the faces
9235 // of the old hex
9236 // *-------* *-------*
9237 // /|25 27| /34 35/|
9238 // 15| | / /19
9239 // / | | /32 33/ |
9240 // * |24 26| *-------*18 |
9241 // 1413*-------* |21 23| 17*
9242 // | /30 31/ | | /
9243 // 12/ / | |16
9244 // |/28 29/ |20 22|/
9245 // *-------* *-------*
9246 //
9247 // note that we have to
9248 // take care of the
9249 // orientation of
9250 // faces.
9251 const int quad_indices[36] = {
9252 new_quads[0]->index(), // 0
9253 new_quads[1]->index(),
9254 new_quads[2]->index(),
9255 new_quads[3]->index(),
9256 new_quads[4]->index(),
9257 new_quads[5]->index(),
9258 new_quads[6]->index(),
9259 new_quads[7]->index(),
9260 new_quads[8]->index(),
9261 new_quads[9]->index(),
9262 new_quads[10]->index(),
9263 new_quads[11]->index(), // 11
9264
9265 hex->face(0)->isotropic_child_index(
9267 0, f_or[0], f_fl[0], f_ro[0])), // 12
9268 hex->face(0)->isotropic_child_index(
9270 1, f_or[0], f_fl[0], f_ro[0])),
9271 hex->face(0)->isotropic_child_index(
9273 2, f_or[0], f_fl[0], f_ro[0])),
9274 hex->face(0)->isotropic_child_index(
9276 3, f_or[0], f_fl[0], f_ro[0])),
9277
9278 hex->face(1)->isotropic_child_index(
9280 0, f_or[1], f_fl[1], f_ro[1])), // 16
9281 hex->face(1)->isotropic_child_index(
9283 1, f_or[1], f_fl[1], f_ro[1])),
9284 hex->face(1)->isotropic_child_index(
9286 2, f_or[1], f_fl[1], f_ro[1])),
9287 hex->face(1)->isotropic_child_index(
9289 3, f_or[1], f_fl[1], f_ro[1])),
9290
9291 hex->face(2)->isotropic_child_index(
9293 0, f_or[2], f_fl[2], f_ro[2])), // 20
9294 hex->face(2)->isotropic_child_index(
9296 1, f_or[2], f_fl[2], f_ro[2])),
9297 hex->face(2)->isotropic_child_index(
9299 2, f_or[2], f_fl[2], f_ro[2])),
9300 hex->face(2)->isotropic_child_index(
9302 3, f_or[2], f_fl[2], f_ro[2])),
9303
9304 hex->face(3)->isotropic_child_index(
9306 0, f_or[3], f_fl[3], f_ro[3])), // 24
9307 hex->face(3)->isotropic_child_index(
9309 1, f_or[3], f_fl[3], f_ro[3])),
9310 hex->face(3)->isotropic_child_index(
9312 2, f_or[3], f_fl[3], f_ro[3])),
9313 hex->face(3)->isotropic_child_index(
9315 3, f_or[3], f_fl[3], f_ro[3])),
9316
9317 hex->face(4)->isotropic_child_index(
9319 0, f_or[4], f_fl[4], f_ro[4])), // 28
9320 hex->face(4)->isotropic_child_index(
9322 1, f_or[4], f_fl[4], f_ro[4])),
9323 hex->face(4)->isotropic_child_index(
9325 2, f_or[4], f_fl[4], f_ro[4])),
9326 hex->face(4)->isotropic_child_index(
9328 3, f_or[4], f_fl[4], f_ro[4])),
9329
9330 hex->face(5)->isotropic_child_index(
9332 0, f_or[5], f_fl[5], f_ro[5])), // 32
9333 hex->face(5)->isotropic_child_index(
9335 1, f_or[5], f_fl[5], f_ro[5])),
9336 hex->face(5)->isotropic_child_index(
9338 2, f_or[5], f_fl[5], f_ro[5])),
9339 hex->face(5)->isotropic_child_index(
9341 3, f_or[5], f_fl[5], f_ro[5]))};
9342
9343 // bottom children
9344 new_hexes[0]->set_bounding_object_indices(
9345 {quad_indices[12],
9346 quad_indices[0],
9347 quad_indices[20],
9348 quad_indices[4],
9349 quad_indices[28],
9350 quad_indices[8]});
9351 new_hexes[1]->set_bounding_object_indices(
9352 {quad_indices[0],
9353 quad_indices[16],
9354 quad_indices[22],
9355 quad_indices[6],
9356 quad_indices[29],
9357 quad_indices[9]});
9358 new_hexes[2]->set_bounding_object_indices(
9359 {quad_indices[13],
9360 quad_indices[1],
9361 quad_indices[4],
9362 quad_indices[24],
9363 quad_indices[30],
9364 quad_indices[10]});
9365 new_hexes[3]->set_bounding_object_indices(
9366 {quad_indices[1],
9367 quad_indices[17],
9368 quad_indices[6],
9369 quad_indices[26],
9370 quad_indices[31],
9371 quad_indices[11]});
9372
9373 // top children
9374 new_hexes[4]->set_bounding_object_indices(
9375 {quad_indices[14],
9376 quad_indices[2],
9377 quad_indices[21],
9378 quad_indices[5],
9379 quad_indices[8],
9380 quad_indices[32]});
9381 new_hexes[5]->set_bounding_object_indices(
9382 {quad_indices[2],
9383 quad_indices[18],
9384 quad_indices[23],
9385 quad_indices[7],
9386 quad_indices[9],
9387 quad_indices[33]});
9388 new_hexes[6]->set_bounding_object_indices(
9389 {quad_indices[15],
9390 quad_indices[3],
9391 quad_indices[5],
9392 quad_indices[25],
9393 quad_indices[10],
9394 quad_indices[34]});
9395 new_hexes[7]->set_bounding_object_indices(
9396 {quad_indices[3],
9397 quad_indices[19],
9398 quad_indices[7],
9399 quad_indices[27],
9400 quad_indices[11],
9401 quad_indices[35]});
9402 break;
9403 }
9404 default:
9405 // all refinement cases have been treated, there
9406 // only remains
9407 // RefinementCase<dim>::no_refinement as
9408 // untreated enumeration value. However, in that
9409 // case we should have aborted much
9410 // earlier. thus we should never get here
9411 Assert(false, ExcInternalError());
9412 break;
9413 } // switch (ref_case)
9414
9415 // and set face orientation flags. note that new
9416 // faces in the interior of the mother cell always
9417 // have a correctly oriented face, but the ones on
9418 // the outer faces will inherit this flag
9419 //
9420 // the flag have been set to true for all faces
9421 // initially, now go the other way round and reset
9422 // faces that are at the boundary of the mother cube
9423 //
9424 // the same is true for the face_flip and
9425 // face_rotation flags. however, the latter two are
9426 // set to false by default as this is the standard
9427 // value
9428
9429 // loop over all faces and all (relevant) subfaces
9430 // of that in order to set the correct values for
9431 // face_orientation, face_flip and face_rotation,
9432 // which are inherited from the corresponding face
9433 // of the mother cube
9434 for (const unsigned int f : GeometryInfo<dim>::face_indices())
9435 for (unsigned int s = 0;
9438 ref_case, f)),
9439 1U);
9440 ++s)
9441 {
9442 const unsigned int current_child =
9444 ref_case,
9445 f,
9446 s,
9447 f_or[f],
9448 f_fl[f],
9449 f_ro[f],
9451 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
9452 new_hexes[current_child]->set_face_orientation(f,
9453 f_or[f]);
9454 new_hexes[current_child]->set_face_flip(f, f_fl[f]);
9455 new_hexes[current_child]->set_face_rotation(f, f_ro[f]);
9456 }
9457
9458 // now see if we have created cells that are
9459 // distorted and if so add them to our list
9460 if (check_for_distorted_cells &&
9461 has_distorted_children<dim, spacedim>(hex))
9462 cells_with_distorted_children.distorted_cells.push_back(
9463 hex);
9464
9465 // note that the refinement flag was already cleared
9466 // at the beginning of this loop
9467
9468 // inform all listeners that cell refinement is done
9469 triangulation.signals.post_refinement_on_cell(hex);
9470 }
9471 }
9472
9473 // clear user data on quads. we used some of this data to
9474 // indicate anisotropic refinemnt cases on faces. all data
9475 // should be cleared by now, but the information whether we
9476 // used indices or pointers is still present. reset it now to
9477 // enable the user to use whichever they like later on.
9478 triangulation.faces->quads.clear_user_data();
9479
9480 // return the list with distorted children
9481 return cells_with_distorted_children;
9482 }
9483
9484
9497 template <int spacedim>
9499 {}
9500
9501
9502
9503 template <int dim, int spacedim>
9504 static void
9507 {
9508 // If the codimension is one, we cannot perform this check
9509 // yet.
9510 if (spacedim > dim)
9511 return;
9512
9513 for (const auto &cell : triangulation.cell_iterators())
9514 if (cell->at_boundary() && cell->refine_flag_set() &&
9515 cell->refine_flag_set() !=
9517 {
9518 // The cell is at the boundary and it is flagged for
9519 // anisotropic refinement. Therefore, we have a closer
9520 // look
9521 const RefinementCase<dim> ref_case = cell->refine_flag_set();
9522 for (const unsigned int face_no :
9524 if (cell->face(face_no)->at_boundary())
9525 {
9526 // this is the critical face at the boundary.
9528 face_no) !=
9530 {
9531 // up to now, we do not want to refine this
9532 // cell along the face under consideration
9533 // here.
9534 const typename Triangulation<dim,
9535 spacedim>::face_iterator
9536 face = cell->face(face_no);
9537 // the new point on the boundary would be this
9538 // one.
9539 const Point<spacedim> new_bound = face->center(true);
9540 // to check it, transform to the unit cell
9541 // with a linear mapping
9542 const Point<dim> new_unit =
9543 cell->reference_cell()
9544 .template get_default_linear_mapping<dim,
9545 spacedim>()
9546 .transform_real_to_unit_cell(cell, new_bound);
9547
9548 // Now, we have to calculate the distance from
9549 // the face in the unit cell.
9550
9551 // take the correct coordinate direction (0
9552 // for faces 0 and 1, 1 for faces 2 and 3, 2
9553 // for faces 4 and 5) and subtract the correct
9554 // boundary value of the face (0 for faces 0,
9555 // 2, and 4; 1 for faces 1, 3 and 5)
9556 const double dist =
9557 std::fabs(new_unit[face_no / 2] - face_no % 2);
9558
9559 // compare this with the empirical value
9560 // allowed. if it is too big, flag the face
9561 // for isotropic refinement
9562 const double allowed = 0.25;
9563
9564 if (dist > allowed)
9565 cell->flag_for_face_refinement(face_no);
9566 } // if flagged for anistropic refinement
9567 } // if (cell->face(face)->at_boundary())
9568 } // for all cells
9569 }
9570
9571
9584 template <int dim, int spacedim>
9585 static void
9587 {
9588 Assert(dim < 3,
9589 ExcMessage("Wrong function called -- there should "
9590 "be a specialization."));
9591 }
9592
9593
9594 template <int spacedim>
9597 {
9598 const unsigned int dim = 3;
9599
9600 // first clear flags on lines, since we need them to determine
9601 // which lines will be refined
9602 triangulation.clear_user_flags_line();
9603
9604 // also clear flags on hexes, since we need them to mark those
9605 // cells which are to be coarsened
9606 triangulation.clear_user_flags_hex();
9607
9608 // variable to store whether the mesh was changed in the
9609 // present loop and in the whole process
9610 bool mesh_changed = false;
9611
9612 do
9613 {
9614 mesh_changed = false;
9615
9616 // for this following, we need to know which cells are
9617 // going to be coarsened, if we had to make a
9618 // decision. the following function sets these flags:
9619 triangulation.fix_coarsen_flags();
9620
9621
9622 // flag those lines that are refined and will not be
9623 // coarsened and those that will be refined
9624 for (const auto &cell : triangulation.cell_iterators())
9625 if (cell->refine_flag_set())
9626 {
9627 for (unsigned int line = 0; line < cell->n_lines(); ++line)
9629 cell->refine_flag_set(), line) ==
9631 // flag a line, that will be
9632 // refined
9633 cell->line(line)->set_user_flag();
9634 }
9635 else if (cell->has_children() &&
9636 !cell->child(0)->coarsen_flag_set())
9637 {
9638 for (unsigned int line = 0;
9639 line < GeometryInfo<dim>::lines_per_cell;
9640 ++line)
9642 cell->refinement_case(), line) ==
9644 // flag a line, that is refined
9645 // and will stay so
9646 cell->line(line)->set_user_flag();
9647 }
9648 else if (cell->has_children() &&
9649 cell->child(0)->coarsen_flag_set())
9650 cell->set_user_flag();
9651
9652
9653 // now check whether there are cells with lines that are
9654 // more than once refined or that will be more than once
9655 // refined. The first thing should never be the case, in
9656 // the second case we flag the cell for refinement
9658 cell = triangulation.last_active();
9659 cell != triangulation.end();
9660 --cell)
9661 for (unsigned int line = 0; line < cell->n_lines(); ++line)
9662 {
9663 if (cell->line(line)->has_children())
9664 {
9665 // if this line is refined, its children should
9666 // not have further children
9667 //
9668 // however, if any of the children is flagged
9669 // for further refinement, we need to refine
9670 // this cell also (at least, if the cell is not
9671 // already flagged)
9672 bool offending_line_found = false;
9673
9674 for (unsigned int c = 0; c < 2; ++c)
9675 {
9676 Assert(cell->line(line)->child(c)->has_children() ==
9677 false,
9679
9680 if (cell->line(line)->child(c)->user_flag_set() &&
9682 cell->refine_flag_set(), line) ==
9684 {
9685 // tag this cell for refinement
9686 cell->clear_coarsen_flag();
9687 // if anisotropic coarsening is allowed:
9688 // extend the refine_flag in the needed
9689 // direction, else set refine_flag
9690 // (isotropic)
9691 if (triangulation.smooth_grid &
9693 allow_anisotropic_smoothing)
9694 cell->flag_for_line_refinement(line);
9695 else
9696 cell->set_refine_flag();
9697
9698 for (unsigned int l = 0;
9699 l < GeometryInfo<dim>::lines_per_cell;
9700 ++l)
9702 cell->refine_flag_set(), line) ==
9704 // flag a line, that will be refined
9705 cell->line(l)->set_user_flag();
9706
9707 // note that we have changed the grid
9708 offending_line_found = true;
9709
9710 // it may save us several loop
9711 // iterations if we flag all lines of
9712 // this cell now (and not at the outset
9713 // of the next iteration) for refinement
9714 for (unsigned int l = 0;
9715 l < GeometryInfo<dim>::lines_per_cell;
9716 ++l)
9717 if (!cell->line(l)->has_children() &&
9719 cell->refine_flag_set(), l) !=
9721 cell->line(l)->set_user_flag();
9722
9723 break;
9724 }
9725 }
9726
9727 if (offending_line_found)
9728 {
9729 mesh_changed = true;
9730 break;
9731 }
9732 }
9733 }
9734
9735
9736 // there is another thing here: if any of the lines will
9737 // be refined, then we may not coarsen the present cell
9738 // similarly, if any of the lines *is* already refined, we
9739 // may not coarsen the current cell. however, there's a
9740 // catch: if the line is refined, but the cell behind it
9741 // is going to be coarsened, then the situation
9742 // changes. if we forget this second condition, the
9743 // refine_and_coarsen_3d test will start to fail. note
9744 // that to know which cells are going to be coarsened, the
9745 // call for fix_coarsen_flags above is necessary
9747 triangulation.last();
9748 cell != triangulation.end();
9749 --cell)
9750 {
9751 if (cell->user_flag_set())
9752 for (unsigned int line = 0;
9753 line < GeometryInfo<dim>::lines_per_cell;
9754 ++line)
9755 if (cell->line(line)->has_children() &&
9756 (cell->line(line)->child(0)->user_flag_set() ||
9757 cell->line(line)->child(1)->user_flag_set()))
9758 {
9759 for (unsigned int c = 0; c < cell->n_children(); ++c)
9760 cell->child(c)->clear_coarsen_flag();
9761 cell->clear_user_flag();
9762 for (unsigned int l = 0;
9763 l < GeometryInfo<dim>::lines_per_cell;
9764 ++l)
9766 cell->refinement_case(), l) ==
9768 // flag a line, that is refined
9769 // and will stay so
9770 cell->line(l)->set_user_flag();
9771 mesh_changed = true;
9772 break;
9773 }
9774 }
9775 }
9776 while (mesh_changed == true);
9777 }
9778
9779
9780
9787 template <int dim, int spacedim>
9788 static bool
9791 {
9792 // in 1d, coarsening is always allowed since we don't enforce
9793 // the 2:1 constraint there
9794 if (dim == 1)
9795 return true;
9796
9797 const RefinementCase<dim> ref_case = cell->refinement_case();
9798 for (unsigned int n : GeometryInfo<dim>::face_indices())
9799 {
9800 // if the cell is not refined along that face, coarsening
9801 // will not change anything, so do nothing. the same
9802 // applies, if the face is at the boandary
9803 const RefinementCase<dim - 1> face_ref_case =
9804 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
9805 n);
9806
9807 const unsigned int n_subfaces =
9808 GeometryInfo<dim - 1>::n_children(face_ref_case);
9809
9810 if (n_subfaces == 0 || cell->at_boundary(n))
9811 continue;
9812 for (unsigned int c = 0; c < n_subfaces; ++c)
9813 {
9815 child = cell->child(
9817
9819 child_neighbor = child->neighbor(n);
9820 if (!child->neighbor_is_coarser(n))
9821 // in 2d, if the child's neighbor is coarser, then
9822 // it has no children. however, in 3d it might be
9823 // otherwise. consider for example, that our face
9824 // might be refined with cut_x, but the neighbor is
9825 // refined with cut_xy at that face. then the
9826 // neighbor pointers of the children of our cell
9827 // will point to the common neighbor cell, not to
9828 // its children. what we really want to know in the
9829 // following is, whether the neighbor cell is
9830 // refined twice with reference to our cell. that
9831 // only has to be asked, if the child's neighbor is
9832 // not a coarser one.
9833 if ((child_neighbor->has_children() &&
9834 !child_neighbor->user_flag_set()) ||
9835 // neighbor has children, which are further
9836 // refined along the face, otherwise something
9837 // went wrong in the construction of neighbor
9838 // pointers. then only allow coarsening if this
9839 // neighbor will be coarsened as well
9840 // (user_pointer is set). the same applies, if
9841 // the neighbors children are not refined but
9842 // will be after refinement
9843 child_neighbor->refine_flag_set())
9844 return false;
9845 }
9846 }
9847 return true;
9848 }
9849 };
9850
9851
9856 {
9857 template <int spacedim>
9859 {}
9860
9861 template <int dim, int spacedim>
9863 {
9864 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
9865 2 * triangulation.n_raw_faces(),
9866 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
9867
9868 const auto set_entry = [&](const auto &face_index, const auto &cell) {
9869 const std::pair<unsigned int, unsigned int> cell_pair = {
9870 cell->level(), cell->index()};
9871 unsigned int index;
9872
9873 if (adjacent_cells[2 * face_index].first ==
9875 adjacent_cells[2 * face_index].second ==
9877 {
9878 index = 2 * face_index + 0;
9879 }
9880 else
9881 {
9882 Assert(((adjacent_cells[2 * face_index + 1].first ==
9884 (adjacent_cells[2 * face_index + 1].second ==
9887 index = 2 * face_index + 1;
9888 }
9889
9890 adjacent_cells[index] = cell_pair;
9891 };
9892
9893 const auto get_entry =
9894 [&](const auto &face_index,
9895 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
9896 auto test = adjacent_cells[2 * face_index];
9897
9898 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
9899 cell->index()))
9900 test = adjacent_cells[2 * face_index + 1];
9901
9902 if ((test.first != numbers::invalid_unsigned_int) &&
9903 (test.second != numbers::invalid_unsigned_int))
9905 test.first,
9906 test.second);
9907 else
9909 };
9910
9911 for (const auto &cell : triangulation.cell_iterators())
9912 for (const auto &face : cell->face_iterators())
9913 {
9914 set_entry(face->index(), cell);
9915
9916 if (cell->is_active() && face->has_children())
9917 for (unsigned int c = 0; c < face->n_children(); ++c)
9918 set_entry(face->child(c)->index(), cell);
9919 }
9920
9921 for (const auto &cell : triangulation.cell_iterators())
9922 for (auto f : cell->face_indices())
9923 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
9924 }
9925
9926 template <int dim, int spacedim>
9927 static void
9931 std::vector<unsigned int> & line_cell_count,
9932 std::vector<unsigned int> & quad_cell_count)
9933 {
9935 (void)triangulation;
9936 (void)cell;
9937 (void)line_cell_count;
9938 (void)quad_cell_count;
9939 }
9940
9941 template <int dim, int spacedim>
9944 const bool check_for_distorted_cells)
9945 {
9947 triangulation, check_for_distorted_cells);
9948 }
9949
9950 template <int dim, int spacedim>
9951 static void
9954 {
9955 // nothing to do since anisotropy is not supported
9956 (void)triangulation;
9957 }
9958
9959 template <int dim, int spacedim>
9960 static void
9963 {
9965 }
9966
9967 template <int dim, int spacedim>
9968 static bool
9971 {
9973 (void)cell;
9974
9975 return false;
9976 }
9977 };
9978
9979
9980 template <int dim, int spacedim>
9983 {
9984 static const FlatManifold<dim, spacedim> flat_manifold;
9985 return flat_manifold;
9986 }
9987 } // namespace TriangulationImplementation
9988} // namespace internal
9989
9990
9991
9992template <int dim, int spacedim>
9994
9995
9996
9997template <int dim, int spacedim>
9999 const MeshSmoothing smooth_grid,
10000 const bool check_for_distorted_cells)
10001 : smooth_grid(smooth_grid)
10002 , anisotropic_refinement(false)
10003 , check_for_distorted_cells(check_for_distorted_cells)
10004{
10005 if (dim == 1)
10006 {
10007 vertex_to_boundary_id_map_1d =
10008 std::make_unique<std::map<unsigned int, types::boundary_id>>();
10009 vertex_to_manifold_id_map_1d =
10010 std::make_unique<std::map<unsigned int, types::manifold_id>>();
10011 }
10012
10013 // connect the any_change signal to the other top level signals
10014 signals.create.connect(signals.any_change);
10015 signals.post_refinement.connect(signals.any_change);
10016 signals.clear.connect(signals.any_change);
10017 signals.mesh_movement.connect(signals.any_change);
10018}
10019
10020
10021
10022template <int dim, int spacedim>
10024 Triangulation<dim, spacedim> &&tria) noexcept
10025 : Subscriptor(std::move(tria))
10026 , smooth_grid(tria.smooth_grid)
10027 , reference_cells(std::move(tria.reference_cells))
10028 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
10029 , periodic_face_map(std::move(tria.periodic_face_map))
10030 , levels(std::move(tria.levels))
10031 , faces(std::move(tria.faces))
10032 , vertices(std::move(tria.vertices))
10033 , vertices_used(std::move(tria.vertices_used))
10034 , manifold(std::move(tria.manifold))
10035 , anisotropic_refinement(tria.anisotropic_refinement)
10036 , check_for_distorted_cells(tria.check_for_distorted_cells)
10037 , number_cache(std::move(tria.number_cache))
10038 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
10039 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
10040{
10042
10043 if (tria.policy)
10044 this->policy = tria.policy->clone();
10045}
10046
10047
10048template <int dim, int spacedim>
10052{
10053 Subscriptor::operator=(std::move(tria));
10054
10055 smooth_grid = tria.smooth_grid;
10056 reference_cells = std::move(tria.reference_cells);
10057 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
10058 periodic_face_map = std::move(tria.periodic_face_map);
10059 levels = std::move(tria.levels);
10060 faces = std::move(tria.faces);
10061 vertices = std::move(tria.vertices);
10062 vertices_used = std::move(tria.vertices_used);
10063 manifold = std::move(tria.manifold);
10064 anisotropic_refinement = tria.anisotropic_refinement;
10065 number_cache = tria.number_cache;
10066 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
10067 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
10068
10070
10071 if (tria.policy)
10072 this->policy = tria.policy->clone();
10073
10074 return *this;
10075}
10076
10077
10078
10079template <int dim, int spacedim>
10081{
10082 // notify listeners that the triangulation is going down...
10083 try
10084 {
10085 signals.clear();
10086 }
10087 catch (...)
10088 {}
10089
10090 levels.clear();
10091
10092 // the vertex_to_boundary_id_map_1d field should be unused except in
10093 // 1d. double check this here, as destruction is a good place to
10094 // ensure that what we've done over the course of the lifetime of
10095 // this object makes sense
10096 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
10098
10099 // the vertex_to_manifold_id_map_1d field should be also unused
10100 // except in 1d. check this as well
10101 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
10103}
10104
10105
10106
10107template <int dim, int spacedim>
10108void
10110{
10111 // notify listeners that the triangulation is going down...
10112 signals.clear();
10113
10114 // ...and then actually clear all content of it
10115 clear_despite_subscriptions();
10116 periodic_face_pairs_level_0.clear();
10117 periodic_face_map.clear();
10118 reference_cells.clear();
10119}
10120
10121
10122template <int dim, int spacedim>
10125{
10126 return MPI_COMM_SELF;
10127}
10128
10129
10130
10131template <int dim, int spacedim>
10132void
10134 const MeshSmoothing mesh_smoothing)
10135{
10136 Assert(n_levels() == 0,
10137 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
10138 smooth_grid = mesh_smoothing;
10139}
10140
10141
10142
10143template <int dim, int spacedim>
10146{
10147 return smooth_grid;
10148}
10149
10150
10151
10152template <int dim, int spacedim>
10153void
10155 const types::manifold_id m_number,
10156 const Manifold<dim, spacedim> &manifold_object)
10157{
10159
10160 manifold[m_number] = manifold_object.clone();
10161}
10162
10163
10164
10165template <int dim, int spacedim>
10166void
10168{
10170
10171 // delete the entry located at number.
10172 manifold.erase(m_number);
10173}
10174
10175
10176template <int dim, int spacedim>
10177void
10179{
10180 manifold.clear();
10181}
10182
10183
10184template <int dim, int spacedim>
10185void
10187 const types::manifold_id m_number)
10188{
10189 Assert(
10190 n_cells() > 0,
10191 ExcMessage(
10192 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
10193
10194 for (const auto &cell : this->active_cell_iterators())
10195 cell->set_all_manifold_ids(m_number);
10196}
10197
10198
10199template <int dim, int spacedim>
10200void
10202 const types::manifold_id m_number)
10203{
10204 Assert(
10205 n_cells() > 0,
10206 ExcMessage(
10207 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
10208
10209 for (const auto &cell : this->active_cell_iterators())
10210 for (auto f : GeometryInfo<dim>::face_indices())
10211 if (cell->face(f)->at_boundary())
10212 cell->face(f)->set_all_manifold_ids(m_number);
10213}
10214
10215
10216template <int dim, int spacedim>
10217void
10219 const types::boundary_id b_id,
10220 const types::manifold_id m_number)
10221{
10222 Assert(
10223 n_cells() > 0,
10224 ExcMessage(
10225 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
10226
10227 bool boundary_found = false;
10228
10229 for (const auto &cell : this->active_cell_iterators())
10230 {
10231 // loop on faces
10232 for (auto f : GeometryInfo<dim>::face_indices())
10233 if (cell->face(f)->at_boundary() &&
10234 cell->face(f)->boundary_id() == b_id)
10235 {
10236 boundary_found = true;
10237 cell->face(f)->set_manifold_id(m_number);
10238 }
10239
10240 // loop on edges if dim >= 3
10241 if (dim >= 3)
10242 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
10243 if (cell->line(e)->at_boundary() &&
10244 cell->line(e)->boundary_id() == b_id)
10245 {
10246 boundary_found = true;
10247 cell->line(e)->set_manifold_id(m_number);
10248 }
10249 }
10250
10251 (void)boundary_found;
10252 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
10253}
10254
10255
10256
10257template <int dim, int spacedim>
10260 const types::manifold_id m_number) const
10261{
10262 // look, if there is a manifold stored at
10263 // manifold_id number.
10264 const auto it = manifold.find(m_number);
10265
10266 if (it != manifold.end())
10267 {
10268 // if we have found an entry, return it
10269 return *(it->second);
10270 }
10271
10272 // if we have not found an entry connected with number, we return
10273 // the default (flat) manifold
10274 return internal::TriangulationImplementation::
10275 get_default_flat_manifold<dim, spacedim>();
10276}
10277
10278
10279
10280template <int dim, int spacedim>
10281std::vector<types::boundary_id>
10283{
10284 // in 1d, we store a map of all used boundary indicators. use it for
10285 // our purposes
10286 if (dim == 1)
10287 {
10288 std::vector<types::boundary_id> boundary_ids;
10289 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
10290 vertex_to_boundary_id_map_1d->begin();
10291 p != vertex_to_boundary_id_map_1d->end();
10292 ++p)
10293 boundary_ids.push_back(p->second);
10294
10295 return boundary_ids;
10296 }
10297 else
10298 {
10299 std::set<types::boundary_id> b_ids;
10300 for (auto cell : active_cell_iterators())
10301 if (cell->is_locally_owned())
10302 for (const unsigned int face : cell->face_indices())
10303 if (cell->at_boundary(face))
10304 b_ids.insert(cell->face(face)->boundary_id());
10305 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
10306 return boundary_ids;
10307 }
10308}
10309
10310
10311
10312template <int dim, int spacedim>
10313std::vector<types::manifold_id>
10315{
10316 std::set<types::manifold_id> m_ids;
10317 for (auto cell : active_cell_iterators())
10318 if (cell->is_locally_owned())
10319 {
10320 m_ids.insert(cell->manifold_id());
10321 for (const auto &face : cell->face_iterators())
10322 m_ids.insert(face->manifold_id());
10323 if (dim == 3)
10324 for (const unsigned int l : cell->line_indices())
10325 m_ids.insert(cell->line(l)->manifold_id());
10326 }
10327 return {m_ids.begin(), m_ids.end()};
10328}
10329
10330/*-----------------------------------------------------------------*/
10331
10332
10333template <int dim, int spacedim>
10334void
10336 const Triangulation<dim, spacedim> &other_tria)
10337{
10338 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
10339 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
10340 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
10341 (dim == 1 || other_tria.faces != nullptr),
10342 ExcMessage(
10343 "When calling Triangulation::copy_triangulation(), "
10344 "the target triangulation must be empty but the source "
10345 "triangulation (the argument to this function) must contain "
10346 "something. Here, it seems like the source does not "
10347 "contain anything at all."));
10348
10349
10350 // copy normal elements
10351 vertices = other_tria.vertices;
10352 vertices_used = other_tria.vertices_used;
10353 anisotropic_refinement = other_tria.anisotropic_refinement;
10354 smooth_grid = other_tria.smooth_grid;
10355 reference_cells = other_tria.reference_cells;
10356
10357 if (dim > 1)
10358 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
10359 *other_tria.faces);
10360
10361 for (const auto &p : other_tria.manifold)
10362 set_manifold(p.first, *p.second);
10363
10364
10365 levels.reserve(other_tria.levels.size());
10366 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
10367 levels.push_back(
10368 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
10369 *other_tria.levels[level]));
10370
10371 number_cache = other_tria.number_cache;
10372
10373 if (dim == 1)
10374 {
10375 vertex_to_boundary_id_map_1d =
10376 std::make_unique<std::map<unsigned int, types::boundary_id>>(
10377 *other_tria.vertex_to_boundary_id_map_1d);
10378
10379 vertex_to_manifold_id_map_1d =
10380 std::make_unique<std::map<unsigned int, types::manifold_id>>(
10381 *other_tria.vertex_to_manifold_id_map_1d);
10382 }
10383
10384 if (other_tria.policy)
10385 this->policy = other_tria.policy->clone();
10386
10387 // inform those who are listening on other_tria of the copy operation
10388 other_tria.signals.copy(*this);
10389 // also inform all listeners of the current triangulation that the
10390 // triangulation has been created
10391 signals.create();
10392
10393 // note that we need not copy the
10394 // subscriptor!
10395}
10396
10397
10398
10399template <int dim, int spacedim>
10400void
10402 const std::vector<Point<spacedim>> &v,
10403 const std::vector<CellData<dim>> & cells,
10404 const SubCellData & subcelldata)
10405{
10406 std::vector<CellData<dim>> reordered_cells(cells); // NOLINT
10407 SubCellData reordered_subcelldata(subcelldata); // NOLINT
10408
10409 // in-place reordering of data
10410 reorder_compatibility(reordered_cells, reordered_subcelldata);
10411
10412 // now create triangulation from
10413 // reordered data
10414 create_triangulation(v, reordered_cells, reordered_subcelldata);
10415}
10416
10417
10418template <int dim, int spacedim>
10419void
10421{
10422 this->update_reference_cells();
10423
10424 if (this->all_reference_cells_are_hyper_cube())
10425 {
10426 this->policy =
10428 dim,
10429 spacedim,
10431 }
10432 else
10433 {
10434 this->policy =
10436 dim,
10437 spacedim,
10439 }
10440}
10441
10442
10443
10444template <int dim, int spacedim>
10445void
10447 const std::vector<Point<spacedim>> &v,
10448 const std::vector<CellData<dim>> & cells,
10449 const SubCellData & subcelldata)
10450{
10451 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
10452 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
10453 // check that no forbidden arrays
10454 // are used
10455 Assert(subcelldata.check_consistency(dim), ExcInternalError());
10456
10457 // try to create a triangulation; if this fails, we still want to
10458 // throw an exception but if we just do so we'll get into trouble
10459 // because sometimes other objects are already attached to it:
10460 try
10461 {
10463 create_triangulation(v, cells, subcelldata, *this);
10464 }
10465 catch (...)
10466 {
10467 clear_despite_subscriptions();
10468 throw;
10469 }
10470
10471 reset_policy();
10472
10473 // update our counts of the various elements of a triangulation, and set
10474 // active_cell_indices of all cells
10475 reset_cell_vertex_indices_cache();
10477 *this, levels.size(), number_cache);
10478 reset_active_cell_indices();
10479 reset_global_cell_indices();
10480
10481 // now verify that there are indeed no distorted cells. as per the
10482 // documentation of this class, we first collect all distorted cells
10483 // and then throw an exception if there are any
10484 if (check_for_distorted_cells)
10485 {
10486 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
10487 // throw the array (and fill the various location fields) if
10488 // there are distorted cells. otherwise, just fall off the end
10489 // of the function
10490 AssertThrow(distorted_cells.distorted_cells.size() == 0, distorted_cells);
10491 }
10492
10493
10494 /*
10495 When the triangulation is a manifold (dim < spacedim), the normal field
10496 provided from the map class depends on the order of the vertices.
10497 It may happen that this normal field is discontinuous.
10498 The following code takes care that this is not the case by setting the
10499 cell direction flag on those cell that produce the wrong orientation.
10500
10501 To determine if 2 neighbours have the same or opposite orientation
10502 we use a table of truth.
10503 Its entries are indexes by the local indices of the common face.
10504 For example if two elements share a face, and this face is
10505 face 0 for element 0 and face 1 for element 1, then
10506 table(0,1) will tell whether the orientation are the same (true) or
10507 opposite (false).
10508
10509 Even though there may be a combinatorial/graph theory argument to get
10510 this table in any dimension, I tested by hand all the different possible
10511 cases in 1D and 2D to generate the table.
10512
10513 Assuming that a surface respects the standard orientation for 2d meshes,
10514 the tables of truth are symmetric and their true values are the following
10515 1D curves: (0,1)
10516 2D surface: (0,1),(0,2),(1,3),(2,3)
10517
10518 We store this data using an n_faces x n_faces full matrix, which is
10519 actually much bigger than the minimal data required, but it makes the code
10520 more readable.
10521
10522 */
10523 if (dim < spacedim)
10524 {
10527 switch (dim)
10528 {
10529 case 1:
10530 {
10531 bool values[][2] = {{false, true}, {true, false}};
10532 for (const unsigned int i : GeometryInfo<dim>::face_indices())
10533 for (const unsigned int j : GeometryInfo<dim>::face_indices())
10534 correct(i, j) = (values[i][j]);
10535 break;
10536 }
10537 case 2:
10538 {
10539 bool values[][4] = {{false, true, true, false},
10540 {true, false, false, true},
10541 {true, false, false, true},
10542 {false, true, true, false}};
10543 for (const unsigned int i : GeometryInfo<dim>::face_indices())
10544 for (const unsigned int j : GeometryInfo<dim>::face_indices())
10545 correct(i, j) = (values[i][j]);
10546 break;
10547 }
10548 default:
10549 Assert(false, ExcNotImplemented());
10550 }
10551
10552
10553 std::list<active_cell_iterator> this_round, next_round;
10554 active_cell_iterator neighbor;
10555
10556 this_round.push_back(begin_active());
10557 begin_active()->set_direction_flag(true);
10558 begin_active()->set_user_flag();
10559
10560 while (this_round.size() > 0)
10561 {
10562 for (typename std::list<active_cell_iterator>::iterator cell =
10563 this_round.begin();
10564 cell != this_round.end();
10565 ++cell)
10566 {
10567 for (const unsigned int i : (*cell)->face_indices())
10568 {
10569 if (!((*cell)->face(i)->at_boundary()))
10570 {
10571 neighbor = (*cell)->neighbor(i);
10572
10573 unsigned int cf = (*cell)->face_index(i);
10574 unsigned int j = 0;
10575 while (neighbor->face_index(j) != cf)
10576 {
10577 ++j;
10578 }
10579
10580
10581 // If we already saw this guy, check that everything is
10582 // fine
10583 if (neighbor->user_flag_set())
10584 {
10585 // If we have visited this guy, then the ordering and
10586 // the orientation should agree
10587 Assert(!(correct(i, j) ^
10588 (neighbor->direction_flag() ==
10589 (*cell)->direction_flag())),
10590 ExcNonOrientableTriangulation());
10591 }
10592 else
10593 {
10594 next_round.push_back(neighbor);
10595 neighbor->set_user_flag();
10596 if ((correct(i, j) ^ (neighbor->direction_flag() ==
10597 (*cell)->direction_flag())))
10598 neighbor->set_direction_flag(
10599 !neighbor->direction_flag());
10600 }
10601 }
10602 }
10603 }
10604
10605 // Before we quit let's check
10606 // that if the triangulation
10607 // is disconnected that we
10608 // still get all cells
10609 if (next_round.size() == 0)
10610 for (const auto &cell : this->active_cell_iterators())
10611 if (cell->user_flag_set() == false)
10612 {
10613 next_round.push_back(cell);
10614 cell->set_direction_flag(true);
10615 cell->set_user_flag();
10616 break;
10617 }
10618
10619 this_round = next_round;
10620 next_round.clear();
10621 }
10622 }
10623
10624 // inform all listeners that the triangulation has been created
10625 signals.create();
10626}
10627
10628
10629
10630template <int dim, int spacedim>
10631void
10634{
10635 // 1) create coarse grid
10637 construction_data.coarse_cells,
10638 SubCellData());
10639
10640 // create a copy of cell_infos such that we can sort them
10641 auto cell_infos = construction_data.cell_infos;
10642
10643 // sort cell_infos on each level separately
10644 for (auto &cell_info : cell_infos)
10645 std::sort(
10646 cell_info.begin(),
10647 cell_info.end(),
10650 const CellId a_id(a.id);
10651 const CellId b_id(b.id);
10652
10653 const auto a_coarse_cell_index =
10654 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
10655 const auto b_coarse_cell_index =
10656 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
10657
10658 // according to their coarse-cell index and if that is
10659 // same according to their cell id (the result is that
10660 // cells on each level are sorted according to their
10661 // index on that level - what we need in the following
10662 // operations)
10663 if (a_coarse_cell_index != b_coarse_cell_index)
10664 return a_coarse_cell_index < b_coarse_cell_index;
10665 else
10666 return a_id < b_id;
10667 });
10668
10669 // 2) create all levels via a sequence of refinements. note that
10670 // we must make sure that we actually have cells on this level,
10671 // which is not clear in a parallel context for some processes
10672 for (unsigned int level = 0;
10673 level < cell_infos.size() && !cell_infos[level].empty();
10674 ++level)
10675 {
10676 // a) set manifold ids here (because new vertices have to be
10677 // positioned correctly during each refinement step)
10678 {
10679 auto cell = this->begin(level);
10680 auto cell_info = cell_infos[level].begin();
10681 for (; cell_info != cell_infos[level].end(); ++cell_info)
10682 {
10683 while (cell_info->id != cell->id().template to_binary<dim>())
10684 ++cell;
10685 if (dim == 3)
10686 for (const auto quad : cell->face_indices())
10687 cell->quad(quad)->set_manifold_id(
10688 cell_info->manifold_quad_ids[quad]);
10689
10690 if (dim >= 2)
10691 for (const auto line : cell->line_indices())
10692 cell->line(line)->set_manifold_id(
10693 cell_info->manifold_line_ids[line]);
10694
10695 cell->set_manifold_id(cell_info->manifold_id);
10696 }
10697 }
10698
10699 // b) perform refinement on all levels but on the finest
10700 if (level + 1 != cell_infos.size())
10701 {
10702 // find cells that should have children and mark them for
10703 // refinement
10704 auto coarse_cell = this->begin(level);
10705 auto fine_cell_info = cell_infos[level + 1].begin();
10706
10707 // loop over all cells on the next level
10708 for (; fine_cell_info != cell_infos[level + 1].end();
10709 ++fine_cell_info)
10710 {
10711 // find the parent of that cell
10712 while (
10713 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
10714 ++coarse_cell;
10715
10716 // set parent for refinement
10717 coarse_cell->set_refine_flag();
10718 }
10719
10720 // execute refinement
10721 ::Triangulation<dim,
10722 spacedim>::execute_coarsening_and_refinement();
10723 }
10724 }
10725
10726 // 3) set boundary ids
10727 for (unsigned int level = 0;
10728 level < cell_infos.size() && !cell_infos[level].empty();
10729 ++level)
10730 {
10731 auto cell = this->begin(level);
10732 auto cell_info = cell_infos[level].begin();
10733 for (; cell_info != cell_infos[level].end(); ++cell_info)
10734 {
10735 // find cell that has the correct cell
10736 while (cell_info->id != cell->id().template to_binary<dim>())
10737 ++cell;
10738
10739 // boundary ids
10740 for (auto pair : cell_info->boundary_ids)
10741 {
10742 Assert(cell->at_boundary(pair.first),
10743 ExcMessage("Cell face is not on the boundary!"));
10744 cell->face(pair.first)->set_boundary_id(pair.second);
10745 }
10746 }
10747 }
10748}
10749
10750
10751template <int dim, int spacedim>
10752void
10754{
10755 AssertThrow(dim + 1 == spacedim,
10756 ExcMessage("Only works for dim == spacedim-1"));
10757 for (const auto &cell : this->active_cell_iterators())
10758 cell->set_direction_flag(!cell->direction_flag());
10759}
10760
10761
10762
10763template <int dim, int spacedim>
10764void
10766{
10767 Assert(n_cells() > 0,
10768 ExcMessage("Error: An empty Triangulation can not be refined."));
10769
10770 for (const auto &cell : this->active_cell_iterators())
10771 {
10772 cell->clear_coarsen_flag();
10773 cell->set_refine_flag();
10774 }
10775}
10776
10777
10778
10779template <int dim, int spacedim>
10780void
10781Triangulation<dim, spacedim>::refine_global(const unsigned int times)
10782{
10783 for (unsigned int i = 0; i < times; ++i)
10784 {
10785 set_all_refine_flags();
10786 execute_coarsening_and_refinement();
10787 }
10788}
10789
10790
10791
10792template <int dim, int spacedim>
10793void
10794Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
10795{
10796 for (unsigned int i = 0; i < times; ++i)
10797 {
10798 for (const auto &cell : this->active_cell_iterators())
10799 {
10800 cell->clear_refine_flag();
10801 cell->set_coarsen_flag();
10802 }
10803 execute_coarsening_and_refinement();
10804 }
10805}
10806
10807
10808/*-------------------- refine/coarsen flags -------------------------*/
10809
10810
10811
10812template <int dim, int spacedim>
10813void
10814Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
10815{
10816 v.resize(dim * n_active_cells(), false);
10817 std::vector<bool>::iterator i = v.begin();
10818
10819 for (const auto &cell : this->active_cell_iterators())
10820 for (unsigned int j = 0; j < dim; ++j, ++i)
10821 if (cell->refine_flag_set() & (1 << j))
10822 *i = true;
10823
10824 Assert(i == v.end(), ExcInternalError());
10825}
10826
10827
10828
10829template <int dim, int spacedim>
10830void
10832{
10833 std::vector<bool> v;
10834 save_refine_flags(v);
10835 write_bool_vector(mn_tria_refine_flags_begin,
10836 v,
10838 out);
10839}
10840
10841
10842
10843template <int dim, int spacedim>
10844void
10846{
10847 std::vector<bool> v;
10848 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
10849 load_refine_flags(v);
10850}
10851
10852
10853
10854template <int dim, int spacedim>
10855void
10856Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
10857{
10858 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
10859
10860 std::vector<bool>::const_iterator i = v.begin();
10861 for (const auto &cell : this->active_cell_iterators())
10862 {
10863 unsigned int ref_case = 0;
10864
10865 for (unsigned int j = 0; j < dim; ++j, ++i)
10866 if (*i == true)
10867 ref_case += 1 << j;
10869 ExcGridReadError());
10870 if (ref_case > 0)
10871 cell->set_refine_flag(RefinementCase<dim>(ref_case));
10872 else
10873 cell->clear_refine_flag();
10874 }
10875
10876 Assert(i == v.end(), ExcInternalError());
10877}
10878
10879
10880
10881template <int dim, int spacedim>
10882void
10883Triangulation<dim, spacedim>::save_coarsen_flags(std::vector<bool> &v) const
10884{
10885 v.resize(n_active_cells(), false);
10886 std::vector<bool>::iterator i = v.begin();
10887 for (const auto &cell : this->active_cell_iterators())
10888 {
10889 *i = cell->coarsen_flag_set();
10890 ++i;
10891 }
10892
10893 Assert(i == v.end(), ExcInternalError());
10894}
10895
10896
10897
10898template <int dim, int spacedim>
10899void
10901{
10902 std::vector<bool> v;
10903 save_coarsen_flags(v);
10904 write_bool_vector(mn_tria_coarsen_flags_begin,
10905 v,
10907 out);
10908}
10909
10910
10911
10912template <int dim, int spacedim>
10913void
10915{
10916 std::vector<bool> v;
10917 read_bool_vector(mn_tria_coarsen_flags_begin,
10918 v,
10920 in);
10921 load_coarsen_flags(v);
10922}
10923
10924
10925
10926template <int dim, int spacedim>
10927void
10928Triangulation<dim, spacedim>::load_coarsen_flags(const std::vector<bool> &v)
10929{
10930 Assert(v.size() == n_active_cells(), ExcGridReadError());
10931
10932 std::vector<bool>::const_iterator i = v.begin();
10933 for (const auto &cell : this->active_cell_iterators())
10934 {
10935 if (*i == true)
10936 cell->set_coarsen_flag();
10937 else
10938 cell->clear_coarsen_flag();
10939 ++i;
10940 }
10941
10942 Assert(i == v.end(), ExcInternalError());
10943}
10944
10945
10946template <int dim, int spacedim>
10947bool
10949{
10950 return anisotropic_refinement;
10951}
10952
10953
10954
10955/*-------------------- user data/flags -------------------------*/
10956
10957
10958namespace
10959{
10960 // clear user data of cells
10961 void
10962 clear_user_data(std::vector<std::unique_ptr<
10964 {
10965 for (auto &level : levels)
10966 level->cells.clear_user_data();
10967 }
10968
10969
10970 // clear user data of faces
10971 void
10973 {
10974 if (faces->dim == 2)
10975 {
10976 faces->lines.clear_user_data();
10977 }
10978
10979
10980 if (faces->dim == 3)
10981 {
10982 faces->lines.clear_user_data();
10983 faces->quads.clear_user_data();
10984 }
10985 }
10986} // namespace
10987
10988
10989template <int dim, int spacedim>
10990void
10992{
10993 // let functions in anonymous namespace do their work
10994 ::clear_user_data(levels);
10995 ::clear_user_data(faces.get());
10996}
10997
10998
10999
11000namespace
11001{
11002 void
11003 clear_user_flags_line(
11004 unsigned int dim,
11005 std::vector<
11006 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
11007 & levels,
11009 {
11010 if (dim == 1)
11011 {
11012 for (const auto &level : levels)
11013 level->cells.clear_user_flags();
11014 }
11015 else if (dim == 2 || dim == 3)
11016 {
11017 faces->lines.clear_user_flags();
11018 }
11019 else
11020 {
11021 Assert(false, ExcNotImplemented())
11022 }
11023 }
11024} // namespace
11025
11026
11027template <int dim, int spacedim>
11028void
11030{
11031 ::clear_user_flags_line(dim, levels, faces.get());
11032}
11033
11034
11035
11036namespace
11037{
11038 void
11039 clear_user_flags_quad(
11040 unsigned int dim,
11041 std::vector<
11042 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
11043 & levels,
11045 {
11046 if (dim == 1)
11047 {
11048 // nothing to do in 1d
11049 }
11050 else if (dim == 2)
11051 {
11052 for (const auto &level : levels)
11053 level->cells.clear_user_flags();
11054 }
11055 else if (dim == 3)
11056 {
11057 faces->quads.clear_user_flags();
11058 }
11059 else
11060 {
11061 Assert(false, ExcNotImplemented())
11062 }
11063 }
11064} // namespace
11065
11066
11067template <int dim, int spacedim>
11068void
11070{
11071 ::clear_user_flags_quad(dim, levels, faces.get());
11072}
11073
11074
11075
11076namespace
11077{
11078 void
11079 clear_user_flags_hex(
11080 unsigned int dim,
11081 std::vector<
11082 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
11083 &levels,
11085 {
11086 if (dim == 1)
11087 {
11088 // nothing to do in 1d
11089 }
11090 else if (dim == 2)
11091 {
11092 // nothing to do in 2d
11093 }
11094 else if (dim == 3)
11095 {
11096 for (const auto &level : levels)
11097 level->cells.clear_user_flags();
11098 }
11099 else
11100 {
11101 Assert(false, ExcNotImplemented())
11102 }
11103 }
11104} // namespace
11105
11106
11107template <int dim, int spacedim>
11108void
11110{
11111 ::clear_user_flags_hex(dim, levels, faces.get());
11112}
11113
11114
11115
11116template <int dim, int spacedim>
11117void
11119{
11120 clear_user_flags_line();
11121 clear_user_flags_quad();
11122 clear_user_flags_hex();
11123}
11124
11125
11126
11127template <int dim, int spacedim>
11128void
11129Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
11130{
11131 save_user_flags_line(out);
11132
11133 if (dim >= 2)
11134 save_user_flags_quad(out);
11135
11136 if (dim >= 3)
11137 save_user_flags_hex(out);
11138
11139 if (dim >= 4)
11140 Assert(false, ExcNotImplemented());
11141}
11142
11143
11144
11145template <int dim, int spacedim>
11146void
11147Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
11148{
11149 // clear vector and append
11150 // all the stuff later on
11151 v.clear();
11152
11153 std::vector<bool> tmp;
11154
11155 save_user_flags_line(tmp);
11156 v.insert(v.end(), tmp.begin(), tmp.end());
11157
11158 if (dim >= 2)
11159 {
11160 save_user_flags_quad(tmp);
11161 v.insert(v.end(), tmp.begin(), tmp.end());
11162 }
11163
11164 if (dim >= 3)
11165 {
11166 save_user_flags_hex(tmp);
11167 v.insert(v.end(), tmp.begin(), tmp.end());
11168 }
11169
11170 if (dim >= 4)
11171 Assert(false, ExcNotImplemented());
11172}
11173
11174
11175
11176template <int dim, int spacedim>
11177void
11179{
11180 load_user_flags_line(in);
11181
11182 if (dim >= 2)
11183 load_user_flags_quad(in);
11184
11185 if (dim >= 3)
11186 load_user_flags_hex(in);
11187
11188 if (dim >= 4)
11189 Assert(false, ExcNotImplemented());
11190}
11191
11192
11193
11194template <int dim, int spacedim>
11195void
11196Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
11197{
11198 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
11199 std::vector<bool> tmp;
11200
11201 // first extract the flags
11202 // belonging to lines
11203 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
11204 // and set the lines
11205 load_user_flags_line(tmp);
11206
11207 if (dim >= 2)
11208 {
11209 tmp.clear();
11210 tmp.insert(tmp.end(),
11211 v.begin() + n_lines(),
11212 v.begin() + n_lines() + n_quads());
11213 load_user_flags_quad(tmp);
11214 }
11215
11216 if (dim >= 3)
11217 {
11218 tmp.clear();
11219 tmp.insert(tmp.end(),
11220 v.begin() + n_lines() + n_quads(),
11221 v.begin() + n_lines() + n_quads() + n_hexs());
11222 load_user_flags_hex(tmp);
11223 }
11224
11225 if (dim >= 4)
11226 Assert(false, ExcNotImplemented());
11227}
11228
11229
11230
11231template <int dim, int spacedim>
11232void
11234{
11235 v.resize(n_lines(), false);
11236 std::vector<bool>::iterator i = v.begin();
11237 line_iterator line = begin_line(), endl = end_line();
11238 for (; line != endl; ++line, ++i)
11239 *i = line->user_flag_set();
11240
11241 Assert(i == v.end(), ExcInternalError());
11242}
11243
11244
11245
11246template <int dim, int spacedim>
11247void
11249{
11250 std::vector<bool> v;
11251 save_user_flags_line(v);
11252 write_bool_vector(mn_tria_line_user_flags_begin,
11253 v,
11255 out);
11256}
11257
11258
11259
11260template <int dim, int spacedim>
11261void
11263{
11264 std::vector<bool> v;
11265 read_bool_vector(mn_tria_line_user_flags_begin,
11266 v,
11268 in);
11269 load_user_flags_line(v);
11270}
11271
11272
11273
11274template <int dim, int spacedim>
11275void
11277{
11278 Assert(v.size() == n_lines(), ExcGridReadError());
11279
11280 line_iterator line = begin_line(), endl = end_line();
11281 std::vector<bool>::const_iterator i = v.begin();
11282 for (; line != endl; ++line, ++i)
11283 if (*i == true)
11284 line->set_user_flag();
11285 else
11286 line->clear_user_flag();
11287
11288 Assert(i == v.end(), ExcInternalError());
11289}
11290
11291
11292namespace
11293{
11294 template <typename Iterator>
11295 bool
11296 get_user_flag(const Iterator &i)
11297 {
11298 return i->user_flag_set();
11299 }
11300
11301
11302
11303 template <int structdim, int dim, int spacedim>
11304 bool
11306 {
11307 Assert(false, ExcInternalError());
11308 return false;
11309 }
11310
11311
11312
11313 template <typename Iterator>
11314 void
11315 set_user_flag(const Iterator &i)
11316 {
11317 i->set_user_flag();
11318 }
11319
11320
11321
11322 template <int structdim, int dim, int spacedim>
11323 void
11325 {
11326 Assert(false, ExcInternalError());
11327 }
11328
11329
11330
11331 template <typename Iterator>
11332 void
11333 clear_user_flag(const Iterator &i)
11334 {
11335 i->clear_user_flag();
11336 }
11337
11338
11339
11340 template <int structdim, int dim, int spacedim>
11341 void
11342 clear_user_flag(
11344 {
11345 Assert(false, ExcInternalError());
11346 }
11347} // namespace
11348
11349
11350template <int dim, int spacedim>
11351void
11353{
11354 v.resize(n_quads(), false);
11355
11356 if (dim >= 2)
11357 {
11358 std::vector<bool>::iterator i = v.begin();
11359 quad_iterator quad = begin_quad(), endq = end_quad();
11360 for (; quad != endq; ++quad, ++i)
11361 *i = get_user_flag(quad);
11362
11363 Assert(i == v.end(), ExcInternalError());
11364 }
11365}
11366
11367
11368
11369template <int dim, int spacedim>
11370void
11372{
11373 std::vector<bool> v;
11374 save_user_flags_quad(v);
11375 write_bool_vector(mn_tria_quad_user_flags_begin,
11376 v,
11378 out);
11379}
11380
11381
11382
11383template <int dim, int spacedim>
11384void
11386{
11387 std::vector<bool> v;
11388 read_bool_vector(mn_tria_quad_user_flags_begin,
11389 v,
11391 in);
11392 load_user_flags_quad(v);
11393}
11394
11395
11396
11397template <int dim, int spacedim>
11398void
11400{
11401 Assert(v.size() == n_quads(), ExcGridReadError());
11402
11403 if (dim >= 2)
11404 {
11405 quad_iterator quad = begin_quad(), endq = end_quad();
11406 std::vector<bool>::const_iterator i = v.begin();
11407 for (; quad != endq; ++quad, ++i)
11408 if (*i == true)
11409 set_user_flag(quad);
11410 else
11411 clear_user_flag(quad);
11412
11413 Assert(i == v.end(), ExcInternalError());
11414 }
11415}
11416
11417
11418
11419template <int dim, int spacedim>
11420void
11421Triangulation<dim, spacedim>::save_user_flags_hex(std::vector<bool> &v) const
11422{
11423 v.resize(n_hexs(), false);
11424
11425 if (dim >= 3)
11426 {
11427 std::vector<bool>::iterator i = v.begin();
11428 hex_iterator hex = begin_hex(), endh = end_hex();
11429 for (; hex != endh; ++hex, ++i)
11430 *i = get_user_flag(hex);
11431
11432 Assert(i == v.end(), ExcInternalError());
11433 }
11434}
11435
11436
11437
11438template <int dim, int spacedim>
11439void
11441{
11442 std::vector<bool> v;
11443 save_user_flags_hex(v);
11444 write_bool_vector(mn_tria_hex_user_flags_begin,
11445 v,
11447 out);
11448}
11449
11450
11451
11452template <int dim, int spacedim>
11453void
11455{
11456 std::vector<bool> v;
11457 read_bool_vector(mn_tria_hex_user_flags_begin,
11458 v,
11460 in);
11461 load_user_flags_hex(v);
11462}
11463
11464
11465
11466template <int dim, int spacedim>
11467void
11468Triangulation<dim, spacedim>::load_user_flags_hex(const std::vector<bool> &v)
11469{
11470 Assert(v.size() == n_hexs(), ExcGridReadError());
11471
11472 if (dim >= 3)
11473 {
11474 hex_iterator hex = begin_hex(), endh = end_hex();
11475 std::vector<bool>::const_iterator i = v.begin();
11476 for (; hex != endh; ++hex, ++i)
11477 if (*i == true)
11478 set_user_flag(hex);
11479 else
11480 clear_user_flag(hex);
11481
11482 Assert(i == v.end(), ExcInternalError());
11483 }
11484}
11485
11486
11487
11488template <int dim, int spacedim>
11489void
11491 std::vector<unsigned int> &v) const
11492{
11493 // clear vector and append all the
11494 // stuff later on
11495 v.clear();
11496
11497 std::vector<unsigned int> tmp;
11498
11499 save_user_indices_line(tmp);
11500 v.insert(v.end(), tmp.begin(), tmp.end());
11501
11502 if (dim >= 2)
11503 {
11504 save_user_indices_quad(tmp);
11505 v.insert(v.end(), tmp.begin(), tmp.end());
11506 }
11507
11508 if (dim >= 3)
11509 {
11510 save_user_indices_hex(tmp);
11511 v.insert(v.end(), tmp.begin(), tmp.end());
11512 }
11513
11514 if (dim >= 4)
11515 Assert(false, ExcNotImplemented());
11516}
11517
11518
11519
11520template <int dim, int spacedim>
11521void
11523 const std::vector<unsigned int> &v)
11524{
11525 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
11526 std::vector<unsigned int> tmp;
11527
11528 // first extract the indices
11529 // belonging to lines
11530 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
11531 // and set the lines
11532 load_user_indices_line(tmp);
11533
11534 if (dim >= 2)
11535 {
11536 tmp.clear();
11537 tmp.insert(tmp.end(),
11538 v.begin() + n_lines(),
11539 v.begin() + n_lines() + n_quads());
11540 load_user_indices_quad(tmp);
11541 }
11542
11543 if (dim >= 3)
11544 {
11545 tmp.clear();
11546 tmp.insert(tmp.end(),
11547 v.begin() + n_lines() + n_quads(),
11548 v.begin() + n_lines() + n_quads() + n_hexs());
11549 load_user_indices_hex(tmp);
11550 }
11551
11552 if (dim >= 4)
11553 Assert(false, ExcNotImplemented());
11554}
11555
11556
11557
11558namespace
11559{
11560 template <typename Iterator>
11561 unsigned int
11562 get_user_index(const Iterator &i)
11563 {
11564 return i->user_index();
11565 }
11566
11567
11568
11569 template <int structdim, int dim, int spacedim>
11570 unsigned int
11571 get_user_index(
11573 {
11574 Assert(false, ExcInternalError());
11576 }
11577
11578
11579
11580 template <typename Iterator>
11581 void
11582 set_user_index(const Iterator &i, const unsigned int x)
11583 {
11584 i->set_user_index(x);
11585 }
11586
11587
11588
11589 template <int structdim, int dim, int spacedim>
11590 void
11591 set_user_index(
11593 const unsigned int)
11594 {
11595 Assert(false, ExcInternalError());
11596 }
11597} // namespace
11598
11599
11600template <int dim, int spacedim>
11601void
11603 std::vector<unsigned int> &v) const
11604{
11605 v.resize(n_lines(), 0);
11606 std::vector<unsigned int>::iterator i = v.begin();
11607 line_iterator line = begin_line(), endl = end_line();
11608 for (; line != endl; ++line, ++i)
11609 *i = line->user_index();
11610}
11611
11612
11613
11614template <int dim, int spacedim>
11615void
11617 const std::vector<unsigned int> &v)
11618{
11619 Assert(v.size() == n_lines(), ExcGridReadError());
11620
11621 line_iterator line = begin_line(), endl = end_line();
11622 std::vector<unsigned int>::const_iterator i = v.begin();
11623 for (; line != endl; ++line, ++i)
11624 line->set_user_index(*i);
11625}
11626
11627
11628template <int dim, int spacedim>
11629void
11631 std::vector<unsigned int> &v) const
11632{
11633 v.resize(n_quads(), 0);
11634
11635 if (dim >= 2)
11636 {
11637 std::vector<unsigned int>::iterator i = v.begin();
11638 quad_iterator quad = begin_quad(), endq = end_quad();
11639 for (; quad != endq; ++quad, ++i)
11640 *i = get_user_index(quad);
11641 }
11642}
11643
11644
11645
11646template <int dim, int spacedim>
11647void
11649 const std::vector<unsigned int> &v)
11650{
11651 Assert(v.size() == n_quads(), ExcGridReadError());
11652
11653 if (dim >= 2)
11654 {
11655 quad_iterator quad = begin_quad(), endq = end_quad();
11656 std::vector<unsigned int>::const_iterator i = v.begin();
11657 for (; quad != endq; ++quad, ++i)
11658 set_user_index(quad, *i);
11659 }
11660}
11661
11662
11663template <int dim, int spacedim>
11664void
11666 std::vector<unsigned int> &v) const
11667{
11668 v.resize(n_hexs(), 0);
11669
11670 if (dim >= 3)
11671 {
11672 std::vector<unsigned int>::iterator i = v.begin();
11673 hex_iterator hex = begin_hex(), endh = end_hex();
11674 for (; hex != endh; ++hex, ++i)
11675 *i = get_user_index(hex);
11676 }
11677}
11678
11679
11680
11681template <int dim, int spacedim>
11682void
11684 const std::vector<unsigned int> &v)
11685{
11686 Assert(v.size() == n_hexs(), ExcGridReadError());
11687
11688 if (dim >= 3)
11689 {
11690 hex_iterator hex = begin_hex(), endh = end_hex();
11691 std::vector<unsigned int>::const_iterator i = v.begin();
11692 for (; hex != endh; ++hex, ++i)
11693 set_user_index(hex, *i);
11694 }
11695}
11696
11697
11698
11699//---------------- user pointers ----------------------------------------//
11700
11701
11702namespace
11703{
11704 template <typename Iterator>
11705 void *
11706 get_user_pointer(const Iterator &i)
11707 {
11708 return i->user_pointer();
11709 }
11710
11711
11712
11713 template <int structdim, int dim, int spacedim>
11714 void *
11715 get_user_pointer(
11717 {
11718 Assert(false, ExcInternalError());
11719 return nullptr;
11720 }
11721
11722
11723
11724 template <typename Iterator>
11725 void
11726 set_user_pointer(const Iterator &i, void *x)
11727 {
11728 i->set_user_pointer(x);
11729 }
11730
11731
11732
11733 template <int structdim, int dim, int spacedim>
11734 void
11735 set_user_pointer(
11737 void *)
11738 {
11739 Assert(false, ExcInternalError());
11740 }
11741} // namespace
11742
11743
11744template <int dim, int spacedim>
11745void
11746Triangulation<dim, spacedim>::save_user_pointers(std::vector<void *> &v) const
11747{
11748 // clear vector and append all the
11749 // stuff later on
11750 v.clear();
11751
11752 std::vector<void *> tmp;
11753
11754 save_user_pointers_line(tmp);
11755 v.insert(v.end(), tmp.begin(), tmp.end());
11756
11757 if (dim >= 2)
11758 {
11759 save_user_pointers_quad(tmp);
11760 v.insert(v.end(), tmp.begin(), tmp.end());
11761 }
11762
11763 if (dim >= 3)
11764 {
11765 save_user_pointers_hex(tmp);
11766 v.insert(v.end(), tmp.begin(), tmp.end());
11767 }
11768
11769 if (dim >= 4)
11770 Assert(false, ExcNotImplemented());
11771}
11772
11773
11774
11775template <int dim, int spacedim>
11776void
11777Triangulation<dim, spacedim>::load_user_pointers(const std::vector<void *> &v)
11778{
11779 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
11780 std::vector<void *> tmp;
11781
11782 // first extract the pointers
11783 // belonging to lines
11784 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
11785 // and set the lines
11786 load_user_pointers_line(tmp);
11787
11788 if (dim >= 2)
11789 {
11790 tmp.clear();
11791 tmp.insert(tmp.end(),
11792 v.begin() + n_lines(),
11793 v.begin() + n_lines() + n_quads());
11794 load_user_pointers_quad(tmp);
11795 }
11796
11797 if (dim >= 3)
11798 {
11799 tmp.clear();
11800 tmp.insert(tmp.end(),
11801 v.begin() + n_lines() + n_quads(),
11802 v.begin() + n_lines() + n_quads() + n_hexs());
11803 load_user_pointers_hex(tmp);
11804 }
11805
11806 if (dim >= 4)
11807 Assert(false, ExcNotImplemented());
11808}
11809
11810
11811
11812template <int dim, int spacedim>
11813void
11815 std::vector<void *> &v) const
11816{
11817 v.resize(n_lines(), nullptr);
11818 std::vector<void *>::iterator i = v.begin();
11819 line_iterator line = begin_line(), endl = end_line();
11820 for (; line != endl; ++line, ++i)
11821 *i = line->user_pointer();
11822}
11823
11824
11825
11826template <int dim, int spacedim>
11827void
11829 const std::vector<void *> &v)
11830{
11831 Assert(v.size() == n_lines(), ExcGridReadError());
11832
11833 line_iterator line = begin_line(), endl = end_line();
11834 std::vector<void *>::const_iterator i = v.begin();
11835 for (; line != endl; ++line, ++i)
11836 line->set_user_pointer(*i);
11837}
11838
11839
11840
11841template <int dim, int spacedim>
11842void
11844 std::vector<void *> &v) const
11845{
11846 v.resize(n_quads(), nullptr);
11847
11848 if (dim >= 2)
11849 {
11850 std::vector<void *>::iterator i = v.begin();
11851 quad_iterator quad = begin_quad(), endq = end_quad();
11852 for (; quad != endq; ++quad, ++i)
11853 *i = get_user_pointer(quad);
11854 }
11855}
11856
11857
11858
11859template <int dim, int spacedim>
11860void
11862 const std::vector<void *> &v)
11863{
11864 Assert(v.size() == n_quads(), ExcGridReadError());
11865
11866 if (dim >= 2)
11867 {
11868 quad_iterator quad = begin_quad(), endq = end_quad();
11869 std::vector<void *>::const_iterator i = v.begin();
11870 for (; quad != endq; ++quad, ++i)
11871 set_user_pointer(quad, *i);
11872 }
11873}
11874
11875
11876template <int dim, int spacedim>
11877void
11879 std::vector<void *> &v) const
11880{
11881 v.resize(n_hexs(), nullptr);
11882
11883 if (dim >= 3)
11884 {
11885 std::vector<void *>::iterator i = v.begin();
11886 hex_iterator hex = begin_hex(), endh = end_hex();
11887 for (; hex != endh; ++hex, ++i)
11888 *i = get_user_pointer(hex);
11889 }
11890}
11891
11892
11893
11894template <int dim, int spacedim>
11895void
11897 const std::vector<void *> &v)
11898{
11899 Assert(v.size() == n_hexs(), ExcGridReadError());
11900
11901 if (dim >= 3)
11902 {
11903 hex_iterator hex = begin_hex(), endh = end_hex();
11904 std::vector<void *>::const_iterator i = v.begin();
11905 for (; hex != endh; ++hex, ++i)
11906 set_user_pointer(hex, *i);
11907 }
11908}
11909
11910
11911
11912/*------------------------ Cell iterator functions ------------------------*/
11913
11914
11915template <int dim, int spacedim>
11917Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
11918{
11919 switch (dim)
11920 {
11921 case 1:
11922 return begin_raw_line(level);
11923 case 2:
11924 return begin_raw_quad(level);
11925 case 3:
11926 return begin_raw_hex(level);
11927 default:
11928 Assert(false, ExcNotImplemented());
11929 return raw_cell_iterator();
11930 }
11931}
11932
11933
11934
11935template <int dim, int spacedim>
11937Triangulation<dim, spacedim>::begin(const unsigned int level) const
11938{
11939 switch (dim)
11940 {
11941 case 1:
11942 return begin_line(level);
11943 case 2:
11944 return begin_quad(level);
11945 case 3:
11946 return begin_hex(level);
11947 default:
11948 Assert(false, ExcImpossibleInDim(dim));
11949 return cell_iterator();
11950 }
11951}
11952
11953
11954
11955template <int dim, int spacedim>
11957Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
11958{
11959 switch (dim)
11960 {
11961 case 1:
11962 return begin_active_line(level);
11963 case 2:
11964 return begin_active_quad(level);
11965 case 3:
11966 return begin_active_hex(level);
11967 default:
11968 Assert(false, ExcNotImplemented());
11969 return active_cell_iterator();
11970 }
11971}
11972
11973
11974
11975template <int dim, int spacedim>
11978{
11979 const unsigned int level = levels.size() - 1;
11980 if (levels[level]->cells.n_objects() == 0)
11981 return end(level);
11982
11983 // find the last raw iterator on
11984 // this level
11985 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
11986 level,
11987 levels[level]->cells.n_objects() - 1);
11988
11989 // then move to the last used one
11990 if (ri->used() == true)
11991 return ri;
11992 while ((--ri).state() == IteratorState::valid)
11993 if (ri->used() == true)
11994 return ri;
11995 return ri;
11996}
11997
11998
11999
12000template <int dim, int spacedim>
12003{
12004 // get the last used cell
12005 cell_iterator cell = last();
12006
12007 if (cell != end())
12008 {
12009 // then move to the last active one
12010 if (cell->is_active() == true)
12011 return cell;
12012 while ((--cell).state() == IteratorState::valid)
12013 if (cell->is_active() == true)
12014 return cell;
12015 }
12016 return cell;
12017}
12018
12019
12020
12021template <int dim, int spacedim>
12024{
12025 cell_iterator cell(
12026 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
12027
12028 for (const auto &child_index : cell_id.get_child_indices())
12029 {
12030 Assert(
12031 cell->has_children(),
12032 ExcMessage(
12033 "CellId is invalid for this triangulation.\n"
12034 "Either the provided CellId does not correspond to a cell in this "
12035 "triangulation object, or, in case you are using a parallel "
12036 "triangulation, may correspond to an artificial cell that is less "
12037 "refined on this processor."));
12038 cell = cell->child(static_cast<unsigned int>(child_index));
12039 }
12040
12041 return cell;
12042}
12043
12044
12045
12046template <int dim, int spacedim>
12049{
12050 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
12051 -1,
12052 -1);
12053}
12054
12055
12056
12057template <int dim, int spacedim>
12059Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
12060{
12061 // This function may be called on parallel triangulations on levels
12062 // that exist globally, but not on the local portion of the
12063 // triangulation. In that case, just return the end iterator.
12064 //
12065 // We need to use levels.size() instead of n_levels() because the
12066 // latter function uses the cache, but we need to be able to call
12067 // this function at a time when the cache is not currently up to
12068 // date.
12069 if (level >= levels.size())
12070 {
12071 Assert(level < n_global_levels(),
12072 ExcInvalidLevel(level, n_global_levels()));
12073 return end();
12074 }
12075
12076 // Query whether the given level is valid for the local portion of the
12077 // triangulation.
12078 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12079 if (level < levels.size() - 1)
12080 return begin_raw(level + 1);
12081 else
12082 return end();
12083}
12084
12085
12086template <int dim, int spacedim>
12088Triangulation<dim, spacedim>::end(const unsigned int level) const
12089{
12090 // This function may be called on parallel triangulations on levels
12091 // that exist globally, but not on the local portion of the
12092 // triangulation. In that case, just retrn the end iterator.
12093 //
12094 // We need to use levels.size() instead of n_levels() because the
12095 // latter function uses the cache, but we need to be able to call
12096 // this function at a time when the cache is not currently up to
12097 // date.
12098 if (level >= levels.size())
12099 {
12100 Assert(level < n_global_levels(),
12101 ExcInvalidLevel(level, n_global_levels()));
12102 return end();
12103 }
12104
12105 // Query whether the given level is valid for the local portion of the
12106 // triangulation.
12107 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12108 if (level < levels.size() - 1)
12109 return begin(level + 1);
12110 else
12111 return end();
12112}
12113
12114
12115template <int dim, int spacedim>
12117Triangulation<dim, spacedim>::end_active(const unsigned int level) const
12118{
12119 // This function may be called on parallel triangulations on levels
12120 // that exist globally, but not on the local portion of the
12121 // triangulation. In that case, just return the end iterator.
12122 //
12123 // We need to use levels.size() instead of n_levels() because the
12124 // latter function uses the cache, but we need to be able to call
12125 // this function at a time when the cache is not currently up to
12126 // date.
12127 if (level >= levels.size())
12128 {
12129 Assert(level < n_global_levels(),
12130 ExcInvalidLevel(level, n_global_levels()));
12131 return end();
12132 }
12133
12134 // Query whether the given level is valid for the local portion of the
12135 // triangulation.
12136 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12137 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
12138 begin_active(level + 1));
12139}
12140
12141
12142
12143template <int dim, int spacedim>
12146{
12148 begin(), end());
12149}
12150
12151
12152template <int dim, int spacedim>
12155{
12156 return IteratorRange<
12158 end());
12159}
12160
12161
12162
12163template <int dim, int spacedim>
12166 const unsigned int level) const
12167{
12169 begin(level), end(level));
12170}
12171
12172
12173
12174template <int dim, int spacedim>
12177 const unsigned int level) const
12178{
12179 return IteratorRange<
12181 begin_active(level), end_active(level));
12182}
12183
12184
12185/*------------------------ Face iterator functions ------------------------*/
12186
12187
12188template <int dim, int spacedim>
12191{
12192 switch (dim)
12193 {
12194 case 1:
12195 Assert(false, ExcImpossibleInDim(1));
12196 return raw_face_iterator();
12197 case 2:
12198 return begin_line();
12199 case 3:
12200 return begin_quad();
12201 default:
12202 Assert(false, ExcNotImplemented());
12203 return face_iterator();
12204 }
12205}
12206
12207
12208
12209template <int dim, int spacedim>
12212{
12213 switch (dim)
12214 {
12215 case 1:
12216 Assert(false, ExcImpossibleInDim(1));
12217 return raw_face_iterator();
12218 case 2:
12219 return begin_active_line();
12220 case 3:
12221 return begin_active_quad();
12222 default:
12223 Assert(false, ExcNotImplemented());
12224 return active_face_iterator();
12225 }
12226}
12227
12228
12229
12230template <int dim, int spacedim>
12233{
12234 switch (dim)
12235 {
12236 case 1:
12237 Assert(false, ExcImpossibleInDim(1));
12238 return raw_face_iterator();
12239 case 2:
12240 return end_line();
12241 case 3:
12242 return end_quad();
12243 default:
12244 Assert(false, ExcNotImplemented());
12245 return raw_face_iterator();
12246 }
12247}
12248
12249
12250
12251template <int dim, int spacedim>
12254{
12255 return IteratorRange<
12257 begin_active_face(), end_face());
12258}
12259
12260/*------------------------ Vertex iterator functions ------------------------*/
12261
12262
12263template <int dim, int spacedim>
12266{
12267 vertex_iterator i =
12268 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
12269 if (i.state() != IteratorState::valid)
12270 return i;
12271 // This loop will end because every triangulation has used vertices.
12272 while (i->used() == false)
12273 if ((++i).state() != IteratorState::valid)
12274 return i;
12275 return i;
12276}
12277
12278
12279
12280template <int dim, int spacedim>
12283{
12284 // every vertex is active
12285 return begin_vertex();
12286}
12287
12288
12289
12290template <int dim, int spacedim>
12293{
12294 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
12295 -1,
12297}
12298
12299
12300
12301/*------------------------ Line iterator functions ------------------------*/
12302
12303
12304
12305template <int dim, int spacedim>
12308{
12309 // This function may be called on parallel triangulations on levels
12310 // that exist globally, but not on the local portion of the
12311 // triangulation. In that case, just return the end iterator.
12312 //
12313 // We need to use levels.size() instead of n_levels() because the
12314 // latter function uses the cache, but we need to be able to call
12315 // this function at a time when the cache is not currently up to
12316 // date.
12317 if (level >= levels.size())
12318 {
12319 Assert(level < n_global_levels(),
12320 ExcInvalidLevel(level, n_global_levels()));
12321 return end_line();
12322 }
12323
12324 switch (dim)
12325 {
12326 case 1:
12327 // Query whether the given level is valid for the local portion of the
12328 // triangulation.
12329 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12330
12331 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
12332 return end_line();
12333
12334 return raw_line_iterator(
12335 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
12336
12337 default:
12339 return raw_line_iterator(
12340 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
12341 }
12342}
12343
12344
12345template <int dim, int spacedim>
12347Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
12348{
12349 // level is checked in begin_raw
12350 raw_line_iterator ri = begin_raw_line(level);
12351 if (ri.state() != IteratorState::valid)
12352 return ri;
12353 while (ri->used() == false)
12354 if ((++ri).state() != IteratorState::valid)
12355 return ri;
12356 return ri;
12357}
12358
12359
12360
12361template <int dim, int spacedim>
12364{
12365 // level is checked in begin_raw
12366 line_iterator i = begin_line(level);
12367 if (i.state() != IteratorState::valid)
12368 return i;
12369 while (i->has_children())
12370 if ((++i).state() != IteratorState::valid)
12371 return i;
12372 return i;
12373}
12374
12375
12376
12377template <int dim, int spacedim>
12380{
12381 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
12382 -1,
12383 -1);
12384}
12385
12386
12387
12388/*------------------------ Quad iterator functions ------------------------*/
12389
12390
12391template <int dim, int spacedim>
12394{
12395 // This function may be called on parallel triangulations on levels
12396 // that exist globally, but not on the local portion of the
12397 // triangulation. In that case, just return the end iterator.
12398 //
12399 // We need to use levels.size() instead of n_levels() because the
12400 // latter function uses the cache, but we need to be able to call
12401 // this function at a time when the cache is not currently up to
12402 // date.
12403 if (level >= levels.size())
12404 {
12405 Assert(level < n_global_levels(),
12406 ExcInvalidLevel(level, n_global_levels()));
12407 return end_quad();
12408 }
12409
12410 switch (dim)
12411 {
12412 case 1:
12413 Assert(false, ExcImpossibleInDim(1));
12414 return raw_hex_iterator();
12415 case 2:
12416 {
12417 // Query whether the given level is valid for the local portion of the
12418 // triangulation.
12419 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12420
12421 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
12422 return end_quad();
12423
12424 return raw_quad_iterator(
12425 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
12426 }
12427
12428 case 3:
12429 {
12431
12432 return raw_quad_iterator(
12433 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
12434 }
12435
12436
12437 default:
12438 Assert(false, ExcNotImplemented());
12439 return raw_hex_iterator();
12440 }
12441}
12442
12443
12444
12445template <int dim, int spacedim>
12447Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
12448{
12449 // level is checked in begin_raw
12450 raw_quad_iterator ri = begin_raw_quad(level);
12451 if (ri.state() != IteratorState::valid)
12452 return ri;
12453 while (ri->used() == false)
12454 if ((++ri).state() != IteratorState::valid)
12455 return ri;
12456 return ri;
12457}
12458
12459
12460
12461template <int dim, int spacedim>
12464{
12465 // level is checked in begin_raw
12466 quad_iterator i = begin_quad(level);
12467 if (i.state() != IteratorState::valid)
12468 return i;
12469 while (i->has_children())
12470 if ((++i).state() != IteratorState::valid)
12471 return i;
12472 return i;
12473}
12474
12475
12476
12477template <int dim, int spacedim>
12480{
12481 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
12482 -1,
12483 -1);
12484}
12485
12486
12487/*------------------------ Hex iterator functions ------------------------*/
12488
12489
12490template <int dim, int spacedim>
12492Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
12493{
12494 // This function may be called on parallel triangulations on levels
12495 // that exist globally, but not on the local portion of the
12496 // triangulation. In that case, just return the end iterator.
12497 //
12498 // We need to use levels.size() instead of n_levels() because the
12499 // latter function uses the cache, but we need to be able to call
12500 // this function at a time when the cache is not currently up to
12501 // date.
12502 if (level >= levels.size())
12503 {
12504 Assert(level < n_global_levels(),
12505 ExcInvalidLevel(level, n_global_levels()));
12506 return end_hex();
12507 }
12508
12509 switch (dim)
12510 {
12511 case 1:
12512 case 2:
12513 Assert(false, ExcImpossibleInDim(1));
12514 return raw_hex_iterator();
12515 case 3:
12516 {
12517 // Query whether the given level is valid for the local portion of the
12518 // triangulation.
12519 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
12520
12521 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
12522 return end_hex();
12523
12524 return raw_hex_iterator(
12525 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
12526 }
12527
12528 default:
12529 Assert(false, ExcNotImplemented());
12530 return raw_hex_iterator();
12531 }
12532}
12533
12534
12535
12536template <int dim, int spacedim>
12538Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
12539{
12540 // level is checked in begin_raw
12541 raw_hex_iterator ri = begin_raw_hex(level);
12542 if (ri.state() != IteratorState::valid)
12543 return ri;
12544 while (ri->used() == false)
12545 if ((++ri).state() != IteratorState::valid)
12546 return ri;
12547 return ri;
12548}
12549
12550
12551
12552template <int dim, int spacedim>
12555{
12556 // level is checked in begin_raw
12557 hex_iterator i = begin_hex(level);
12558 if (i.state() != IteratorState::valid)
12559 return i;
12560 while (i->has_children())
12561 if ((++i).state() != IteratorState::valid)
12562 return i;
12563 return i;
12564}
12565
12566
12567
12568template <int dim, int spacedim>
12571{
12572 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
12573 -1,
12574 -1);
12575}
12576
12577
12578
12579// -------------------------------- number of cells etc ---------------
12580
12581
12582namespace internal
12583{
12584 namespace TriangulationImplementation
12585 {
12586 inline unsigned int
12588 {
12589 return c.n_lines;
12590 }
12591
12592
12593 inline unsigned int
12596 {
12597 return c.n_active_lines;
12598 }
12599
12600
12601 inline unsigned int
12603 {
12604 return c.n_quads;
12605 }
12606
12607
12608 inline unsigned int
12611 {
12612 return c.n_active_quads;
12613 }
12614
12615
12616 inline unsigned int
12618 {
12619 return c.n_hexes;
12620 }
12621
12622
12623 inline unsigned int
12626 {
12627 return c.n_active_hexes;
12628 }
12629 } // namespace TriangulationImplementation
12630} // namespace internal
12631
12632
12633
12634template <int dim, int spacedim>
12635unsigned int
12637{
12639}
12640
12641
12642template <int dim, int spacedim>
12643unsigned int
12645{
12647}
12648
12649template <int dim, int spacedim>
12652{
12653 return n_active_cells();
12654}
12655
12656
12657
12658template <int dim, int spacedim>
12659unsigned int
12661{
12662 switch (dim)
12663 {
12664 case 1:
12665 return n_used_vertices();
12666 case 2:
12667 return n_lines();
12668 case 3:
12669 return n_quads();
12670 default:
12671 Assert(false, ExcNotImplemented());
12672 }
12673 return 0;
12674}
12675
12676
12677template <int dim, int spacedim>
12678unsigned int
12680{
12681 switch (dim)
12682 {
12683 case 1:
12684 return n_vertices();
12685 case 2:
12686 return n_raw_lines();
12687 case 3:
12688 return n_raw_quads();
12689 default:
12690 Assert(false, ExcNotImplemented());
12691 }
12692 return 0;
12693}
12694
12695
12696template <int dim, int spacedim>
12697unsigned int
12699{
12700 switch (dim)
12701 {
12702 case 1:
12703 return n_used_vertices();
12704 case 2:
12705 return n_active_lines();
12706 case 3:
12707 return n_active_quads();
12708 default:
12709 Assert(false, ExcNotImplemented());
12710 }
12711 return 0;
12712}
12713
12714
12715template <int dim, int spacedim>
12716unsigned int
12717Triangulation<dim, spacedim>::n_raw_cells(const unsigned int level) const
12718{
12719 switch (dim)
12720 {
12721 case 1:
12722 return n_raw_lines(level);
12723 case 2:
12724 return n_raw_quads(level);
12725 case 3:
12726 return n_raw_hexs(level);
12727 default:
12728 Assert(false, ExcNotImplemented());
12729 }
12730 return 0;
12731}
12732
12733
12734
12735template <int dim, int spacedim>
12736unsigned int
12737Triangulation<dim, spacedim>::n_cells(const unsigned int level) const
12738{
12739 switch (dim)
12740 {
12741 case 1:
12742 return n_lines(level);
12743 case 2:
12744 return n_quads(level);
12745 case 3:
12746 return n_hexs(level);
12747 default:
12748 Assert(false, ExcNotImplemented());
12749 }
12750 return 0;
12751}
12752
12753
12754
12755template <int dim, int spacedim>
12756unsigned int
12758{
12759 switch (dim)
12760 {
12761 case 1:
12762 return n_active_lines(level);
12763 case 2:
12764 return n_active_quads(level);
12765 case 3:
12766 return n_active_hexs(level);
12767 default:
12768 Assert(false, ExcNotImplemented());
12769 }
12770 return 0;
12771}
12772
12773
12774template <int dim, int spacedim>
12775bool
12777{
12778 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; lvl++)
12779 if (n_active_cells(lvl) != 0)
12780 return true;
12781
12782 return false;
12783}
12784
12785
12786template <int dim, int spacedim>
12787unsigned int
12789{
12790 return number_cache.n_lines;
12791}
12792
12793
12794
12795template <int dim, int spacedim>
12796unsigned int
12797Triangulation<dim, spacedim>::n_raw_lines(const unsigned int level) const
12798{
12799 if (dim == 1)
12800 {
12801 AssertIndexRange(level, n_levels());
12802 return levels[level]->cells.n_objects();
12803 }
12804
12805 Assert(false, ExcFacesHaveNoLevel());
12806 return 0;
12807}
12808
12809
12810template <int dim, int spacedim>
12811unsigned int
12813{
12814 if (dim == 1)
12815 {
12816 Assert(false, ExcNotImplemented());
12817 return 0;
12818 }
12819
12820 return faces->lines.n_objects();
12821}
12822
12823
12824template <int dim, int spacedim>
12825unsigned int
12826Triangulation<dim, spacedim>::n_lines(const unsigned int level) const
12827{
12828 AssertIndexRange(level, number_cache.n_lines_level.size());
12829 Assert(dim == 1, ExcFacesHaveNoLevel());
12830 return number_cache.n_lines_level[level];
12831}
12832
12833
12834template <int dim, int spacedim>
12835unsigned int
12837{
12838 return number_cache.n_active_lines;
12839}
12840
12841
12842template <int dim, int spacedim>
12843unsigned int
12845{
12846 AssertIndexRange(level, number_cache.n_lines_level.size());
12847 Assert(dim == 1, ExcFacesHaveNoLevel());
12848
12849 return number_cache.n_active_lines_level[level];
12850}
12851
12852
12853template <>
12854unsigned int
12856{
12857 return 0;
12858}
12859
12860
12861template <>
12862unsigned int
12863Triangulation<1, 1>::n_quads(const unsigned int) const
12864{
12865 return 0;
12866}
12867
12868
12869template <>
12870unsigned int
12871Triangulation<1, 1>::n_raw_quads(const unsigned int) const
12872{
12873 return 0;
12874}
12875
12876
12877template <>
12878unsigned int
12879Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
12880{
12881 return 0;
12882}
12883
12884
12885template <>
12886unsigned int
12888{
12889 return 0;
12890}
12891
12892
12893template <>
12894unsigned int
12896{
12897 return 0;
12898}
12899
12900
12901
12902template <>
12903unsigned int
12905{
12906 return 0;
12907}
12908
12909
12910template <>
12911unsigned int
12912Triangulation<1, 2>::n_quads(const unsigned int) const
12913{
12914 return 0;
12915}
12916
12917
12918template <>
12919unsigned int
12920Triangulation<1, 2>::n_raw_quads(const unsigned int) const
12921{
12922 return 0;
12923}
12924
12925
12926template <>
12927unsigned int
12928Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
12929{
12930 return 0;
12931}
12932
12933
12934template <>
12935unsigned int
12937{
12938 return 0;
12939}
12940
12941
12942template <>
12943unsigned int
12945{
12946 return 0;
12947}
12948
12949
12950template <>
12951unsigned int
12953{
12954 return 0;
12955}
12956
12957
12958template <>
12959unsigned int
12960Triangulation<1, 3>::n_quads(const unsigned int) const
12961{
12962 return 0;
12963}
12964
12965
12966template <>
12967unsigned int
12968Triangulation<1, 3>::n_raw_quads(const unsigned int) const
12969{
12970 return 0;
12971}
12972
12973
12974template <>
12975unsigned int
12976Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
12977{
12978 return 0;
12979}
12980
12981
12982template <>
12983unsigned int
12985{
12986 return 0;
12987}
12988
12989
12990template <>
12991unsigned int
12993{
12994 return 0;
12995}
12996
12997
12998
12999template <int dim, int spacedim>
13000unsigned int
13002{
13003 return number_cache.n_quads;
13004}
13005
13006
13007template <int dim, int spacedim>
13008unsigned int
13009Triangulation<dim, spacedim>::n_quads(const unsigned int level) const
13010{
13011 Assert(dim == 2, ExcFacesHaveNoLevel());
13012 AssertIndexRange(level, number_cache.n_quads_level.size());
13013 return number_cache.n_quads_level[level];
13014}
13015
13016
13017
13018template <>
13019unsigned int
13021{
13022 AssertIndexRange(level, n_levels());
13023 return levels[level]->cells.n_objects();
13024}
13025
13026
13027
13028template <>
13029unsigned int
13031{
13032 AssertIndexRange(level, n_levels());
13033 return levels[level]->cells.n_objects();
13034}
13035
13036
13037template <>
13038unsigned int
13039Triangulation<3, 3>::n_raw_quads(const unsigned int) const
13040{
13041 Assert(false, ExcFacesHaveNoLevel());
13042 return 0;
13043}
13044
13045
13046
13047template <int dim, int spacedim>
13048unsigned int
13050{
13051 Assert(false, ExcNotImplemented());
13052 return 0;
13053}
13054
13055
13056
13057template <>
13058unsigned int
13060{
13061 return faces->quads.n_objects();
13062}
13063
13064
13065
13066template <int dim, int spacedim>
13067unsigned int
13069{
13070 return number_cache.n_active_quads;
13071}
13072
13073
13074template <int dim, int spacedim>
13075unsigned int
13077{
13078 AssertIndexRange(level, number_cache.n_quads_level.size());
13079 Assert(dim == 2, ExcFacesHaveNoLevel());
13080
13081 return number_cache.n_active_quads_level[level];
13082}
13083
13084
13085template <int dim, int spacedim>
13086unsigned int
13088{
13089 return 0;
13090}
13091
13092
13093
13094template <int dim, int spacedim>
13095unsigned int
13096Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
13097{
13098 return 0;
13099}
13100
13101
13102
13103template <int dim, int spacedim>
13104unsigned int
13105Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
13106{
13107 return 0;
13108}
13109
13110
13111template <int dim, int spacedim>
13112unsigned int
13114{
13115 return 0;
13116}
13117
13118
13119
13120template <int dim, int spacedim>
13121unsigned int
13122Triangulation<dim, spacedim>::n_active_hexs(const unsigned int) const
13123{
13124 return 0;
13125}
13126
13127
13128template <>
13129unsigned int
13131{
13132 return number_cache.n_hexes;
13133}
13134
13135
13136
13137template <>
13138unsigned int
13139Triangulation<3, 3>::n_hexs(const unsigned int level) const
13140{
13141 AssertIndexRange(level, number_cache.n_hexes_level.size());
13142
13143 return number_cache.n_hexes_level[level];
13144}
13145
13146
13147
13148template <>
13149unsigned int
13151{
13152 AssertIndexRange(level, n_levels());
13153 return levels[level]->cells.n_objects();
13154}
13155
13156
13157template <>
13158unsigned int
13160{
13161 return number_cache.n_active_hexes;
13162}
13163
13164
13165
13166template <>
13167unsigned int
13169{
13170 AssertIndexRange(level, number_cache.n_hexes_level.size());
13171
13172 return number_cache.n_active_hexes_level[level];
13173}
13174
13175
13176
13177template <int dim, int spacedim>
13178unsigned int
13180{
13181 return std::count(vertices_used.begin(), vertices_used.end(), true);
13182}
13183
13184
13185
13186template <int dim, int spacedim>
13187const std::vector<bool> &
13189{
13190 return vertices_used;
13191}
13192
13193
13194
13195template <>
13196unsigned int
13198{
13199 return 2;
13200}
13201
13202
13203
13204template <>
13205unsigned int
13207{
13208 return 2;
13209}
13210
13211
13212template <>
13213unsigned int
13215{
13216 return 2;
13217}
13218
13219
13220template <int dim, int spacedim>
13221unsigned int
13223{
13224 cell_iterator cell = begin(0),
13225 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
13226 // store the largest index of the
13227 // vertices used on level 0
13228 unsigned int max_vertex_index = 0;
13229 for (; cell != endc; ++cell)
13230 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
13231 if (cell->vertex_index(vertex) > max_vertex_index)
13232 max_vertex_index = cell->vertex_index(vertex);
13233
13234 // store the number of times a cell
13235 // touches a vertex. An unsigned
13236 // int should suffice, even for
13237 // larger dimensions
13238 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
13239 // touch a vertex's usage count
13240 // every time we find an adjacent
13241 // element
13242 for (cell = begin(); cell != endc; ++cell)
13243 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
13244 ++usage_count[cell->vertex_index(vertex)];
13245
13247 static_cast<unsigned int>(
13248 *std::max_element(usage_count.begin(), usage_count.end())));
13249}
13250
13251
13252
13253template <int dim, int spacedim>
13256{
13258}
13259
13260
13261
13262template <int dim, int spacedim>
13265{
13266 return *this;
13267}
13268
13269
13270
13271template <int dim, int spacedim>
13274{
13275 return *this;
13276}
13277
13278
13279
13280template <int dim, int spacedim>
13281void
13284 &periodicity_vector)
13285{
13286 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
13287 periodicity_vector.begin(),
13288 periodicity_vector.end());
13289
13290 // Now initialize periodic_face_map
13291 update_periodic_face_map();
13292}
13293
13294
13295
13296template <int dim, int spacedim>
13297const typename std::map<
13298 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
13299 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
13300 unsigned int>,
13301 std::bitset<3>>> &
13303{
13304 return periodic_face_map;
13305}
13306
13307
13308
13309template <int dim, int spacedim>
13310void
13312{
13313 // Call our version of prepare_coarsening_and_refinement() even if a derived
13314 // class like parallel::distributed::Triangulation overrides it. Their
13315 // function will be called in their execute_coarsening_and_refinement()
13316 // function. Even in a distributed computation our job here is to reconstruct
13317 // the local part of the mesh and as such checking our flags is enough.
13319
13320 // verify a case with which we have had
13321 // some difficulty in the past (see the
13322 // deal.II/coarsening_* tests)
13323 if (smooth_grid & limit_level_difference_at_vertices)
13324 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
13325
13326 // Inform all listeners about beginning of refinement.
13327 signals.pre_refinement();
13328
13329 execute_coarsening();
13330
13331 const DistortedCellList cells_with_distorted_children = execute_refinement();
13332
13333 reset_cell_vertex_indices_cache();
13334
13335 // verify a case with which we have had
13336 // some difficulty in the past (see the
13337 // deal.II/coarsening_* tests)
13338 if (smooth_grid & limit_level_difference_at_vertices)
13339 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
13340
13341 // finally build up neighbor connectivity information, and set
13342 // active cell indices
13343 this->policy->update_neighbors(*this);
13344 reset_active_cell_indices();
13345
13346 reset_global_cell_indices(); // TODO: better place?
13347
13348 // Inform all listeners about end of refinement.
13349 signals.post_refinement();
13350
13351 AssertThrow(cells_with_distorted_children.distorted_cells.size() == 0,
13352 cells_with_distorted_children);
13353
13354 update_periodic_face_map();
13355}
13356
13357
13358
13359template <int dim, int spacedim>
13360void
13362{
13363 unsigned int active_cell_index = 0;
13364 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
13365 if ((cell->used() == false) || cell->has_children())
13366 cell->set_active_cell_index(numbers::invalid_unsigned_int);
13367 else
13368 {
13369 cell->set_active_cell_index(active_cell_index);
13370 ++active_cell_index;
13371 }
13372
13373 Assert(active_cell_index == n_active_cells(), ExcInternalError());
13374}
13375
13376
13377
13378template <int dim, int spacedim>
13379void
13381{
13382 {
13384 for (const auto &cell : active_cell_iterators())
13385 cell->set_global_active_cell_index(cell_index++);
13386 }
13387
13388 for (unsigned int l = 0; l < levels.size(); ++l)
13389 {
13391 for (const auto &cell : cell_iterators_on_level(l))
13392 cell->set_global_level_cell_index(cell_index++);
13393 }
13394}
13395
13396
13397
13398template <int dim, int spacedim>
13399void
13401{
13402 for (unsigned int l = 0; l < levels.size(); ++l)
13403 {
13404 constexpr unsigned int max_vertices_per_cell = 1 << dim;
13405 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
13406 cache.clear();
13407 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
13409 for (const auto &cell : cell_iterators_on_level(l))
13410 {
13411 const unsigned int my_index = cell->index() * max_vertices_per_cell;
13412 for (const unsigned int i : cell->vertex_indices())
13413 cache[my_index + i] = internal::TriaAccessorImplementation::
13414 Implementation::vertex_index(*cell, i);
13415 }
13416 }
13417}
13418
13419
13420
13421template <int dim, int spacedim>
13422void
13424{
13425 // first empty the currently stored objects
13426 periodic_face_map.clear();
13427
13428 typename std::vector<
13430 for (it = periodic_face_pairs_level_0.begin();
13431 it != periodic_face_pairs_level_0.end();
13432 ++it)
13433 {
13434 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
13435 it->cell[1],
13436 it->face_idx[0],
13437 it->face_idx[1],
13438 it->orientation,
13439 periodic_face_map);
13440
13441 // for the other way, we need to invert the orientation
13442 std::bitset<3> inverted_orientation;
13443 {
13444 bool orientation, flip, rotation;
13445 orientation = it->orientation[0];
13446 rotation = it->orientation[2];
13447 flip = orientation ? rotation ^ it->orientation[1] : it->orientation[1];
13448 inverted_orientation[0] = orientation;
13449 inverted_orientation[1] = flip;
13450 inverted_orientation[2] = rotation;
13451 }
13452 update_periodic_face_map_recursively<dim, spacedim>(it->cell[1],
13453 it->cell[0],
13454 it->face_idx[1],
13455 it->face_idx[0],
13456 inverted_orientation,
13457 periodic_face_map);
13458 }
13459
13460 // check consistency
13461 typename std::map<std::pair<cell_iterator, unsigned int>,
13462 std::pair<std::pair<cell_iterator, unsigned int>,
13463 std::bitset<3>>>::const_iterator it_test;
13464 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
13465 ++it_test)
13466 {
13468 it_test->first.first;
13470 it_test->second.first.first;
13471 if (cell_1->level() == cell_2->level())
13472 {
13473 // if both cells have the same neighbor, then the same pair
13474 // order swapped has to be in the map
13475 Assert(periodic_face_map[it_test->second.first].first ==
13476 it_test->first,
13478 }
13479 }
13480}
13481
13482
13483
13484template <int dim, int spacedim>
13485void
13487{
13488 std::set<ReferenceCell> reference_cells_set;
13489 for (auto cell : active_cell_iterators())
13490 if (cell->is_locally_owned())
13491 reference_cells_set.insert(cell->reference_cell());
13492
13493 std::vector<ReferenceCell> reference_cells(reference_cells_set.begin(),
13494 reference_cells_set.end());
13495
13496 this->reference_cells = reference_cells;
13497}
13498
13499
13500
13501template <int dim, int spacedim>
13502const std::vector<ReferenceCell> &
13504{
13505 return this->reference_cells;
13506}
13507
13508
13509
13510template <int dim, int spacedim>
13511bool
13513{
13514 Assert(this->reference_cells.size() > 0,
13515 ExcMessage("You can't ask about the kinds of reference "
13516 "cells used by this triangulation if the "
13517 "triangulation doesn't yet have any cells in it."));
13518 return (this->reference_cells.size() == 1 &&
13519 this->reference_cells[0] == ReferenceCells::get_hypercube<dim>());
13520}
13521
13522
13523
13524template <int dim, int spacedim>
13525void
13527{
13528 levels.clear();
13529 faces.reset();
13530
13531 vertices.clear();
13532 vertices_used.clear();
13533
13534 manifold.clear();
13535
13537}
13538
13539
13540
13541template <int dim, int spacedim>
13544{
13545 const DistortedCellList cells_with_distorted_children =
13546 this->policy->execute_refinement(*this, check_for_distorted_cells);
13547
13548
13549
13550 // re-compute number of lines
13552 *this, levels.size(), number_cache);
13553
13554#ifdef DEBUG
13555 for (const auto &level : levels)
13556 monitor_memory(level->cells, dim);
13557
13558 // check whether really all refinement flags are reset (also of
13559 // previously non-active cells which we may not have touched. If the
13560 // refinement flag of a non-active cell is set, something went wrong
13561 // since the cell-accessors should have caught this)
13562 for (const auto &cell : this->cell_iterators())
13563 Assert(!cell->refine_flag_set(), ExcInternalError());
13564#endif
13565
13566 return cells_with_distorted_children;
13567}
13568
13569
13570
13571template <int dim, int spacedim>
13572void
13574{
13575 // create a vector counting for each line how many cells contain
13576 // this line. in 3D, this is used later on to decide which lines can
13577 // be deleted after coarsening a cell. in other dimensions it will
13578 // be ignored
13579 std::vector<unsigned int> line_cell_count =
13580 count_cells_bounded_by_line(*this);
13581 std::vector<unsigned int> quad_cell_count =
13582 count_cells_bounded_by_quad(*this);
13583
13584 // loop over all cells. Flag all cells of which all children are
13585 // flagged for coarsening and delete the childrens' flags. In
13586 // effect, only those cells are flagged of which originally all
13587 // children were flagged and for which all children are on the same
13588 // refinement level. For flagging, the user flags are used, to avoid
13589 // confusion and because non-active cells can't be flagged for
13590 // coarsening. Note that because of the effects of
13591 // @p{fix_coarsen_flags}, of a cell either all or no children must
13592 // be flagged for coarsening, so it is ok to only check the first
13593 // child
13594 clear_user_flags();
13595
13596 for (const auto &cell : this->cell_iterators())
13597 if (!cell->is_active())
13598 if (cell->child(0)->coarsen_flag_set())
13599 {
13600 cell->set_user_flag();
13601 for (unsigned int child = 0; child < cell->n_children(); ++child)
13602 {
13603 Assert(cell->child(child)->coarsen_flag_set(),
13605 cell->child(child)->clear_coarsen_flag();
13606 }
13607 }
13608
13609
13610 // now do the actual coarsening step. Since the loop goes over used
13611 // cells we only need not worry about deleting some cells since the
13612 // ++operator will then just hop over them if we should hit one. Do
13613 // the loop in the reverse way since we may only delete some cells
13614 // if their neighbors have already been deleted (if the latter are
13615 // on a higher level for example)
13616 //
13617 // since we delete the *children* of cells, we can ignore cells
13618 // on the highest level, i.e., level must be less than or equal
13619 // to n_levels()-2.
13620 cell_iterator cell = begin(), endc = end();
13621 if (levels.size() >= 2)
13622 for (cell = last(); cell != endc; --cell)
13623 if (cell->level() <= static_cast<int>(levels.size() - 2) &&
13624 cell->user_flag_set())
13625 {
13626 // inform all listeners that cell coarsening is going to happen
13627 signals.pre_coarsening_on_cell(cell);
13628 // use a separate function, since this is dimension specific
13629 this->policy->delete_children(*this,
13630 cell,
13631 line_cell_count,
13632 quad_cell_count);
13633 }
13634
13635 // re-compute number of lines and quads
13637 *this, levels.size(), number_cache);
13638
13639 // in principle no user flags should be set any more at this point
13640#if DEBUG
13641 for (cell = begin(); cell != endc; ++cell)
13642 Assert(cell->user_flag_set() == false, ExcInternalError());
13643#endif
13644}
13645
13646
13647
13648template <int dim, int spacedim>
13649void
13651{
13652 // copy a piece of code from prepare_coarsening_and_refinement that
13653 // ensures that the level difference at vertices is limited if so
13654 // desired. we need this code here since at least in 1d we don't
13655 // call the dimension-independent version of
13656 // prepare_coarsening_and_refinement function. in 2d and 3d, having
13657 // this hunk here makes our lives a bit easier as well as it takes
13658 // care of these cases earlier than it would otherwise happen.
13659 //
13660 // the main difference to the code in p_c_and_r is that here we
13661 // absolutely have to make sure that we get things right, i.e. that
13662 // in particular we set flags right if
13663 // limit_level_difference_at_vertices is set. to do so we iterate
13664 // until the flags don't change any more
13665 std::vector<bool> previous_coarsen_flags(n_active_cells());
13666 save_coarsen_flags(previous_coarsen_flags);
13667
13668 std::vector<int> vertex_level(vertices.size(), 0);
13669
13670 bool continue_iterating = true;
13671
13672 do
13673 {
13674 if (smooth_grid & limit_level_difference_at_vertices)
13675 {
13676 Assert(!anisotropic_refinement,
13677 ExcMessage("In case of anisotropic refinement the "
13678 "limit_level_difference_at_vertices flag for "
13679 "mesh smoothing must not be set!"));
13680
13681 // store highest level one of the cells adjacent to a vertex
13682 // belongs to
13683 std::fill(vertex_level.begin(), vertex_level.end(), 0);
13684 for (const auto &cell : this->active_cell_iterators())
13685 {
13686 if (cell->refine_flag_set())
13687 for (const unsigned int vertex :
13689 vertex_level[cell->vertex_index(vertex)] =
13690 std::max(vertex_level[cell->vertex_index(vertex)],
13691 cell->level() + 1);
13692 else if (!cell->coarsen_flag_set())
13693 for (const unsigned int vertex :
13695 vertex_level[cell->vertex_index(vertex)] =
13696 std::max(vertex_level[cell->vertex_index(vertex)],
13697 cell->level());
13698 else
13699 {
13700 // if coarsen flag is set then tentatively assume
13701 // that the cell will be coarsened. this isn't
13702 // always true (the coarsen flag could be removed
13703 // again) and so we may make an error here. we try
13704 // to correct this by iterating over the entire
13705 // process until we are converged
13706 Assert(cell->coarsen_flag_set(), ExcInternalError());
13707 for (const unsigned int vertex :
13709 vertex_level[cell->vertex_index(vertex)] =
13710 std::max(vertex_level[cell->vertex_index(vertex)],
13711 cell->level() - 1);
13712 }
13713 }
13714
13715
13716 // loop over all cells in reverse order. do so because we
13717 // can then update the vertex levels on the adjacent
13718 // vertices and maybe already flag additional cells in this
13719 // loop
13720 //
13721 // note that not only may we have to add additional
13722 // refinement flags, but we will also have to remove
13723 // coarsening flags on cells adjacent to vertices that will
13724 // see refinement
13725 active_cell_iterator cell = begin_active(), endc = end();
13726 for (cell = last_active(); cell != endc; --cell)
13727 if (cell->refine_flag_set() == false)
13728 {
13729 for (const unsigned int vertex :
13731 if (vertex_level[cell->vertex_index(vertex)] >=
13732 cell->level() + 1)
13733 {
13734 // remove coarsen flag...
13735 cell->clear_coarsen_flag();
13736
13737 // ...and if necessary also refine the current
13738 // cell, at the same time updating the level
13739 // information about vertices
13740 if (vertex_level[cell->vertex_index(vertex)] >
13741 cell->level() + 1)
13742 {
13743 cell->set_refine_flag();
13744
13745 for (const unsigned int v :
13747 vertex_level[cell->vertex_index(v)] =
13748 std::max(vertex_level[cell->vertex_index(v)],
13749 cell->level() + 1);
13750 }
13751
13752 // continue and see whether we may, for example,
13753 // go into the inner 'if' above based on a
13754 // different vertex
13755 }
13756 }
13757 }
13758
13759 // loop over all cells. Flag all cells of which all children are
13760 // flagged for coarsening and delete the childrens' flags. Also
13761 // delete all flags of cells for which not all children of a
13762 // cell are flagged. In effect, only those cells are flagged of
13763 // which originally all children were flagged and for which all
13764 // children are on the same refinement level. For flagging, the
13765 // user flags are used, to avoid confusion and because
13766 // non-active cells can't be flagged for coarsening
13767 //
13768 // In effect, all coarsen flags are turned into user flags of
13769 // the mother cell if coarsening is possible or deleted
13770 // otherwise.
13771 clear_user_flags();
13772 // Coarsen flags of cells with no mother cell, i.e. on the
13773 // coarsest level are deleted explicitly.
13774 for (const auto &acell : this->active_cell_iterators_on_level(0))
13775 acell->clear_coarsen_flag();
13776
13777 for (const auto &cell : this->cell_iterators())
13778 {
13779 // nothing to do if we are already on the finest level
13780 if (cell->is_active())
13781 continue;
13782
13783 const unsigned int n_children = cell->n_children();
13784 unsigned int flagged_children = 0;
13785 for (unsigned int child = 0; child < n_children; ++child)
13786 if (cell->child(child)->is_active() &&
13787 cell->child(child)->coarsen_flag_set())
13788 {
13789 ++flagged_children;
13790 // clear flag since we don't need it anymore
13791 cell->child(child)->clear_coarsen_flag();
13792 }
13793
13794 // flag this cell for coarsening if all children were
13795 // flagged
13796 if (flagged_children == n_children)
13797 cell->set_user_flag();
13798 }
13799
13800 // in principle no coarsen flags should be set any more at this
13801 // point
13802#if DEBUG
13803 for (auto &cell : this->cell_iterators())
13804 Assert(cell->coarsen_flag_set() == false, ExcInternalError());
13805#endif
13806
13807 // now loop over all cells which have the user flag set. their
13808 // children were flagged for coarsening. set the coarsen flag
13809 // again if we are sure that none of the neighbors of these
13810 // children are refined, or will be refined, since then we would
13811 // get a two-level jump in refinement. on the other hand, if one
13812 // of the children's neighbors has their user flag set, then we
13813 // know that its children will go away by coarsening, and we
13814 // will be ok.
13815 //
13816 // note on the other hand that we do allow level-2 jumps in
13817 // refinement between neighbors in 1d, so this whole procedure
13818 // is only necessary if we are not in 1d
13819 //
13820 // since we remove some coarsening/user flags in the process, we
13821 // have to work from the finest level to the coarsest one, since
13822 // we occasionally inspect user flags of cells on finer levels
13823 // and need to be sure that these flags are final
13824 cell_iterator cell = begin(), endc = end();
13825 for (cell = last(); cell != endc; --cell)
13826 if (cell->user_flag_set())
13827 // if allowed: flag the
13828 // children for coarsening
13829 if (this->policy->coarsening_allowed(cell))
13830 for (unsigned int c = 0; c < cell->n_children(); ++c)
13831 {
13832 Assert(cell->child(c)->refine_flag_set() == false,
13834
13835 cell->child(c)->set_coarsen_flag();
13836 }
13837
13838 // clear all user flags again, now that we don't need them any
13839 // more
13840 clear_user_flags();
13841
13842
13843 // now see if anything has changed in the last iteration of this
13844 // function
13845 std::vector<bool> current_coarsen_flags(n_active_cells());
13846 save_coarsen_flags(current_coarsen_flags);
13847
13848 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
13849 previous_coarsen_flags = current_coarsen_flags;
13850 }
13851 while (continue_iterating == true);
13852}
13853
13854
13855// TODO: merge the following 3 functions since they are the same
13856template <>
13857bool
13859{
13860 // save the flags to determine whether something was changed in the
13861 // course of this function
13862 std::vector<bool> flags_before;
13863 save_coarsen_flags(flags_before);
13864
13865 // do nothing in 1d, except setting the coarsening flags correctly
13866 fix_coarsen_flags();
13867
13868 std::vector<bool> flags_after;
13869 save_coarsen_flags(flags_after);
13870
13871 return (flags_before != flags_after);
13872}
13873
13874
13875template <>
13876bool
13878{
13879 // save the flags to determine whether something was changed in the
13880 // course of this function
13881 std::vector<bool> flags_before;
13882 save_coarsen_flags(flags_before);
13883
13884 // do nothing in 1d, except setting the coarsening flags correctly
13885 fix_coarsen_flags();
13886
13887 std::vector<bool> flags_after;
13888 save_coarsen_flags(flags_after);
13889
13890 return (flags_before != flags_after);
13891}
13892
13893
13894template <>
13895bool
13897{
13898 // save the flags to determine whether something was changed in the
13899 // course of this function
13900 std::vector<bool> flags_before;
13901 save_coarsen_flags(flags_before);
13902
13903 // do nothing in 1d, except setting the coarsening flags correctly
13904 fix_coarsen_flags();
13905
13906 std::vector<bool> flags_after;
13907 save_coarsen_flags(flags_after);
13908
13909 return (flags_before != flags_after);
13910}
13911
13912
13913
13914namespace
13915{
13916 // check if the given @param cell marked for coarsening would
13917 // produce an unrefined island. To break up long chains of these
13918 // cells we recursively check our neighbors in case we change this
13919 // cell. This reduces the number of outer iterations dramatically.
13920 template <int dim, int spacedim>
13921 void
13922 possibly_do_not_produce_unrefined_islands(
13924 {
13925 Assert(cell->has_children(), ExcInternalError());
13926
13927 unsigned int n_neighbors = 0;
13928 // count all neighbors that will be refined along the face of our
13929 // cell after the next step
13930 unsigned int count = 0;
13931 for (unsigned int n : GeometryInfo<dim>::face_indices())
13932 {
13933 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
13934 cell->neighbor(n);
13935 if (neighbor.state() == IteratorState::valid)
13936 {
13937 ++n_neighbors;
13938 if (face_will_be_refined_by_neighbor(cell, n))
13939 ++count;
13940 }
13941 }
13942 // clear coarsen flags if either all existing neighbors will be
13943 // refined or all but one will be and the cell is in the interior
13944 // of the domain
13945 if (count == n_neighbors ||
13946 (count >= n_neighbors - 1 &&
13947 n_neighbors == GeometryInfo<dim>::faces_per_cell))
13948 {
13949 for (unsigned int c = 0; c < cell->n_children(); ++c)
13950 cell->child(c)->clear_coarsen_flag();
13951
13952 for (const unsigned int face : GeometryInfo<dim>::face_indices())
13953 if (!cell->at_boundary(face) &&
13954 (!cell->neighbor(face)->is_active()) &&
13955 (cell_will_be_coarsened(cell->neighbor(face))))
13956 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
13957 cell->neighbor(face));
13958 }
13959 }
13960
13961
13962 // see if the current cell needs to be refined to avoid unrefined
13963 // islands.
13964 //
13965 // there are sometimes chains of cells that induce refinement of
13966 // each other. to avoid running the loop in
13967 // prepare_coarsening_and_refinement over and over again for each
13968 // one of them, at least for the isotropic refinement case we seek
13969 // to flag neighboring elements as well as necessary. this takes
13970 // care of (slightly pathological) cases like
13971 // deal.II/mesh_smoothing_03
13972 template <int dim, int spacedim>
13973 void
13974 possibly_refine_unrefined_island(
13976 const bool allow_anisotropic_smoothing)
13977 {
13978 Assert(cell->is_active(), ExcInternalError());
13979 Assert(cell->refine_flag_set() == false, ExcInternalError());
13980
13981
13982 // now we provide two algorithms. the first one is the standard
13983 // one, coming from the time, where only isotropic refinement was
13984 // possible. it simply counts the neighbors that are or will be
13985 // refined and compares to the number of other ones. the second
13986 // one does this check independently for each direction: if all
13987 // neighbors in one direction (normally two, at the boundary only
13988 // one) are refined, the current cell is flagged to be refined in
13989 // an according direction.
13990
13991 if (allow_anisotropic_smoothing == false)
13992 {
13993 // use first algorithm
13994 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
13995 for (const unsigned int face : GeometryInfo<dim>::face_indices())
13996 if (!cell->at_boundary(face))
13997 {
13998 if (face_will_be_refined_by_neighbor(cell, face))
13999 ++refined_neighbors;
14000 else
14001 ++unrefined_neighbors;
14002 }
14003
14004 if (unrefined_neighbors < refined_neighbors)
14005 {
14006 cell->clear_coarsen_flag();
14007 cell->set_refine_flag();
14008
14009 // ok, so now we have flagged this cell. if we know that
14010 // there were any unrefined neighbors at all, see if any
14011 // of those will have to be refined as well
14012 if (unrefined_neighbors > 0)
14013 for (const unsigned int face : GeometryInfo<dim>::face_indices())
14014 if (!cell->at_boundary(face) &&
14015 (face_will_be_refined_by_neighbor(cell, face) == false) &&
14016 (cell->neighbor(face)->has_children() == false) &&
14017 (cell->neighbor(face)->refine_flag_set() == false))
14018 possibly_refine_unrefined_island<dim, spacedim>(
14019 cell->neighbor(face), allow_anisotropic_smoothing);
14020 }
14021 }
14022 else
14023 {
14024 // variable to store the cell refine case needed to fulfill
14025 // all smoothing requirements
14026 RefinementCase<dim> smoothing_cell_refinement_case =
14028
14029 // use second algorithm, do the check individually for each
14030 // direction
14031 for (unsigned int face_pair = 0;
14032 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
14033 ++face_pair)
14034 {
14035 // variable to store the cell refine case needed to refine
14036 // at the current face pair in the same way as the
14037 // neighbors do...
14038 RefinementCase<dim> directional_cell_refinement_case =
14040
14041 for (unsigned int face_index = 0; face_index < 2; ++face_index)
14042 {
14043 unsigned int face = 2 * face_pair + face_index;
14044 // variable to store the refine case (to come) of the
14045 // face under consideration
14046 RefinementCase<dim - 1> expected_face_ref_case =
14047 RefinementCase<dim - 1>::no_refinement;
14048
14049 if (cell->neighbor(face).state() == IteratorState::valid)
14050 face_will_be_refined_by_neighbor<dim, spacedim>(
14051 cell, face, expected_face_ref_case);
14052 // now extract which refine case would be necessary to
14053 // achieve the same face refinement. set the
14054 // intersection with other requirements for the same
14055 // direction.
14056
14057 // note: using the intersection is not an obvious
14058 // decision, we could also argue that it is more
14059 // natural to use the union. however, intersection is
14060 // the less aggressive tactic and favours a smaller
14061 // number of refined cells over an intensive
14062 // smoothing. this way we try not to lose too much of
14063 // the effort we put in anisotropic refinement
14064 // indicators due to overly aggressive smoothing...
14065 directional_cell_refinement_case =
14066 (directional_cell_refinement_case &
14069 expected_face_ref_case,
14070 face,
14071 cell->face_orientation(face),
14072 cell->face_flip(face),
14073 cell->face_rotation(face)));
14074 } // for both face indices
14075 // if both requirements sum up to something useful, add
14076 // this to the refine case for smoothing. note: if
14077 // directional_cell_refinement_case is isotropic still,
14078 // then something went wrong...
14079 Assert(directional_cell_refinement_case <
14082 smoothing_cell_refinement_case =
14083 smoothing_cell_refinement_case | directional_cell_refinement_case;
14084 } // for all face_pairs
14085 // no we collected contributions from all directions. combine
14086 // the new flags with the existing refine case, but only if
14087 // smoothing is required
14088 if (smoothing_cell_refinement_case)
14089 {
14090 cell->clear_coarsen_flag();
14091 cell->set_refine_flag(cell->refine_flag_set() |
14092 smoothing_cell_refinement_case);
14093 }
14094 }
14095 }
14096} // namespace
14097
14098
14099template <int dim, int spacedim>
14100bool
14102{
14103 // save the flags to determine whether something was changed in the
14104 // course of this function
14105 std::vector<bool> flags_before[2];
14106 save_coarsen_flags(flags_before[0]);
14107 save_refine_flags(flags_before[1]);
14108
14109 // save the flags at the outset of each loop. we do so in order to
14110 // find out whether something was changed in the present loop, in
14111 // which case we would have to re-run the loop. the other
14112 // possibility to find this out would be to set a flag
14113 // @p{something_changed} to true each time we change something.
14114 // however, sometimes one change in one of the parts of the loop is
14115 // undone by another one, so we might end up in an endless loop. we
14116 // could be tempted to break this loop at an arbitrary number of
14117 // runs, but that would not be a clean solution, since we would
14118 // either have to 1/ break the loop too early, in which case the
14119 // promise that a second call to this function immediately after the
14120 // first one does not change anything, would be broken, or 2/ we do
14121 // as many loops as there are levels. we know that information is
14122 // transported over one level in each run of the loop, so this is
14123 // enough. Unfortunately, each loop is rather expensive, so we chose
14124 // the way presented here
14125 std::vector<bool> flags_before_loop[2] = {flags_before[0], flags_before[1]};
14126
14127 // now for what is done in each loop: we have to fulfill several
14128 // tasks at the same time, namely several mesh smoothing algorithms
14129 // and mesh regularization, by which we mean that the next mesh
14130 // fulfills several requirements such as no double refinement at
14131 // each face or line, etc.
14132 //
14133 // since doing these things at once seems almost impossible (in the
14134 // first year of this library, they were done in two functions, one
14135 // for refinement and one for coarsening, and most things within
14136 // these were done at once, so the code was rather impossible to
14137 // join into this, only, function), we do them one after each
14138 // other. the order in which we do them is such that the important
14139 // tasks, namely regularization, are done last and the least
14140 // important things are done the first. the following order is
14141 // chosen:
14142 //
14143 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
14144 // coarsen flags on level 1 to avoid level 0 cells being created
14145 // by coarsening. As coarsen flags will never be added, this can
14146 // be done once and for all before the actual loop starts.
14147 //
14148 // 1/ do not coarsen a cell if 'most of the neighbors' will be
14149 // refined after the step. This is to prevent occurrence of
14150 // unrefined islands.
14151 //
14152 // 2/ eliminate refined islands in the interior and at the
14153 // boundary. since they don't do much harm besides increasing the
14154 // number of degrees of freedom, doing this has a rather low
14155 // priority.
14156 //
14157 // 3/ limit the level difference of neighboring cells at each
14158 // vertex.
14159 //
14160 // 4/ eliminate unrefined islands. this has higher priority since
14161 // this diminishes the approximation properties not only of the
14162 // unrefined island, but also of the surrounding patch.
14163 //
14164 // 5/ ensure patch level 1. Then the triangulation consists of
14165 // patches, i.e. of cells that are refined once. It follows that
14166 // if at least one of the children of a cell is or will be
14167 // refined than all children need to be refined. This step only
14168 // sets refinement flags and does not set coarsening flags. If
14169 // the patch_level_1 flag is set, then
14170 // eliminate_unrefined_islands, eliminate_refined_inner_islands
14171 // and eliminate_refined_boundary_islands will be fulfilled
14172 // automatically and do not need to be enforced separately.
14173 //
14174 // 6/ take care of the requirement that no double refinement is done
14175 // at each face
14176 //
14177 // 7/ take care that no double refinement is done at each line in 3d
14178 // or higher dimensions.
14179 //
14180 // 8/ make sure that all children of each cell are either flagged
14181 // for coarsening or none of the children is
14182 //
14183 // For some of these steps, it is known that they interact. Namely,
14184 // it is not possible to guarantee that after step 6 another step 5
14185 // would have no effect; the same holds for the opposite order and
14186 // also when taking into account step 7. however, it is important to
14187 // guarantee that step five or six do not undo something that step 5
14188 // did, and step 7 not something of step 6, otherwise the
14189 // requirements will not be satisfied even if the loop
14190 // terminates. this is accomplished by the fact that steps 5 and 6
14191 // only *add* refinement flags and delete coarsening flags
14192 // (therefore, step 6 can't undo something that step 4 already did),
14193 // and step 7 only deletes coarsening flags, never adds some. step 7
14194 // needs also take care that it won't tag cells for refinement for
14195 // which some neighbors are more refined or will be refined.
14196
14198 // STEP 0:
14199 // Only if coarsest_level_1 or patch_level_1 is set: clear all
14200 // coarsen flags on level 1 to avoid level 0 cells being created
14201 // by coarsening.
14202 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
14203 n_levels() >= 2)
14204 {
14205 for (const auto &cell : active_cell_iterators_on_level(1))
14206 cell->clear_coarsen_flag();
14207 }
14208
14209 bool mesh_changed_in_this_loop = false;
14210 do
14211 {
14213 // STEP 1:
14214 // do not coarsen a cell if 'most of the neighbors' will be
14215 // refined after the step. This is to prevent the occurrence
14216 // of unrefined islands. If patch_level_1 is set, this will
14217 // be automatically fulfilled.
14218 if (smooth_grid & do_not_produce_unrefined_islands &&
14219 !(smooth_grid & patch_level_1))
14220 {
14221 for (const auto &cell : cell_iterators())
14222 {
14223 // only do something if this
14224 // cell will be coarsened
14225 if (!cell->is_active() && cell_will_be_coarsened(cell))
14226 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
14227 }
14228 }
14229
14230
14232 // STEP 2:
14233 // eliminate refined islands in the interior and at the
14234 // boundary. since they don't do much harm besides increasing
14235 // the number of degrees of freedom, doing this has a rather
14236 // low priority. If patch_level_1 is set, this will be
14237 // automatically fulfilled.
14238 //
14239 // there is one corner case to consider: if this is a
14240 // distributed triangulation, there may be refined islands on
14241 // the boundary of which we own only part (e.g. a single cell
14242 // in the corner of a domain). the rest of the island is
14243 // ghost cells and it *looks* like the area around it
14244 // (artificial cells) are coarser but this is only because
14245 // they may actually be equally fine on other
14246 // processors. it's hard to detect this case but we can do
14247 // the following: only set coarsen flags to remove this
14248 // refined island if all cells we want to set flags on are
14249 // locally owned
14250 if (smooth_grid & (eliminate_refined_inner_islands |
14251 eliminate_refined_boundary_islands) &&
14252 !(smooth_grid & patch_level_1))
14253 {
14254 for (const auto &cell : cell_iterators())
14255 if (!cell->is_active() ||
14256 (cell->is_active() && cell->refine_flag_set() &&
14257 cell->is_locally_owned()))
14258 {
14259 // check whether all children are active, i.e. not
14260 // refined themselves. This is a precondition that the
14261 // children may be coarsened away. If the cell is only
14262 // flagged for refinement, then all future children
14263 // will be active
14264 bool all_children_active = true;
14265 if (!cell->is_active())
14266 for (unsigned int c = 0; c < cell->n_children(); ++c)
14267 if (!cell->child(c)->is_active() ||
14268 cell->child(c)->is_ghost() ||
14269 cell->child(c)->is_artificial())
14270 {
14271 all_children_active = false;
14272 break;
14273 }
14274
14275 if (all_children_active)
14276 {
14277 // count number of refined and unrefined neighbors
14278 // of cell. neighbors on lower levels are counted
14279 // as unrefined since they can only get to the
14280 // same level as this cell by the next refinement
14281 // cycle
14282 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
14283
14284 // Keep track if this cell is at a periodic
14285 // boundary or not. TODO: We do not currently run
14286 // the algorithm for inner islands at a periodic
14287 // boundary (remains to be implemented), but we
14288 // also don't want to consider them
14289 // boundary_island cells as this can interfere
14290 // with 2:1 refinement across periodic faces.
14291 // Instead: just ignore those cells for this
14292 // smoothing operation below.
14293 bool at_periodic_boundary = false;
14294
14295 for (const unsigned int n :
14297 {
14298 const cell_iterator neighbor = cell->neighbor(n);
14299 if (neighbor.state() == IteratorState::valid)
14300 {
14301 ++total_neighbors;
14302
14303 if (!face_will_be_refined_by_neighbor(cell, n))
14304 ++unrefined_neighbors;
14305 }
14306 else if (cell->has_periodic_neighbor(n))
14307 {
14308 ++total_neighbors;
14309 at_periodic_boundary = true;
14310 }
14311 }
14312
14313 // if all neighbors unrefined: mark this cell for
14314 // coarsening or don't refine if marked for that
14315 //
14316 // also do the distinction between the two
14317 // versions of the eliminate_refined_*_islands
14318 // flag
14319 //
14320 // the last check is whether there are any
14321 // neighbors at all. if not so, then we are (e.g.)
14322 // on the coarsest grid with one cell, for which,
14323 // of course, we do not remove the refine flag.
14324 if ((unrefined_neighbors == total_neighbors) &&
14325 ((!cell->at_boundary() &&
14326 (smooth_grid & eliminate_refined_inner_islands)) ||
14327 (cell->at_boundary() && !at_periodic_boundary &&
14328 (smooth_grid &
14329 eliminate_refined_boundary_islands))) &&
14330 (total_neighbors != 0))
14331 {
14332 if (!cell->is_active())
14333 for (unsigned int c = 0; c < cell->n_children(); ++c)
14334 {
14335 cell->child(c)->clear_refine_flag();
14336 cell->child(c)->set_coarsen_flag();
14337 }
14338 else
14339 cell->clear_refine_flag();
14340 }
14341 }
14342 }
14343 }
14344
14346 // STEP 3:
14347 // limit the level difference of neighboring cells at each
14348 // vertex.
14349 //
14350 // in case of anisotropic refinement this does not make
14351 // sense. as soon as one cell is anisotropically refined, an
14352 // Assertion is thrown. therefore we can ignore this problem
14353 // later on
14354 if (smooth_grid & limit_level_difference_at_vertices)
14355 {
14356 Assert(!anisotropic_refinement,
14357 ExcMessage("In case of anisotropic refinement the "
14358 "limit_level_difference_at_vertices flag for "
14359 "mesh smoothing must not be set!"));
14360
14361 // store highest level one of the cells adjacent to a vertex
14362 // belongs to
14363 std::vector<int> vertex_level(vertices.size(), 0);
14364 for (const auto &cell : active_cell_iterators())
14365 {
14366 if (cell->refine_flag_set())
14367 for (const unsigned int vertex :
14369 vertex_level[cell->vertex_index(vertex)] =
14370 std::max(vertex_level[cell->vertex_index(vertex)],
14371 cell->level() + 1);
14372 else if (!cell->coarsen_flag_set())
14373 for (const unsigned int vertex :
14375 vertex_level[cell->vertex_index(vertex)] =
14376 std::max(vertex_level[cell->vertex_index(vertex)],
14377 cell->level());
14378 else
14379 {
14380 // if coarsen flag is set then tentatively assume
14381 // that the cell will be coarsened. this isn't
14382 // always true (the coarsen flag could be removed
14383 // again) and so we may make an error here
14384 Assert(cell->coarsen_flag_set(), ExcInternalError());
14385 for (const unsigned int vertex :
14387 vertex_level[cell->vertex_index(vertex)] =
14388 std::max(vertex_level[cell->vertex_index(vertex)],
14389 cell->level() - 1);
14390 }
14391 }
14392
14393
14394 // loop over all cells in reverse order. do so because we
14395 // can then update the vertex levels on the adjacent
14396 // vertices and maybe already flag additional cells in this
14397 // loop
14398 //
14399 // note that not only may we have to add additional
14400 // refinement flags, but we will also have to remove
14401 // coarsening flags on cells adjacent to vertices that will
14402 // see refinement
14403 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
14404 if (cell->refine_flag_set() == false)
14405 {
14406 for (const unsigned int vertex :
14408 if (vertex_level[cell->vertex_index(vertex)] >=
14409 cell->level() + 1)
14410 {
14411 // remove coarsen flag...
14412 cell->clear_coarsen_flag();
14413
14414 // ...and if necessary also refine the current
14415 // cell, at the same time updating the level
14416 // information about vertices
14417 if (vertex_level[cell->vertex_index(vertex)] >
14418 cell->level() + 1)
14419 {
14420 cell->set_refine_flag();
14421
14422 for (const unsigned int v :
14424 vertex_level[cell->vertex_index(v)] =
14425 std::max(vertex_level[cell->vertex_index(v)],
14426 cell->level() + 1);
14427 }
14428
14429 // continue and see whether we may, for example,
14430 // go into the inner'if'
14431 // above based on a
14432 // different vertex
14433 }
14434 }
14435 }
14436
14438 // STEP 4:
14439 // eliminate unrefined islands. this has higher priority
14440 // since this diminishes the approximation properties not
14441 // only of the unrefined island, but also of the surrounding
14442 // patch.
14443 //
14444 // do the loop from finest to coarsest cells since we may
14445 // trigger a cascade by marking cells for refinement which
14446 // may trigger more cells further down below
14447 if (smooth_grid & eliminate_unrefined_islands)
14448 {
14449 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
14450 // only do something if cell is not already flagged for
14451 // (isotropic) refinement
14452 if (cell->refine_flag_set() !=
14454 possibly_refine_unrefined_island<dim, spacedim>(
14455 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
14456 }
14457
14459 // STEP 5:
14460 // ensure patch level 1.
14461 //
14462 // Introduce some terminology:
14463 // - a cell that is refined
14464 // once is a patch of
14465 // level 1 simply called patch.
14466 // - a cell that is globally
14467 // refined twice is called
14468 // a patch of level 2.
14469 // - patch level n says that
14470 // the triangulation consists
14471 // of patches of level n.
14472 // This makes sense only
14473 // if the grid is already at
14474 // least n times globally
14475 // refined.
14476 //
14477 // E.g. from patch level 1 follows: if at least one of the
14478 // children of a cell is or will be refined than enforce all
14479 // children to be refined.
14480
14481 // This step 4 only sets refinement flags and does not set
14482 // coarsening flags.
14483 if (smooth_grid & patch_level_1)
14484 {
14485 // An important assumption (A) is that before calling this
14486 // function the grid was already of patch level 1.
14487
14488 // loop over all cells whose children are all active. (By
14489 // assumption (A) either all or none of the children are
14490 // active). If the refine flag of at least one of the
14491 // children is set then set_refine_flag and
14492 // clear_coarsen_flag of all children.
14493 for (const auto &cell : cell_iterators())
14494 if (!cell->is_active())
14495 {
14496 // ensure the invariant. we can then check whether all
14497 // of its children are further refined or not by
14498 // simply looking at the first child
14499 Assert(cell_is_patch_level_1(cell), ExcInternalError());
14500 if (cell->child(0)->has_children() == true)
14501 continue;
14502
14503 // cell is found to be a patch. combine the refine
14504 // cases of all children
14505 RefinementCase<dim> combined_ref_case =
14507 for (unsigned int i = 0; i < cell->n_children(); ++i)
14508 combined_ref_case =
14509 combined_ref_case | cell->child(i)->refine_flag_set();
14510 if (combined_ref_case != RefinementCase<dim>::no_refinement)
14511 for (unsigned int i = 0; i < cell->n_children(); ++i)
14512 {
14513 cell_iterator child = cell->child(i);
14514
14515 child->clear_coarsen_flag();
14516 child->set_refine_flag(combined_ref_case);
14517 }
14518 }
14519
14520 // The code above dealt with the case where we may get a
14521 // non-patch_level_1 mesh from refinement. Now also deal
14522 // with the case where we could get such a mesh by
14523 // coarsening. Coarsen the children (and remove the
14524 // grandchildren) only if all cell->grandchild(i)
14525 // ->coarsen_flag_set() are set.
14526 //
14527 // for a case where this is a bit tricky, take a look at the
14528 // mesh_smoothing_0[12] testcases
14529 for (const auto &cell : cell_iterators())
14530 {
14531 // check if this cell has active grandchildren. note
14532 // that we know that it is patch_level_1, i.e. if one of
14533 // its children is active then so are all, and it isn't
14534 // going to have any grandchildren at all:
14535 if (cell->is_active() || cell->child(0)->is_active())
14536 continue;
14537
14538 // cell is not active, and so are none of its
14539 // children. check the grandchildren. note that the
14540 // children are also patch_level_1, and so we only ever
14541 // need to check their first child
14542 const unsigned int n_children = cell->n_children();
14543 bool has_active_grandchildren = false;
14544
14545 for (unsigned int i = 0; i < n_children; ++i)
14546 if (cell->child(i)->child(0)->is_active())
14547 {
14548 has_active_grandchildren = true;
14549 break;
14550 }
14551
14552 if (has_active_grandchildren == false)
14553 continue;
14554
14555
14556 // ok, there are active grandchildren. see if either all
14557 // or none of them are flagged for coarsening
14558 unsigned int n_grandchildren = 0;
14559
14560 // count all coarsen flags of the grandchildren.
14561 unsigned int n_coarsen_flags = 0;
14562
14563 // cell is not a patch (of level 1) as it has a
14564 // grandchild. Is cell a patch of level 2?? Therefore:
14565 // find out whether all cell->child(i) are patches
14566 for (unsigned int c = 0; c < n_children; ++c)
14567 {
14568 // get at the child. by assumption (A), and the
14569 // check by which we got here, the child is not
14570 // active
14571 cell_iterator child = cell->child(c);
14572
14573 const unsigned int nn_children = child->n_children();
14574 n_grandchildren += nn_children;
14575
14576 // if child is found to be a patch of active cells
14577 // itself, then add up how many of its children are
14578 // supposed to be coarsened
14579 if (child->child(0)->is_active())
14580 for (unsigned int cc = 0; cc < nn_children; ++cc)
14581 if (child->child(cc)->coarsen_flag_set())
14582 ++n_coarsen_flags;
14583 }
14584
14585 // if not all grandchildren are supposed to be coarsened
14586 // (e.g. because some simply don't have the flag set, or
14587 // because they are not active and therefore cannot
14588 // carry the flag), then remove the coarsen flag from
14589 // all of the active grandchildren. note that there may
14590 // be coarsen flags on the grandgrandchildren -- we
14591 // don't clear them here, but we'll get to them in later
14592 // iterations if necessary
14593 //
14594 // there is nothing we have to do if no coarsen flags
14595 // have been set at all
14596 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
14597 for (unsigned int c = 0; c < n_children; ++c)
14598 {
14599 const cell_iterator child = cell->child(c);
14600 if (child->child(0)->is_active())
14601 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
14602 child->child(cc)->clear_coarsen_flag();
14603 }
14604 }
14605 }
14606
14608 //
14609 // at the boundary we could end up with cells with negative
14610 // volume or at least with a part, that is negative, if the
14611 // cell is refined anisotropically. we have to check, whether
14612 // that can happen
14613 this->policy->prevent_distorted_boundary_cells(*this);
14614
14616 // STEP 6:
14617 // take care of the requirement that no
14618 // double refinement is done at each face
14619 //
14620 // in case of anisotropic refinement it is only likely, but
14621 // not sure, that the cells, which are more refined along a
14622 // certain face common to two cells are on a higher
14623 // level. therefore we cannot be sure, that the requirement
14624 // of no double refinement is fulfilled after a single pass
14625 // of the following actions. We could just wait for the next
14626 // global loop. when this function terminates, the
14627 // requirement will be fulfilled. However, it might be faster
14628 // to insert an inner loop here.
14629 bool changed = true;
14630 while (changed)
14631 {
14632 changed = false;
14633 active_cell_iterator cell = last_active(), endc = end();
14634
14635 for (; cell != endc; --cell)
14636 if (cell->refine_flag_set())
14637 {
14638 // loop over neighbors of cell
14639 for (const auto i : cell->face_indices())
14640 {
14641 // only do something if the face is not at the
14642 // boundary and if the face will be refined with
14643 // the RefineCase currently flagged for
14644 const bool has_periodic_neighbor =
14645 cell->has_periodic_neighbor(i);
14646 const bool has_neighbor_or_periodic_neighbor =
14647 !cell->at_boundary(i) || has_periodic_neighbor;
14648 if (has_neighbor_or_periodic_neighbor &&
14650 cell->refine_flag_set(), i) !=
14652 {
14653 // 1) if the neighbor has children: nothing to
14654 // worry about. 2) if the neighbor is active
14655 // and a coarser one, ensure, that its
14656 // refine_flag is set 3) if the neighbor is
14657 // active and as refined along the face as our
14658 // current cell, make sure, that no
14659 // coarsen_flag is set. if we remove the
14660 // coarsen flag of our neighbor,
14661 // fix_coarsen_flags() makes sure, that the
14662 // mother cell will not be coarsened
14663 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
14664 {
14665 if ((!has_periodic_neighbor &&
14666 cell->neighbor_is_coarser(i)) ||
14667 (has_periodic_neighbor &&
14668 cell->periodic_neighbor_is_coarser(i)))
14669 {
14670 if (cell->neighbor_or_periodic_neighbor(i)
14671 ->coarsen_flag_set())
14672 cell->neighbor_or_periodic_neighbor(i)
14673 ->clear_coarsen_flag();
14674 // we'll set the refine flag for this
14675 // neighbor below. we note, that we
14676 // have changed something by setting
14677 // the changed flag to true. We do not
14678 // need to do so, if we just removed
14679 // the coarsen flag, as the changed
14680 // flag only indicates the need to
14681 // re-run the inner loop. however, we
14682 // only loop over cells flagged for
14683 // refinement here, so nothing to
14684 // worry about if we remove coarsen
14685 // flags
14686
14687 if (dim == 2)
14688 {
14689 if (smooth_grid &
14690 allow_anisotropic_smoothing)
14691 changed =
14692 has_periodic_neighbor ?
14693 cell->periodic_neighbor(i)
14694 ->flag_for_face_refinement(
14695 cell
14696 ->periodic_neighbor_of_coarser_periodic_neighbor(
14697 i)
14698 .first,
14700 cell->neighbor(i)
14701 ->flag_for_face_refinement(
14702 cell
14703 ->neighbor_of_coarser_neighbor(
14704 i)
14705 .first,
14707 else
14708 {
14709 if (!cell
14710 ->neighbor_or_periodic_neighbor(
14711 i)
14712 ->refine_flag_set())
14713 changed = true;
14714 cell->neighbor_or_periodic_neighbor(i)
14715 ->set_refine_flag();
14716 }
14717 }
14718 else // i.e. if (dim==3)
14719 {
14720 // ugly situations might arise here,
14721 // consider the following situation, which
14722 // shows neighboring cells at the common
14723 // face, where the upper right element is
14724 // coarser at the given face. Now the upper
14725 // child element of the lower left wants to
14726 // refine according to cut_z, such that
14727 // there is a 'horizontal' refinement of the
14728 // face marked with #####
14729 //
14730 // / /
14731 // / /
14732 // *---------------*
14733 // | |
14734 // | |
14735 // | |
14736 // | |
14737 // | |
14738 // | | /
14739 // | |/
14740 // *---------------*
14741 //
14742 //
14743 // *---------------*
14744 // /| /|
14745 // / | ##### / |
14746 // | |
14747 // *---------------*
14748 // /| /|
14749 // / | / |
14750 // | |
14751 // *---------------*
14752 // / /
14753 // / /
14754 //
14755 // this introduces too many hanging nodes
14756 // and the neighboring (coarser) cell (upper
14757 // right) has to be refined. If it is only
14758 // refined according to cut_z, then
14759 // everything is ok:
14760 //
14761 // / /
14762 // / /
14763 // *---------------*
14764 // | |
14765 // | | /
14766 // | |/
14767 // *---------------*
14768 // | |
14769 // | | /
14770 // | |/
14771 // *---------------*
14772 //
14773 //
14774 // *---------------*
14775 // /| /|
14776 // / *---------------*
14777 // /| /|
14778 // *---------------*
14779 // /| /|
14780 // / | / |
14781 // | |
14782 // *---------------*
14783 // / /
14784 // / /
14785 //
14786 // if however the cell wants to refine
14787 // itself in an other way, or if we disallow
14788 // anisotropic smoothing, then simply
14789 // refining the neighbor isotropically is
14790 // not going to work, since this introduces
14791 // a refinement of face ##### with both
14792 // cut_x and cut_y, which is not possible:
14793 //
14794 // / / /
14795 // / / /
14796 // *-------*-------*
14797 // | | |
14798 // | | | /
14799 // | | |/
14800 // *-------*-------*
14801 // | | |
14802 // | | | /
14803 // | | |/
14804 // *-------*-------*
14805 //
14806 //
14807 // *---------------*
14808 // /| /|
14809 // / *---------------*
14810 // /| /|
14811 // *---------------*
14812 // /| /|
14813 // / | / |
14814 // | |
14815 // *---------------*
14816 // / /
14817 // / /
14818 //
14819 // thus, in this case we also need to refine
14820 // our current cell in the new direction:
14821 //
14822 // / / /
14823 // / / /
14824 // *-------*-------*
14825 // | | |
14826 // | | | /
14827 // | | |/
14828 // *-------*-------*
14829 // | | |
14830 // | | | /
14831 // | | |/
14832 // *-------*-------*
14833 //
14834 //
14835 // *-------*-------*
14836 // /| /| /|
14837 // / *-------*-------*
14838 // /| /| /|
14839 // *-------*-------*
14840 // /| / /|
14841 // / | / |
14842 // | |
14843 // *---------------*
14844 // / /
14845 // / /
14846
14847 std::pair<unsigned int, unsigned int>
14848 nb_indices =
14849 has_periodic_neighbor ?
14850 cell
14851 ->periodic_neighbor_of_coarser_periodic_neighbor(
14852 i) :
14853 cell->neighbor_of_coarser_neighbor(i);
14854 unsigned int refined_along_x = 0,
14855 refined_along_y = 0,
14856 to_be_refined_along_x = 0,
14857 to_be_refined_along_y = 0;
14858
14859 const int this_face_index =
14860 cell->face_index(i);
14861
14862 // step 1: detect, along which axis the face
14863 // is currently refined
14864
14865 // first, we need an iterator pointing to
14866 // the parent face. This requires a slight
14867 // detour in case the neighbor is behind a
14868 // periodic face.
14869 const auto parent_face = [&]() {
14870 if (has_periodic_neighbor)
14871 {
14872 const auto neighbor =
14873 cell->periodic_neighbor(i);
14874 const auto parent_face_no =
14875 neighbor
14876 ->periodic_neighbor_of_periodic_neighbor(
14877 nb_indices.first);
14878 auto parent =
14879 neighbor->periodic_neighbor(
14880 nb_indices.first);
14881 return parent->face(parent_face_no);
14882 }
14883 else
14884 return cell->neighbor(i)->face(
14885 nb_indices.first);
14886 }();
14887
14888 if ((this_face_index ==
14889 parent_face->child_index(0)) ||
14890 (this_face_index ==
14891 parent_face->child_index(1)))
14892 {
14893 // this might be an
14894 // anisotropic child. get the
14895 // face refine case of the
14896 // neighbors face and count
14897 // refinements in x and y
14898 // direction.
14899 RefinementCase<dim - 1> frc =
14900 parent_face->refinement_case();
14902 ++refined_along_x;
14904 ++refined_along_y;
14905 }
14906 else
14907 // this has to be an isotropic
14908 // child
14909 {
14910 ++refined_along_x;
14911 ++refined_along_y;
14912 }
14913 // step 2: detect, along which axis the face
14914 // has to be refined given the current
14915 // refine flag
14916 RefinementCase<dim - 1> flagged_frc =
14918 cell->refine_flag_set(),
14919 i,
14920 cell->face_orientation(i),
14921 cell->face_flip(i),
14922 cell->face_rotation(i));
14923 if (flagged_frc &
14925 ++to_be_refined_along_x;
14926 if (flagged_frc &
14928 ++to_be_refined_along_y;
14929
14930 // step 3: set the refine flag of the
14931 // (coarser and active) neighbor.
14932 if ((smooth_grid &
14933 allow_anisotropic_smoothing) ||
14934 cell->neighbor_or_periodic_neighbor(i)
14935 ->refine_flag_set())
14936 {
14937 if (refined_along_x +
14938 to_be_refined_along_x >
14939 1)
14940 changed |=
14941 cell
14942 ->neighbor_or_periodic_neighbor(i)
14943 ->flag_for_face_refinement(
14944 nb_indices.first,
14945 RefinementCase<dim -
14946 1>::cut_axis(0));
14947 if (refined_along_y +
14948 to_be_refined_along_y >
14949 1)
14950 changed |=
14951 cell
14952 ->neighbor_or_periodic_neighbor(i)
14953 ->flag_for_face_refinement(
14954 nb_indices.first,
14955 RefinementCase<dim -
14956 1>::cut_axis(1));
14957 }
14958 else
14959 {
14960 if (cell
14961 ->neighbor_or_periodic_neighbor(i)
14962 ->refine_flag_set() !=
14964 dim>::isotropic_refinement)
14965 changed = true;
14966 cell->neighbor_or_periodic_neighbor(i)
14967 ->set_refine_flag();
14968 }
14969
14970 // step 4: if necessary (see above) add to
14971 // the refine flag of the current cell
14972 cell_iterator nb =
14973 cell->neighbor_or_periodic_neighbor(i);
14974 RefinementCase<dim - 1> nb_frc =
14976 nb->refine_flag_set(),
14977 nb_indices.first,
14978 nb->face_orientation(nb_indices.first),
14979 nb->face_flip(nb_indices.first),
14980 nb->face_rotation(nb_indices.first));
14981 if ((nb_frc & RefinementCase<dim>::cut_x) &&
14982 !(refined_along_x ||
14983 to_be_refined_along_x))
14984 changed |= cell->flag_for_face_refinement(
14985 i,
14987 if ((nb_frc & RefinementCase<dim>::cut_y) &&
14988 !(refined_along_y ||
14989 to_be_refined_along_y))
14990 changed |= cell->flag_for_face_refinement(
14991 i,
14993 }
14994 } // if neighbor is coarser
14995 else // -> now the neighbor is not coarser
14996 {
14997 cell->neighbor_or_periodic_neighbor(i)
14998 ->clear_coarsen_flag();
14999 const unsigned int nb_nb =
15000 has_periodic_neighbor ?
15001 cell
15002 ->periodic_neighbor_of_periodic_neighbor(
15003 i) :
15004 cell->neighbor_of_neighbor(i);
15005 const cell_iterator neighbor =
15006 cell->neighbor_or_periodic_neighbor(i);
15007 RefinementCase<dim - 1> face_ref_case =
15009 neighbor->refine_flag_set(),
15010 nb_nb,
15011 neighbor->face_orientation(nb_nb),
15012 neighbor->face_flip(nb_nb),
15013 neighbor->face_rotation(nb_nb));
15014 RefinementCase<dim - 1> needed_face_ref_case =
15016 cell->refine_flag_set(),
15017 i,
15018 cell->face_orientation(i),
15019 cell->face_flip(i),
15020 cell->face_rotation(i));
15021 // if the neighbor wants to refine the
15022 // face with cut_x and we want cut_y
15023 // or vice versa, we have to refine
15024 // isotropically at the given face
15025 if ((face_ref_case ==
15027 needed_face_ref_case ==
15029 (face_ref_case ==
15031 needed_face_ref_case ==
15033 {
15034 changed = cell->flag_for_face_refinement(
15035 i, face_ref_case);
15036 neighbor->flag_for_face_refinement(
15037 nb_nb, needed_face_ref_case);
15038 }
15039 }
15040 }
15041 else //-> the neighbor is not active
15042 {
15043 RefinementCase<dim - 1>
15044 face_ref_case = cell->face(i)->refinement_case(),
15045 needed_face_ref_case =
15047 cell->refine_flag_set(),
15048 i,
15049 cell->face_orientation(i),
15050 cell->face_flip(i),
15051 cell->face_rotation(i));
15052 // if the face is refined with cut_x and
15053 // we want cut_y or vice versa, we have to
15054 // refine isotropically at the given face
15055 if ((face_ref_case == RefinementCase<dim>::cut_x &&
15056 needed_face_ref_case ==
15058 (face_ref_case == RefinementCase<dim>::cut_y &&
15059 needed_face_ref_case ==
15061 changed =
15062 cell->flag_for_face_refinement(i,
15063 face_ref_case);
15064 }
15065 }
15066 }
15067 }
15068 }
15069
15071 // STEP 7:
15072 // take care that no double refinement
15073 // is done at each line in 3d or higher
15074 // dimensions.
15075 this->policy->prepare_refinement_dim_dependent(*this);
15076
15078 // STEP 8:
15079 // make sure that all children of each
15080 // cell are either flagged for coarsening
15081 // or none of the children is
15082 fix_coarsen_flags();
15083 // get the refinement and coarsening
15084 // flags
15085 std::vector<bool> flags_after_loop[2];
15086 save_coarsen_flags(flags_after_loop[0]);
15087 save_refine_flags(flags_after_loop[1]);
15088
15089 // find out whether something was
15090 // changed in this loop
15091 mesh_changed_in_this_loop =
15092 ((flags_before_loop[0] != flags_after_loop[0]) ||
15093 (flags_before_loop[1] != flags_after_loop[1]));
15094
15095 // set the flags for the next loop
15096 // already
15097 flags_before_loop[0].swap(flags_after_loop[0]);
15098 flags_before_loop[1].swap(flags_after_loop[1]);
15099 }
15100 while (mesh_changed_in_this_loop);
15101
15102
15103 // find out whether something was really changed in this
15104 // function. Note that @p{flags_before_loop} represents the state
15105 // after the last loop, i.e. the present state
15106 return ((flags_before[0] != flags_before_loop[0]) ||
15107 (flags_before[1] != flags_before_loop[1]));
15108}
15109
15110
15111
15112template <int dim, int spacedim>
15113void
15115 const unsigned int magic_number1,
15116 const std::vector<bool> &v,
15117 const unsigned int magic_number2,
15118 std::ostream & out)
15119{
15120 const unsigned int N = v.size();
15121 unsigned char * flags = new unsigned char[N / 8 + 1];
15122 for (unsigned int i = 0; i < N / 8 + 1; ++i)
15123 flags[i] = 0;
15124
15125 for (unsigned int position = 0; position < N; ++position)
15126 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
15127
15128 AssertThrow(out, ExcIO());
15129
15130 // format:
15131 // 0. magic number
15132 // 1. number of flags
15133 // 2. the flags
15134 // 3. magic number
15135 out << magic_number1 << ' ' << N << std::endl;
15136 for (unsigned int i = 0; i < N / 8 + 1; ++i)
15137 out << static_cast<unsigned int>(flags[i]) << ' ';
15138
15139 out << std::endl << magic_number2 << std::endl;
15140
15141 delete[] flags;
15142
15143 AssertThrow(out, ExcIO());
15144}
15145
15146
15147template <int dim, int spacedim>
15148void
15149Triangulation<dim, spacedim>::read_bool_vector(const unsigned int magic_number1,
15150 std::vector<bool> &v,
15151 const unsigned int magic_number2,
15152 std::istream & in)
15153{
15154 AssertThrow(in, ExcIO());
15155
15156 unsigned int magic_number;
15157 in >> magic_number;
15158 AssertThrow(magic_number == magic_number1, ExcGridReadError());
15159
15160 unsigned int N;
15161 in >> N;
15162 v.resize(N);
15163
15164 unsigned char * flags = new unsigned char[N / 8 + 1];
15165 unsigned short int tmp;
15166 for (unsigned int i = 0; i < N / 8 + 1; ++i)
15167 {
15168 in >> tmp;
15169 flags[i] = tmp;
15170 }
15171
15172 for (unsigned int position = 0; position != N; ++position)
15173 v[position] = (flags[position / 8] & (1 << (position % 8)));
15174
15175 in >> magic_number;
15176 AssertThrow(magic_number == magic_number2, ExcGridReadError());
15177
15178 delete[] flags;
15179
15180 AssertThrow(in, ExcIO());
15181}
15182
15183
15184
15185template <int dim, int spacedim>
15186std::size_t
15188{
15189 std::size_t mem = 0;
15191 for (const auto &level : levels)
15194 mem += MemoryConsumption::memory_consumption(vertices_used);
15195 mem += sizeof(manifold);
15196 mem += sizeof(smooth_grid);
15197 mem += MemoryConsumption::memory_consumption(number_cache);
15198 mem += sizeof(faces);
15199 if (faces)
15201
15202 return mem;
15203}
15204
15205
15206
15207template <int dim, int spacedim>
15209 default;
15210
15211
15212// explicit instantiations
15213#include "tria.inst"
15214
Definition: cell_id.h:71
ArrayView< const std::uint8_t > get_child_indices() const
Definition: cell_id.h:410
types::coarse_cell_id get_coarse_cell_id() const
Definition: cell_id.h:402
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition: point.h:111
Subscriptor & operator=(const Subscriptor &)
Definition: subscriptor.h:292
Definition: tensor.h:472
constexpr void clear()
void join() 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:3620
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:3997
virtual void clear()
bool anisotropic_refinement
Definition: tria.h:4009
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)
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition: tria.h:4067
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
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:3992
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:4016
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:4044
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:3531
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:3986
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
void load_user_pointers(const std::vector< void * > &v)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition: tria.h:4027
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
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
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
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifold
Definition: tria.h:4004
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
MeshSmoothing smooth_grid
Definition: tria.h:3525
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition: tria.h:3583
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition: tria.h:2295
virtual ~Triangulation() override
unsigned int n_vertices() const
void save_user_indices(std::vector< unsigned int > &v) const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition: tria.h:3978
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:1682
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition: tria.cc:1689
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:1665
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition: tria.cc:1659
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition: tria.cc:1696
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition: tria.cc:1675
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition: tria.cc:1704
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<::ReferenceCell > quad_reference_cell
Definition: tria_faces.h:80
std::vector< unsigned char > quads_line_orientations
Definition: tria_faces.h:73
std::vector<::ReferenceCell > reference_cell
Definition: tria_levels.h:225
std::vector< std::pair< int, int > > neighbors
Definition: tria_levels.h:148
std::vector< types::global_cell_index > global_active_cell_indices
Definition: tria_levels.h:108
std::vector< types::global_cell_index > global_level_cell_indices
Definition: tria_levels.h:113
std::vector< unsigned char > face_orientations
Definition: tria_levels.h:218
std::vector< types::subdomain_id > level_subdomain_ids
Definition: tria_levels.h:167
std::vector< std::uint8_t > refine_flags
Definition: tria_levels.h:89
std::vector< types::subdomain_id > subdomain_ids
Definition: tria_levels.h:158
std::vector< unsigned int > active_cell_indices
Definition: tria_levels.h:103
std::vector< types::manifold_id > manifold_id
Definition: tria_objects.h:185
std::vector< BoundaryOrMaterialId > boundary_or_material_id
Definition: tria_objects.h:179
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
Point< 3 > vertices[4]
Point< 2 > second
Definition: grid_out.cc:4588
Point< 2 > first
Definition: grid_out.cc:4587
unsigned int level
Definition: grid_out.cc:4590
AdjacentCell adjacent_cells[2]
Definition: grid_tools.cc:1176
unsigned int vertex_indices[2]
Definition: grid_tools.cc:1256
unsigned int cell_index
Definition: grid_tools.cc:1092
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:584
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)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:538
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1622
static ::ExceptionBase & ExcLineInexistant(int arg1, int arg2)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
Definition: exceptions.h:1528
#define AssertIndexRange(index, range)
Definition: exceptions.h:1690
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
static ::ExceptionBase & ExcFacesHaveNoLevel()
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:561
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:515
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:610
#define AssertThrow(cond, exc)
Definition: exceptions.h:1575
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition: tria.h:1361
void loop(ITERATOR begin, typename identity< ITERATOR >::type end, DOFINFO &dinfo, INFOBOX &info, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &cell_worker, const std::function< void(DOFINFO &, typename INFOBOX::CellInfo &)> &boundary_worker, const std::function< void(DOFINFO &, DOFINFO &, typename INFOBOX::CellInfo &, typename INFOBOX::CellInfo &)> &face_worker, ASSEMBLER &assembler, const LoopControl &lctrl=LoopControl())
Definition: loop.h:439
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)
const unsigned int mn_tria_refine_flags_end
Definition: magic_numbers.h:30
const unsigned int mn_tria_coarsen_flags_end
Definition: magic_numbers.h:32
const unsigned int mn_tria_refine_flags_begin
Definition: magic_numbers.h:29
const unsigned int mn_tria_hex_user_flags_end
Definition: magic_numbers.h:38
const unsigned int mn_tria_line_user_flags_begin
Definition: magic_numbers.h:33
const unsigned int mn_tria_line_user_flags_end
Definition: magic_numbers.h:34
const unsigned int mn_tria_quad_user_flags_end
Definition: magic_numbers.h:36
const unsigned int mn_tria_coarsen_flags_begin
Definition: magic_numbers.h:31
const unsigned int mn_tria_hex_user_flags_begin
Definition: magic_numbers.h:37
const unsigned int mn_tria_quad_user_flags_begin
Definition: magic_numbers.h:35
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition: mapping.cc:240
Expression fabs(const Expression &x)
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
double cell_measure(const std::vector< Point< dim > > &all_vertices, const unsigned int(&vertex_indices)[GeometryInfo< dim >::vertices_per_cell])
@ valid
Iterator points to a valid object.
static const char N
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
void swap(MemorySpaceData< Number, MemorySpace > &, MemorySpaceData< Number, MemorySpace > &)
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 Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:1111
Point< 1 > transform_real_to_unit_cell(const std::array< Point< spacedim >, GeometryInfo< 1 >::vertices_per_cell > &vertices, const Point< spacedim > &p)
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 3 > &c)
Definition: tria.cc:12617
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition: tria.cc:12594
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition: tria.cc:9982
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition: tria.cc:12587
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition: tria.cc:1118
void monitor_memory(const TriaObjects &tria_object, const unsigned int)
Definition: tria.cc:1539
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 3 > &c)
Definition: tria.cc:12624
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition: tria.cc:1321
const types::boundary_id internal_face_boundary_id
Definition: types.h:255
const types::subdomain_id invalid_subdomain_id
Definition: types.h:276
static const unsigned int invalid_unsigned_int
Definition: types.h:196
const types::manifold_id flat_manifold_id
Definition: types.h:264
const types::global_dof_index invalid_dof_index
Definition: types.h:211
TriangulationBase< dim, spacedim > Triangulation
Definition: tria_base.h:396
::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:141
unsigned int boundary_id
Definition: types.h:129
const ::parallel::distributed::Triangulation< dim, spacedim > * triangulation
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 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:1542
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition: tria.cc:9858
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition: tria.cc:9969
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:9943
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:9862
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:9928
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:9961
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:9952
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition: tria.cc:2017
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition: tria.cc:2677
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition: tria.cc:2618
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition: tria.cc:9498
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:2116
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition: tria.cc:9586
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:2971
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition: tria.cc:2640
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition: tria.cc:2110
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:5121
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in)
Definition: tria.cc:2533
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:4018
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:3601
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition: tria.cc:1910
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:9505
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition: tria.cc:1822
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition: tria.cc:9789
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:2729
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition: tria.cc:9595
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:2833
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition: tria.cc:4559
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:2295
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:4793
std::vector< unsigned int > n_active_lines_level
Definition: tria.h:183
std::vector< unsigned int > n_active_quads_level
Definition: tria.h:241
std::vector< unsigned int > n_active_hexes_level
Definition: tria.h:300