Reference documentation for deal.II version 9.4.1
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 1998 - 2022 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
481 reorder_compatibility(std::vector<CellData<2>> &cells, 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
490 reorder_compatibility(std::vector<CellData<3>> &cells,
491 SubCellData & subcelldata)
492 {
493 unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
494 for (auto &cell : cells)
495 if (cell.vertices.size() == GeometryInfo<3>::vertices_per_cell)
496 {
497 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
498 tmp[i] = cell.vertices[i];
499 for (const unsigned int i : GeometryInfo<3>::vertex_indices())
500 cell.vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
501 }
502
503 // now points in boundary quads
504 for (auto &boundary_quad : subcelldata.boundary_quads)
505 if (boundary_quad.vertices.size() == GeometryInfo<2>::vertices_per_cell)
506 std::swap(boundary_quad.vertices[2], boundary_quad.vertices[3]);
507 }
508
509
510
528 template <int dim, int spacedim>
529 unsigned int
530 middle_vertex_index(
532 {
533 if (line->has_children())
534 return line->child(0)->vertex_index(1);
536 }
537
538
539 template <int dim, int spacedim>
540 unsigned int
541 middle_vertex_index(
543 {
544 switch (static_cast<unsigned char>(quad->refinement_case()))
545 {
547 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
548 break;
550 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
551 break;
553 return quad->child(0)->vertex_index(3);
554 break;
555 default:
556 break;
557 }
559 }
560
561
562 template <int dim, int spacedim>
563 unsigned int
564 middle_vertex_index(
566 {
567 switch (static_cast<unsigned char>(hex->refinement_case()))
568 {
570 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
571 break;
573 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
574 break;
576 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
577 break;
579 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
580 break;
582 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
583 break;
585 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
586 break;
588 return hex->child(0)->vertex_index(7);
589 break;
590 default:
591 break;
592 }
594 }
595
596
609 template <class TRIANGULATION>
610 inline typename TRIANGULATION::DistortedCellList
611 collect_distorted_coarse_cells(const TRIANGULATION &)
612 {
613 return typename TRIANGULATION::DistortedCellList();
614 }
615
616
617
626 template <int dim>
628 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
629 {
630 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
631 for (const auto &cell : triangulation.cell_iterators_on_level(0))
632 {
634 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
635 vertices[i] = cell->vertex(i);
636
639
640 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
641 if (determinants[i] <= 1e-9 * std::pow(cell->diameter(), 1. * dim))
642 {
643 distorted_cells.distorted_cells.push_back(cell);
644 break;
645 }
646 }
647
648 return distorted_cells;
649 }
650
651
658 template <int dim>
659 bool
660 has_distorted_children(
661 const typename Triangulation<dim, dim>::cell_iterator &cell)
662 {
663 Assert(cell->has_children(), ExcInternalError());
664
665 for (unsigned int c = 0; c < cell->n_children(); ++c)
666 {
668 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
669 vertices[i] = cell->child(c)->vertex(i);
670
673
674 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
675 if (determinants[i] <=
676 1e-9 * std::pow(cell->child(c)->diameter(), 1. * dim))
677 return true;
678 }
679
680 return false;
681 }
682
683
691 template <int dim, int spacedim>
692 bool
693 has_distorted_children(
695 {
696 return false;
697 }
698
699
700 template <int dim, int spacedim>
701 void
702 update_periodic_face_map_recursively(
703 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
704 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
705 unsigned int n_face_1,
706 unsigned int n_face_2,
707 const std::bitset<3> & orientation,
708 typename std::map<
710 unsigned int>,
711 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
712 unsigned int>,
713 std::bitset<3>>> &periodic_face_map)
714 {
715 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
716 const FaceIterator face_1 = cell_1->face(n_face_1);
717 const FaceIterator face_2 = cell_2->face(n_face_2);
718
719 const bool face_orientation = orientation[0];
720 const bool face_flip = orientation[1];
721 const bool face_rotation = orientation[2];
722
723 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
724 face_rotation == false),
725 ExcMessage("The supplied orientation "
726 "(face_orientation, face_flip, face_rotation) "
727 "is invalid for 1D"));
728
729 Assert((dim != 2) || (face_orientation == true && face_rotation == false),
730 ExcMessage("The supplied orientation "
731 "(face_orientation, face_flip, face_rotation) "
732 "is invalid for 2D"));
733
734 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
735
736 Assert(face_1->at_boundary() && face_2->at_boundary(),
737 ExcMessage("Periodic faces must be on the boundary"));
738
739 // Check if the requirement that each edge can only have at most one hanging
740 // node, and as a consequence neighboring cells can differ by at most
741 // one refinement level is enforced. In 1d, there are no hanging nodes and
742 // so neighboring cells can differ by more than one refinement level.
743 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
745
746 // insert periodic face pair for both cells
747 using CellFace =
748 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
749 unsigned int>;
750 const CellFace cell_face_1(cell_1, n_face_1);
751 const CellFace cell_face_2(cell_2, n_face_2);
752 const std::pair<CellFace, std::bitset<3>> cell_face_orientation_2(
753 cell_face_2, orientation);
754
755 const std::pair<CellFace, std::pair<CellFace, std::bitset<3>>>
756 periodic_faces(cell_face_1, cell_face_orientation_2);
757
758 // Only one periodic neighbor is allowed
759 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
760 periodic_face_map.insert(periodic_faces);
761
762 if (dim == 1)
763 {
764 if (cell_1->has_children())
765 {
766 if (cell_2->has_children())
767 {
768 update_periodic_face_map_recursively<dim, spacedim>(
769 cell_1->child(n_face_1),
770 cell_2->child(n_face_2),
771 n_face_1,
772 n_face_2,
773 orientation,
774 periodic_face_map);
775 }
776 else // only face_1 has children
777 {
778 update_periodic_face_map_recursively<dim, spacedim>(
779 cell_1->child(n_face_1),
780 cell_2,
781 n_face_1,
782 n_face_2,
783 orientation,
784 periodic_face_map);
785 }
786 }
787 }
788 else // dim == 2 || dim == 3
789 {
790 // A lookup table on how to go through the child cells depending on the
791 // orientation:
792 // see Documentation of GeometryInfo for details
793
794 static const int lookup_table_2d[2][2] =
795 // flip:
796 {
797 {0, 1}, // false
798 {1, 0} // true
799 };
800
801 static const int lookup_table_3d[2][2][2][4] =
802 // orientation flip rotation
803 {{{
804 {0, 2, 1, 3}, // false false false
805 {2, 3, 0, 1} // false false true
806 },
807 {
808 {3, 1, 2, 0}, // false true false
809 {1, 0, 3, 2} // false true true
810 }},
811 {{
812 {0, 1, 2, 3}, // true false false
813 {1, 3, 0, 2} // true false true
814 },
815 {
816 {3, 2, 1, 0}, // true true false
817 {2, 0, 3, 1} // true true true
818 }}};
819
820 if (cell_1->has_children())
821 {
822 if (cell_2->has_children())
823 {
824 // In the case that both faces have children, we loop over all
825 // children and apply update_periodic_face_map_recursively
826 // recursively:
827
828 Assert(face_1->n_children() ==
830 face_2->n_children() ==
833
834 for (unsigned int i = 0;
835 i < GeometryInfo<dim>::max_children_per_face;
836 ++i)
837 {
838 // Lookup the index for the second face
839 unsigned int j = 0;
840 switch (dim)
841 {
842 case 2:
843 j = lookup_table_2d[face_flip][i];
844 break;
845 case 3:
846 j = lookup_table_3d[face_orientation][face_flip]
847 [face_rotation][i];
848 break;
849 default:
851 }
852
853 // find subcell ids that belong to the subface indices
854 unsigned int child_cell_1 =
856 cell_1->refinement_case(),
857 n_face_1,
858 i,
859 cell_1->face_orientation(n_face_1),
860 cell_1->face_flip(n_face_1),
861 cell_1->face_rotation(n_face_1),
862 face_1->refinement_case());
863 unsigned int child_cell_2 =
865 cell_2->refinement_case(),
866 n_face_2,
867 j,
868 cell_2->face_orientation(n_face_2),
869 cell_2->face_flip(n_face_2),
870 cell_2->face_rotation(n_face_2),
871 face_2->refinement_case());
872
873 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
874 face_1->child(i),
876 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
877 face_2->child(j),
879
880 // precondition: subcell has the same orientation as cell
881 // (so that the face numbers coincide) recursive call
882 update_periodic_face_map_recursively<dim, spacedim>(
883 cell_1->child(child_cell_1),
884 cell_2->child(child_cell_2),
885 n_face_1,
886 n_face_2,
887 orientation,
888 periodic_face_map);
889 }
890 }
891 else // only face_1 has children
892 {
893 for (unsigned int i = 0;
894 i < GeometryInfo<dim>::max_children_per_face;
895 ++i)
896 {
897 // find subcell ids that belong to the subface indices
898 unsigned int child_cell_1 =
900 cell_1->refinement_case(),
901 n_face_1,
902 i,
903 cell_1->face_orientation(n_face_1),
904 cell_1->face_flip(n_face_1),
905 cell_1->face_rotation(n_face_1),
906 face_1->refinement_case());
907
908 // recursive call
909 update_periodic_face_map_recursively<dim, spacedim>(
910 cell_1->child(child_cell_1),
911 cell_2,
912 n_face_1,
913 n_face_2,
914 orientation,
915 periodic_face_map);
916 }
917 }
918 }
919 }
920 }
921
922
923} // end of anonymous namespace
924
925
926namespace internal
927{
928 namespace TriangulationImplementation
929 {
930 // make sure that if in the following we
931 // write Triangulation<dim,spacedim>
932 // we mean the *class*
933 // ::Triangulation, not the
934 // enclosing namespace
935 // internal::TriangulationImplementation
936 using ::Triangulation;
937
943 int,
944 << "Something went wrong when making cell " << arg1
945 << ". Read the docs and the source code "
946 << "for more information.");
952 int,
953 << "Something went wrong upon construction of cell "
954 << arg1);
965 int,
966 << "Cell " << arg1
967 << " has negative measure. This typically "
968 << "indicates some distortion in the cell, or a mistakenly "
969 << "swapped pair of vertices in the input to "
970 << "Triangulation::create_triangulation().");
979 int,
980 int,
981 int,
982 << "Error while creating cell " << arg1
983 << ": the vertex index " << arg2 << " must be between 0 and "
984 << arg3 << '.');
990 int,
991 int,
992 << "While trying to assign a boundary indicator to a line: "
993 << "the line with end vertices " << arg1 << " and " << arg2
994 << " does not exist.");
1000 int,
1001 int,
1002 int,
1003 int,
1004 << "While trying to assign a boundary indicator to a quad: "
1005 << "the quad with bounding lines " << arg1 << ", " << arg2
1006 << ", " << arg3 << ", " << arg4 << " does not exist.");
1013 int,
1014 int,
1016 << "The input data for creating a triangulation contained "
1017 << "information about a line with indices " << arg1 << " and " << arg2
1018 << " that is described to have boundary indicator "
1019 << static_cast<int>(arg3)
1020 << ". However, this is an internal line not located on the "
1021 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1022 << std::endl
1023 << "If this happened at a place where you call "
1024 << "Triangulation::create_triangulation() yourself, you need "
1025 << "to check the SubCellData object you pass to this function."
1026 << std::endl
1027 << std::endl
1028 << "If this happened in a place where you are reading a mesh "
1029 << "from a file, then you need to investigate why such a line "
1030 << "ended up in the input file. A typical case is a geometry "
1031 << "that consisted of multiple parts and for which the mesh "
1032 << "generator program assumes that the interface between "
1033 << "two parts is a boundary when that isn't supposed to be "
1034 << "the case, or where the mesh generator simply assigns "
1035 << "'geometry indicators' to lines at the perimeter of "
1036 << "a part that are not supposed to be interpreted as "
1037 << "'boundary indicators'.");
1044 int,
1045 int,
1046 int,
1047 int,
1049 << "The input data for creating a triangulation contained "
1050 << "information about a quad with indices " << arg1 << ", " << arg2
1051 << ", " << arg3 << ", and " << arg4
1052 << " that is described to have boundary indicator "
1053 << static_cast<int>(arg5)
1054 << ". However, this is an internal quad not located on the "
1055 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1056 << std::endl
1057 << "If this happened at a place where you call "
1058 << "Triangulation::create_triangulation() yourself, you need "
1059 << "to check the SubCellData object you pass to this function."
1060 << std::endl
1061 << std::endl
1062 << "If this happened in a place where you are reading a mesh "
1063 << "from a file, then you need to investigate why such a quad "
1064 << "ended up in the input file. A typical case is a geometry "
1065 << "that consisted of multiple parts and for which the mesh "
1066 << "generator program assumes that the interface between "
1067 << "two parts is a boundary when that isn't supposed to be "
1068 << "the case, or where the mesh generator simply assigns "
1069 << "'geometry indicators' to quads at the surface of "
1070 << "a part that are not supposed to be interpreted as "
1071 << "'boundary indicators'.");
1078 int,
1079 int,
1080 << "In SubCellData the line info of the line with vertex indices " << arg1
1081 << " and " << arg2 << " appears more than once. "
1082 << "This is not allowed.");
1089 int,
1090 int,
1091 std::string,
1092 << "In SubCellData the line info of the line with vertex indices " << arg1
1093 << " and " << arg2 << " appears multiple times with different (valid) "
1094 << arg3 << ". This is not allowed.");
1101 int,
1102 int,
1103 int,
1104 int,
1105 std::string,
1106 << "In SubCellData the quad info of the quad with line indices " << arg1
1107 << ", " << arg2 << ", " << arg3 << " and " << arg4
1108 << " appears multiple times with different (valid) " << arg5
1109 << ". This is not allowed.");
1110
1111 /*
1112 * Reserve space for TriaFaces. Details:
1113 *
1114 * Reserve space for line_orientations.
1115 *
1116 * @note Used only for dim=3.
1117 */
1118 void
1120 const unsigned int new_quads_in_pairs,
1121 const unsigned int new_quads_single)
1122 {
1123 AssertDimension(tria_faces.dim, 3);
1124
1125 Assert(new_quads_in_pairs % 2 == 0, ExcInternalError());
1126
1127 unsigned int next_free_single = 0;
1128 unsigned int next_free_pair = 0;
1129
1130 // count the number of objects, of unused single objects and of
1131 // unused pairs of objects
1132 unsigned int n_quads = 0;
1133 unsigned int n_unused_pairs = 0;
1134 unsigned int n_unused_singles = 0;
1135 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
1136 {
1137 if (tria_faces.quads.used[i])
1138 ++n_quads;
1139 else if (i + 1 < tria_faces.quads.used.size())
1140 {
1141 if (tria_faces.quads.used[i + 1])
1142 {
1143 ++n_unused_singles;
1144 if (next_free_single == 0)
1145 next_free_single = i;
1146 }
1147 else
1148 {
1149 ++n_unused_pairs;
1150 if (next_free_pair == 0)
1151 next_free_pair = i;
1152 ++i;
1153 }
1154 }
1155 else
1156 ++n_unused_singles;
1157 }
1158 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
1159 tria_faces.quads.used.size(),
1161
1162 // how many single quads are needed in addition to n_unused_quads?
1163 const int additional_single_quads = new_quads_single - n_unused_singles;
1164
1165 unsigned int new_size =
1166 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
1167 if (additional_single_quads > 0)
1168 new_size += additional_single_quads;
1169
1170 // see above...
1171 if (new_size > tria_faces.quads.n_objects())
1172 {
1173 // reserve the field of the derived class
1174 tria_faces.quads_line_orientations.reserve(
1176 tria_faces.quads_line_orientations.insert(
1177 tria_faces.quads_line_orientations.end(),
1179 tria_faces.quads_line_orientations.size(),
1180 1u);
1181
1182 tria_faces.quad_reference_cell.reserve(new_size);
1183 tria_faces.quad_reference_cell.insert(
1184 tria_faces.quad_reference_cell.end(),
1185 new_size - tria_faces.quad_reference_cell.size(),
1187 }
1188 }
1189
1190
1191
1205 void
1207 const unsigned int total_cells,
1208 const unsigned int dimension,
1209 const unsigned int space_dimension)
1210 {
1211 // we need space for total_cells cells. Maybe we have more already
1212 // with those cells which are unused, so only allocate new space if
1213 // needed.
1214 //
1215 // note that all arrays should have equal sizes (checked by
1216 // @p{monitor_memory}
1217 if (total_cells > tria_level.refine_flags.size())
1218 {
1219 tria_level.refine_flags.reserve(total_cells);
1220 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
1221 total_cells -
1222 tria_level.refine_flags.size(),
1223 /*RefinementCase::no_refinement=*/0);
1224
1225 tria_level.coarsen_flags.reserve(total_cells);
1226 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
1227 total_cells -
1228 tria_level.coarsen_flags.size(),
1229 false);
1230
1231 tria_level.active_cell_indices.reserve(total_cells);
1232 tria_level.active_cell_indices.insert(
1233 tria_level.active_cell_indices.end(),
1234 total_cells - tria_level.active_cell_indices.size(),
1236
1237 tria_level.subdomain_ids.reserve(total_cells);
1238 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
1239 total_cells -
1240 tria_level.subdomain_ids.size(),
1241 0);
1242
1243 tria_level.level_subdomain_ids.reserve(total_cells);
1244 tria_level.level_subdomain_ids.insert(
1245 tria_level.level_subdomain_ids.end(),
1246 total_cells - tria_level.level_subdomain_ids.size(),
1247 0);
1248
1249 tria_level.global_active_cell_indices.reserve(total_cells);
1250 tria_level.global_active_cell_indices.insert(
1251 tria_level.global_active_cell_indices.end(),
1252 total_cells - tria_level.global_active_cell_indices.size(),
1254
1255 tria_level.global_level_cell_indices.reserve(total_cells);
1256 tria_level.global_level_cell_indices.insert(
1257 tria_level.global_level_cell_indices.end(),
1258 total_cells - tria_level.global_level_cell_indices.size(),
1260
1261 if (dimension < space_dimension)
1262 {
1263 tria_level.direction_flags.reserve(total_cells);
1264 tria_level.direction_flags.insert(
1265 tria_level.direction_flags.end(),
1266 total_cells - tria_level.direction_flags.size(),
1267 true);
1268 }
1269 else
1270 tria_level.direction_flags.clear();
1271
1272 tria_level.parents.reserve((total_cells + 1) / 2);
1273 tria_level.parents.insert(tria_level.parents.end(),
1274 (total_cells + 1) / 2 -
1275 tria_level.parents.size(),
1276 -1);
1277
1278 tria_level.neighbors.reserve(total_cells * (2 * dimension));
1279 tria_level.neighbors.insert(tria_level.neighbors.end(),
1280 total_cells * (2 * dimension) -
1281 tria_level.neighbors.size(),
1282 std::make_pair(-1, -1));
1283
1284 if (tria_level.dim == 2 || tria_level.dim == 3)
1285 {
1286 const unsigned int max_faces_per_cell = 2 * dimension;
1287 tria_level.face_orientations.reserve(total_cells *
1288 max_faces_per_cell);
1289 tria_level.face_orientations.insert(
1290 tria_level.face_orientations.end(),
1291 total_cells * max_faces_per_cell -
1292 tria_level.face_orientations.size(),
1293 1u);
1294
1295 tria_level.reference_cell.reserve(total_cells);
1296 tria_level.reference_cell.insert(
1297 tria_level.reference_cell.end(),
1298 total_cells - tria_level.reference_cell.size(),
1299 tria_level.dim == 2 ? ::ReferenceCells::Quadrilateral :
1301 }
1302 }
1303 }
1304
1305
1306
1311 int,
1312 int,
1313 << "The containers have sizes " << arg1 << " and " << arg2
1314 << ", which is not as expected.");
1315
1321 void
1322 monitor_memory(const TriaLevel & tria_level,
1323 const unsigned int true_dimension)
1324 {
1325 (void)tria_level;
1326 (void)true_dimension;
1327 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
1328 tria_level.neighbors.size(),
1329 ExcMemoryInexact(tria_level.refine_flags.size(),
1330 tria_level.neighbors.size()));
1331 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
1332 tria_level.neighbors.size(),
1333 ExcMemoryInexact(tria_level.coarsen_flags.size(),
1334 tria_level.neighbors.size()));
1335 }
1336
1337
1338
1351 void
1353 const unsigned int new_objects_in_pairs,
1354 const unsigned int new_objects_single = 0)
1355 {
1356 if (tria_objects.structdim <= 2)
1357 {
1358 Assert(new_objects_in_pairs % 2 == 0, ExcInternalError());
1359
1360 tria_objects.next_free_single = 0;
1361 tria_objects.next_free_pair = 0;
1362 tria_objects.reverse_order_next_free_single = false;
1363
1364 // count the number of objects, of unused single objects and of
1365 // unused pairs of objects
1366 unsigned int n_objects = 0;
1367 unsigned int n_unused_pairs = 0;
1368 unsigned int n_unused_singles = 0;
1369 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
1370 {
1371 if (tria_objects.used[i])
1372 ++n_objects;
1373 else if (i + 1 < tria_objects.used.size())
1374 {
1375 if (tria_objects.used[i + 1])
1376 {
1377 ++n_unused_singles;
1378 if (tria_objects.next_free_single == 0)
1379 tria_objects.next_free_single = i;
1380 }
1381 else
1382 {
1383 ++n_unused_pairs;
1384 if (tria_objects.next_free_pair == 0)
1385 tria_objects.next_free_pair = i;
1386 ++i;
1387 }
1388 }
1389 else
1390 ++n_unused_singles;
1391 }
1392 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
1393 tria_objects.used.size(),
1395
1396 // how many single objects are needed in addition to
1397 // n_unused_objects?
1398 const int additional_single_objects =
1399 new_objects_single - n_unused_singles;
1400
1401 unsigned int new_size = tria_objects.used.size() +
1402 new_objects_in_pairs - 2 * n_unused_pairs;
1403 if (additional_single_objects > 0)
1404 new_size += additional_single_objects;
1405
1406 // only allocate space if necessary
1407 if (new_size > tria_objects.n_objects())
1408 {
1409 const unsigned int max_faces_per_cell =
1410 2 * tria_objects.structdim;
1411 const unsigned int max_children_per_cell =
1412 1 << tria_objects.structdim;
1413
1414 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1415 tria_objects.cells.insert(tria_objects.cells.end(),
1416 (new_size - tria_objects.n_objects()) *
1417 max_faces_per_cell,
1418 -1);
1419
1420 tria_objects.used.reserve(new_size);
1421 tria_objects.used.insert(tria_objects.used.end(),
1422 new_size - tria_objects.used.size(),
1423 false);
1424
1425 tria_objects.user_flags.reserve(new_size);
1426 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1427 new_size -
1428 tria_objects.user_flags.size(),
1429 false);
1430
1431 const unsigned int factor = max_children_per_cell / 2;
1432 tria_objects.children.reserve(factor * new_size);
1433 tria_objects.children.insert(tria_objects.children.end(),
1434 factor * new_size -
1435 tria_objects.children.size(),
1436 -1);
1437
1438 if (tria_objects.structdim > 1)
1439 {
1440 tria_objects.refinement_cases.reserve(new_size);
1441 tria_objects.refinement_cases.insert(
1442 tria_objects.refinement_cases.end(),
1443 new_size - tria_objects.refinement_cases.size(),
1444 /*RefinementCase::no_refinement=*/0);
1445 }
1446
1447 // first reserve, then resize. Otherwise the std library can
1448 // decide to allocate more entries.
1449 tria_objects.boundary_or_material_id.reserve(new_size);
1450 tria_objects.boundary_or_material_id.resize(new_size);
1451
1452 tria_objects.user_data.reserve(new_size);
1453 tria_objects.user_data.resize(new_size);
1454
1455 tria_objects.manifold_id.reserve(new_size);
1456 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1457 new_size -
1458 tria_objects.manifold_id.size(),
1460 }
1461
1462 if (n_unused_singles == 0)
1463 {
1464 tria_objects.next_free_single = new_size - 1;
1465 tria_objects.reverse_order_next_free_single = true;
1466 }
1467 }
1468 else
1469 {
1470 const unsigned int new_hexes = new_objects_in_pairs;
1471
1472 const unsigned int new_size =
1473 new_hexes + std::count(tria_objects.used.begin(),
1474 tria_objects.used.end(),
1475 true);
1476
1477 // see above...
1478 if (new_size > tria_objects.n_objects())
1479 {
1480 const unsigned int max_faces_per_cell =
1481 2 * tria_objects.structdim;
1482
1483 tria_objects.cells.reserve(new_size * max_faces_per_cell);
1484 tria_objects.cells.insert(tria_objects.cells.end(),
1485 (new_size - tria_objects.n_objects()) *
1486 max_faces_per_cell,
1487 -1);
1488
1489 tria_objects.used.reserve(new_size);
1490 tria_objects.used.insert(tria_objects.used.end(),
1491 new_size - tria_objects.used.size(),
1492 false);
1493
1494 tria_objects.user_flags.reserve(new_size);
1495 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
1496 new_size -
1497 tria_objects.user_flags.size(),
1498 false);
1499
1500 tria_objects.children.reserve(4 * new_size);
1501 tria_objects.children.insert(tria_objects.children.end(),
1502 4 * new_size -
1503 tria_objects.children.size(),
1504 -1);
1505
1506 // for the following fields, we know exactly how many elements
1507 // we need, so first reserve then resize (resize itself, at least
1508 // with some compiler libraries, appears to round up the size it
1509 // actually reserves)
1510 tria_objects.boundary_or_material_id.reserve(new_size);
1511 tria_objects.boundary_or_material_id.resize(new_size);
1512
1513 tria_objects.manifold_id.reserve(new_size);
1514 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
1515 new_size -
1516 tria_objects.manifold_id.size(),
1518
1519 tria_objects.user_data.reserve(new_size);
1520 tria_objects.user_data.resize(new_size);
1521
1522 tria_objects.refinement_cases.reserve(new_size);
1523 tria_objects.refinement_cases.insert(
1524 tria_objects.refinement_cases.end(),
1525 new_size - tria_objects.refinement_cases.size(),
1526 /*RefinementCase::no_refinement=*/0);
1527 }
1528 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
1529 }
1530 }
1531
1532
1533
1539 void
1540 monitor_memory(const TriaObjects &tria_object, const unsigned int)
1541 {
1542 Assert(tria_object.n_objects() == tria_object.used.size(),
1543 ExcMemoryInexact(tria_object.n_objects(),
1544 tria_object.used.size()));
1545 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
1546 ExcMemoryInexact(tria_object.n_objects(),
1547 tria_object.user_flags.size()));
1548 Assert(tria_object.n_objects() ==
1549 tria_object.boundary_or_material_id.size(),
1550 ExcMemoryInexact(tria_object.n_objects(),
1551 tria_object.boundary_or_material_id.size()));
1552 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
1553 ExcMemoryInexact(tria_object.n_objects(),
1554 tria_object.manifold_id.size()));
1555 Assert(tria_object.n_objects() == tria_object.user_data.size(),
1556 ExcMemoryInexact(tria_object.n_objects(),
1557 tria_object.user_data.size()));
1558
1559 if (tria_object.structdim == 1)
1560 {
1561 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
1562 ExcMemoryInexact(tria_object.n_objects(),
1563 tria_object.children.size()));
1564 }
1565 else if (tria_object.structdim == 2)
1566 {
1567 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
1568 ExcMemoryInexact(tria_object.n_objects(),
1569 tria_object.children.size()));
1570 }
1571 else if (tria_object.structdim == 3)
1572 {
1573 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
1574 ExcMemoryInexact(tria_object.n_objects(),
1575 tria_object.children.size()));
1576 }
1577 }
1578
1579
1580
1585 template <int dim, int spacedim>
1587 {
1588 public:
1592 virtual ~Policy() = default;
1593
1597 virtual void
1599
1603 virtual void
1607 std::vector<unsigned int> & line_cell_count,
1608 std::vector<unsigned int> &quad_cell_count) = 0;
1609
1615 const bool check_for_distorted_cells) = 0;
1616
1620 virtual void
1623
1627 virtual void
1630
1634 virtual bool
1636 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
1637
1644 virtual std::unique_ptr<Policy<dim, spacedim>>
1645 clone() = 0;
1646 };
1647
1648
1649
1655 template <int dim, int spacedim, typename T>
1656 class PolicyWrapper : public Policy<dim, spacedim>
1657 {
1658 public:
1659 void
1661 {
1662 T::update_neighbors(tria);
1663 }
1664
1665 void
1669 std::vector<unsigned int> & line_cell_count,
1670 std::vector<unsigned int> &quad_cell_count) override
1671 {
1672 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
1673 }
1674
1677 const bool check_for_distorted_cells) override
1678 {
1679 return T::execute_refinement(triangulation, check_for_distorted_cells);
1680 }
1681
1682 void
1685 {
1686 T::prevent_distorted_boundary_cells(triangulation);
1687 }
1688
1689 void
1692 {
1693 T::prepare_refinement_dim_dependent(triangulation);
1694 }
1695
1696 bool
1699 override
1700 {
1701 return T::template coarsening_allowed<dim, spacedim>(cell);
1702 }
1703
1704 std::unique_ptr<Policy<dim, spacedim>>
1705 clone() override
1706 {
1707 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
1708 }
1709 };
1710
1711
1712
1809 {
1821 template <int dim, int spacedim>
1822 static void
1825 const unsigned int level_objects,
1827 {
1828 using line_iterator =
1830
1831 number_cache.n_levels = 0;
1832 if (level_objects > 0)
1833 // find the last level on which there are used cells
1834 for (unsigned int level = 0; level < level_objects; ++level)
1835 if (triangulation.begin(level) != triangulation.end(level))
1836 number_cache.n_levels = level + 1;
1837
1838 // no cells at all?
1839 Assert(number_cache.n_levels > 0, ExcInternalError());
1840
1841 //---------------------------------
1842 // update the number of lines on the different levels in the
1843 // cache
1844 number_cache.n_lines = 0;
1845 number_cache.n_active_lines = 0;
1846
1847 // for 1d, lines have levels so take count the objects per
1848 // level and globally
1849 if (dim == 1)
1850 {
1851 number_cache.n_lines_level.resize(number_cache.n_levels);
1852 number_cache.n_active_lines_level.resize(number_cache.n_levels);
1853
1854 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
1855 {
1856 // count lines on this level
1857 number_cache.n_lines_level[level] = 0;
1858 number_cache.n_active_lines_level[level] = 0;
1859
1860 line_iterator line = triangulation.begin_line(level),
1861 endc =
1862 (level == number_cache.n_levels - 1 ?
1863 line_iterator(triangulation.end_line()) :
1864 triangulation.begin_line(level + 1));
1865 for (; line != endc; ++line)
1866 {
1867 ++number_cache.n_lines_level[level];
1868 if (line->has_children() == false)
1869 ++number_cache.n_active_lines_level[level];
1870 }
1871
1872 // update total number of lines
1873 number_cache.n_lines += number_cache.n_lines_level[level];
1874 number_cache.n_active_lines +=
1875 number_cache.n_active_lines_level[level];
1876 }
1877 }
1878 else
1879 {
1880 // for dim>1, there are no levels for lines
1881 number_cache.n_lines_level.clear();
1882 number_cache.n_active_lines_level.clear();
1883
1884 line_iterator line = triangulation.begin_line(),
1885 endc = triangulation.end_line();
1886 for (; line != endc; ++line)
1887 {
1888 ++number_cache.n_lines;
1889 if (line->has_children() == false)
1890 ++number_cache.n_active_lines;
1891 }
1892 }
1893 }
1894
1909 template <int dim, int spacedim>
1910 static void
1913 const unsigned int level_objects,
1915 {
1916 // update lines and n_levels in number_cache. since we don't
1917 // access any of these numbers, we can do this in the
1918 // background
1920 static_cast<
1921 void (*)(const Triangulation<dim, spacedim> &,
1922 const unsigned int,
1924 &compute_number_cache<dim, spacedim>),
1926 level_objects,
1928 number_cache));
1929
1930 using quad_iterator =
1932
1933 //---------------------------------
1934 // update the number of quads on the different levels in the
1935 // cache
1936 number_cache.n_quads = 0;
1937 number_cache.n_active_quads = 0;
1938
1939 // for 2d, quads have levels so take count the objects per
1940 // level and globally
1941 if (dim == 2)
1942 {
1943 // count the number of levels; the function we called above
1944 // on a separate Task for lines also does this and puts it into
1945 // number_cache.n_levels, but this datum may not yet be
1946 // available as we call the function on a separate task
1947 unsigned int n_levels = 0;
1948 if (level_objects > 0)
1949 // find the last level on which there are used cells
1950 for (unsigned int level = 0; level < level_objects; ++level)
1951 if (triangulation.begin(level) != triangulation.end(level))
1952 n_levels = level + 1;
1953
1954 number_cache.n_quads_level.resize(n_levels);
1955 number_cache.n_active_quads_level.resize(n_levels);
1956
1957 for (unsigned int level = 0; level < n_levels; ++level)
1958 {
1959 // count quads on this level
1960 number_cache.n_quads_level[level] = 0;
1961 number_cache.n_active_quads_level[level] = 0;
1962
1963 quad_iterator quad = triangulation.begin_quad(level),
1964 endc =
1965 (level == n_levels - 1 ?
1966 quad_iterator(triangulation.end_quad()) :
1967 triangulation.begin_quad(level + 1));
1968 for (; quad != endc; ++quad)
1969 {
1970 ++number_cache.n_quads_level[level];
1971 if (quad->has_children() == false)
1972 ++number_cache.n_active_quads_level[level];
1973 }
1974
1975 // update total number of quads
1976 number_cache.n_quads += number_cache.n_quads_level[level];
1977 number_cache.n_active_quads +=
1978 number_cache.n_active_quads_level[level];
1979 }
1980 }
1981 else
1982 {
1983 // for dim>2, there are no levels for quads
1984 number_cache.n_quads_level.clear();
1985 number_cache.n_active_quads_level.clear();
1986
1987 quad_iterator quad = triangulation.begin_quad(),
1988 endc = triangulation.end_quad();
1989 for (; quad != endc; ++quad)
1990 {
1991 ++number_cache.n_quads;
1992 if (quad->has_children() == false)
1993 ++number_cache.n_active_quads;
1994 }
1995 }
1996
1997 // wait for the background computation for lines
1998 update_lines.join();
1999 }
2000
2016 template <int dim, int spacedim>
2017 static void
2020 const unsigned int level_objects,
2022 {
2023 // update quads, lines and n_levels in number_cache. since we
2024 // don't access any of these numbers, we can do this in the
2025 // background
2026 Threads::Task<void> update_quads_and_lines = Threads::new_task(
2027 static_cast<
2028 void (*)(const Triangulation<dim, spacedim> &,
2029 const unsigned int,
2031 &compute_number_cache<dim, spacedim>),
2033 level_objects,
2035 number_cache));
2036
2037 using hex_iterator =
2039
2040 //---------------------------------
2041 // update the number of hexes on the different levels in the
2042 // cache
2043 number_cache.n_hexes = 0;
2044 number_cache.n_active_hexes = 0;
2045
2046 // for 3d, hexes have levels so take count the objects per
2047 // level and globally
2048 if (dim == 3)
2049 {
2050 // count the number of levels; the function we called
2051 // above on a separate Task for quads (recursively, via
2052 // the lines function) also does this and puts it into
2053 // number_cache.n_levels, but this datum may not yet be
2054 // available as we call the function on a separate task
2055 unsigned int n_levels = 0;
2056 if (level_objects > 0)
2057 // find the last level on which there are used cells
2058 for (unsigned int level = 0; level < level_objects; ++level)
2059 if (triangulation.begin(level) != triangulation.end(level))
2060 n_levels = level + 1;
2061
2062 number_cache.n_hexes_level.resize(n_levels);
2063 number_cache.n_active_hexes_level.resize(n_levels);
2064
2065 for (unsigned int level = 0; level < n_levels; ++level)
2066 {
2067 // count hexes on this level
2068 number_cache.n_hexes_level[level] = 0;
2069 number_cache.n_active_hexes_level[level] = 0;
2070
2071 hex_iterator hex = triangulation.begin_hex(level),
2072 endc = (level == n_levels - 1 ?
2073 hex_iterator(triangulation.end_hex()) :
2074 triangulation.begin_hex(level + 1));
2075 for (; hex != endc; ++hex)
2076 {
2077 ++number_cache.n_hexes_level[level];
2078 if (hex->has_children() == false)
2079 ++number_cache.n_active_hexes_level[level];
2080 }
2081
2082 // update total number of hexes
2083 number_cache.n_hexes += number_cache.n_hexes_level[level];
2084 number_cache.n_active_hexes +=
2085 number_cache.n_active_hexes_level[level];
2086 }
2087 }
2088 else
2089 {
2090 // for dim>3, there are no levels for hexes
2091 number_cache.n_hexes_level.clear();
2092 number_cache.n_active_hexes_level.clear();
2093
2094 hex_iterator hex = triangulation.begin_hex(),
2095 endc = triangulation.end_hex();
2096 for (; hex != endc; ++hex)
2097 {
2098 ++number_cache.n_hexes;
2099 if (hex->has_children() == false)
2100 ++number_cache.n_active_hexes;
2101 }
2102 }
2103
2104 // wait for the background computation for quads
2105 update_quads_and_lines.join();
2106 }
2107
2108
2109
2110 template <int spacedim>
2111 static void
2113 {}
2114
2115
2116 template <int dim, int spacedim>
2117 static void
2119 {
2120 // each face can be neighbored on two sides
2121 // by cells. according to the face's
2122 // intrinsic normal we define the left
2123 // neighbor as the one for which the face
2124 // normal points outward, and store that
2125 // one first; the second one is then
2126 // the right neighbor for which the
2127 // face normal points inward. This
2128 // information depends on the type of cell
2129 // and local number of face for the
2130 // 'standard ordering and orientation' of
2131 // faces and then on the face_orientation
2132 // information for the real mesh. Set up a
2133 // table to have fast access to those
2134 // offsets (0 for left and 1 for
2135 // right). Some of the values are invalid
2136 // as they reference too large face
2137 // numbers, but we just leave them at a
2138 // zero value.
2139 //
2140 // Note, that in 2d for lines as faces the
2141 // normal direction given in the
2142 // GeometryInfo class is not consistent. We
2143 // thus define here that the normal for a
2144 // line points to the right if the line
2145 // points upwards.
2146 //
2147 // There is one more point to
2148 // consider, however: if we have
2149 // dim<spacedim, then we may have
2150 // cases where cells are
2151 // inverted. In effect, both
2152 // cells think they are the left
2153 // neighbor of an edge, for
2154 // example, which leads us to
2155 // forget neighborship
2156 // information (a case that shows
2157 // this is
2158 // codim_one/hanging_nodes_02). We
2159 // store whether a cell is
2160 // inverted using the
2161 // direction_flag, so if a cell
2162 // has a false direction_flag,
2163 // then we need to invert our
2164 // selection whether we are a
2165 // left or right neighbor in all
2166 // following computations.
2167 //
2168 // first index: dimension (minus 2)
2169 // second index: local face index
2170 // third index: face_orientation (false and true)
2171 static const unsigned int left_right_offset[2][6][2] = {
2172 // quadrilateral
2173 {{0, 1}, // face 0, face_orientation = false and true
2174 {1, 0}, // face 1, face_orientation = false and true
2175 {1, 0}, // face 2, face_orientation = false and true
2176 {0, 1}, // face 3, face_orientation = false and true
2177 {0, 0}, // face 4, invalid face
2178 {0, 0}}, // face 5, invalid face
2179 // hexahedron
2180 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
2181
2182 // now create a vector of the two active
2183 // neighbors (left and right) for each face
2184 // and fill it by looping over all cells. For
2185 // cases with anisotropic refinement and more
2186 // then one cell neighboring at a given side
2187 // of the face we will automatically get the
2188 // active one on the highest level as we loop
2189 // over cells from lower levels first.
2191 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
2192 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
2193
2194 for (const auto &cell : triangulation.cell_iterators())
2195 for (auto f : cell->face_indices())
2196 {
2198 cell->face(f);
2199
2200 const unsigned int offset =
2201 (cell->direction_flag() ?
2202 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2203 1 -
2204 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2205
2206 adjacent_cells[2 * face->index() + offset] = cell;
2207
2208 // if this cell is not refined, but the
2209 // face is, then we'll have to set our
2210 // cell as neighbor for the child faces
2211 // as well. Fortunately the normal
2212 // orientation of children will be just
2213 // the same.
2214 if (dim == 2)
2215 {
2216 if (cell->is_active() && face->has_children())
2217 {
2218 adjacent_cells[2 * face->child(0)->index() + offset] =
2219 cell;
2220 adjacent_cells[2 * face->child(1)->index() + offset] =
2221 cell;
2222 }
2223 }
2224 else // -> dim == 3
2225 {
2226 // We need the same as in 2d
2227 // here. Furthermore, if the face is
2228 // refined with cut_x or cut_y then
2229 // those children again in the other
2230 // direction, and if this cell is
2231 // refined isotropically (along the
2232 // face) then the neighbor will
2233 // (probably) be refined as cut_x or
2234 // cut_y along the face. For those
2235 // neighboring children cells, their
2236 // neighbor will be the current,
2237 // inactive cell, as our children are
2238 // too fine to be neighbors. Catch that
2239 // case by also acting on inactive
2240 // cells with isotropic refinement
2241 // along the face. If the situation
2242 // described is not present, the data
2243 // will be overwritten later on when we
2244 // visit cells on finer levels, so no
2245 // harm will be done.
2246 if (face->has_children() &&
2247 (cell->is_active() ||
2249 cell->refinement_case(), f) ==
2250 RefinementCase<dim - 1>::isotropic_refinement))
2251 {
2252 for (unsigned int c = 0; c < face->n_children(); ++c)
2253 adjacent_cells[2 * face->child(c)->index() + offset] =
2254 cell;
2255 if (face->child(0)->has_children())
2256 {
2257 adjacent_cells[2 * face->child(0)->child(0)->index() +
2258 offset] = cell;
2259 adjacent_cells[2 * face->child(0)->child(1)->index() +
2260 offset] = cell;
2261 }
2262 if (face->child(1)->has_children())
2263 {
2264 adjacent_cells[2 * face->child(1)->child(0)->index() +
2265 offset] = cell;
2266 adjacent_cells[2 * face->child(1)->child(1)->index() +
2267 offset] = cell;
2268 }
2269 } // if cell active and face refined
2270 } // else -> dim==3
2271 } // for all faces of all cells
2272
2273 // now loop again over all cells and set the
2274 // corresponding neighbor cell. Note, that we
2275 // have to use the opposite of the
2276 // left_right_offset in this case as we want
2277 // the offset of the neighbor, not our own.
2278 for (const auto &cell : triangulation.cell_iterators())
2279 for (auto f : cell->face_indices())
2280 {
2281 const unsigned int offset =
2282 (cell->direction_flag() ?
2283 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
2284 1 -
2285 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
2286 cell->set_neighbor(
2287 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
2288 }
2289 }
2290
2291
2295 template <int dim, int spacedim>
2296 static void
2298 const std::vector<CellData<dim>> & cells,
2299 const SubCellData & subcelldata,
2301 {
2302 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
2303 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
2304
2305 // Check that all cells have positive volume.
2306#ifndef _MSC_VER
2307 // TODO: The following code does not compile with MSVC. Find a way
2308 // around it
2309 if (dim == spacedim)
2310 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
2311 {
2312 // If we should check for distorted cells, then we permit them
2313 // to exist. If a cell has negative measure, then it must be
2314 // distorted (the converse is not necessarily true); hence
2315 // throw an exception if no such cells should exist.
2317 {
2318 const double cell_measure = GridTools::cell_measure<spacedim>(
2319 vertices,
2320 ArrayView<const unsigned int>(cells[cell_no].vertices));
2321 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
2322 }
2323 }
2324#endif
2325
2326 // clear old content
2327 tria.levels.clear();
2328 tria.levels.push_back(
2329 std::make_unique<
2331
2332 if (dim > 1)
2333 tria.faces = std::make_unique<
2335
2336 // copy vertices
2338 tria.vertices_used.assign(vertices.size(), true);
2339
2340 // compute connectivity
2341 const auto connectivity = build_connectivity<unsigned int>(cells);
2342 const unsigned int n_cell = cells.size();
2343
2344 // TriaObjects: lines
2345 if (dim >= 2)
2346 {
2347 auto &lines_0 = tria.faces->lines; // data structure to be filled
2348
2349 // get connectivity between quads and lines
2350 const auto & crs = connectivity.entity_to_entities(1, 0);
2351 const unsigned int n_lines = crs.ptr.size() - 1;
2352
2353 // allocate memory
2354 reserve_space_(lines_0, n_lines);
2355
2356 // loop over lines
2357 for (unsigned int line = 0; line < n_lines; ++line)
2358 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
2359 ++i, ++j)
2360 lines_0.cells[line * GeometryInfo<1>::faces_per_cell + j] =
2361 crs.col[i]; // set vertex indices
2362 }
2363
2364 // TriaObjects: quads
2365 if (dim == 3)
2366 {
2367 auto &quads_0 = tria.faces->quads; // data structures to be filled
2368 auto &faces = *tria.faces;
2369
2370 // get connectivity between quads and lines
2371 const auto & crs = connectivity.entity_to_entities(2, 1);
2372 const unsigned int n_quads = crs.ptr.size() - 1;
2373
2374 // allocate memory
2375 reserve_space_(quads_0, n_quads);
2376 reserve_space_(faces, 2 /*structdim*/, n_quads);
2377
2378 // loop over all quads -> entity type, line indices/orientations
2379 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
2380 {
2381 // set entity type of quads
2382 faces.quad_reference_cell[q] = connectivity.entity_types(2)[q];
2383
2384 // loop over all its lines
2385 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
2386 ++i, ++j, ++k)
2387 {
2388 // set line index
2389 quads_0.cells[q * GeometryInfo<2>::faces_per_cell + j] =
2390 crs.col[i];
2391
2392 // set line orientations
2393 faces.quads_line_orientations
2395 connectivity.entity_orientations(1)[k];
2396 }
2397 }
2398 }
2399
2400 // TriaObjects/TriaLevel: cell
2401 {
2402 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
2403 auto &level = *tria.levels[0];
2404
2405 // get connectivity between cells/faces and cells/cells
2406 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2407 const auto &nei = connectivity.entity_to_entities(dim, dim);
2408
2409 // in 2D optional: since in in pure QUAD meshes same line
2410 // orientations can be guaranteed
2411 const bool orientation_needed =
2412 dim == 3 ||
2413 (dim == 2 &&
2414 std::any_of(connectivity.entity_orientations(1).begin(),
2415 connectivity.entity_orientations(1).end(),
2416 [](const auto &i) { return i == 0; }));
2417
2418 // allocate memory
2419 reserve_space_(cells_0, n_cell);
2420 reserve_space_(level, spacedim, n_cell, orientation_needed);
2421
2422 // loop over all cells
2423 for (unsigned int cell = 0; cell < n_cell; ++cell)
2424 {
2425 // set material ids
2426 cells_0.boundary_or_material_id[cell].material_id =
2427 cells[cell].material_id;
2428
2429 // set manifold ids
2430 cells_0.manifold_id[cell] = cells[cell].manifold_id;
2431
2432 // set entity types
2433 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
2434
2435 // loop over faces
2436 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2437 ++i, ++j)
2438 {
2439 // set neighbor if not at boundary
2440 if (nei.col[i] != static_cast<unsigned int>(-1))
2441 level.neighbors[cell * GeometryInfo<dim>::faces_per_cell +
2442 j] = {0, nei.col[i]};
2443
2444 // set face indices
2445 cells_0.cells[cell * GeometryInfo<dim>::faces_per_cell + j] =
2446 crs.col[i];
2447
2448 // set face orientation if needed
2449 if (orientation_needed)
2450 {
2451 level.face_orientations
2453 connectivity.entity_orientations(dim - 1)[i];
2454 }
2455 }
2456 }
2457 }
2458
2459 // TriaFaces: boundary id of boundary faces
2460 if (dim > 1)
2461 {
2462 auto &bids_face = dim == 3 ?
2463 tria.faces->quads.boundary_or_material_id :
2464 tria.faces->lines.boundary_or_material_id;
2465
2466 // count number of cells a face is belonging to
2467 std::vector<unsigned int> count(bids_face.size(), 0);
2468
2469 // get connectivity between cells/faces
2470 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
2471
2472 // count how many cells are adjacent to the same face
2473 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2474 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
2475 count[crs.col[i]]++;
2476
2477 // loop over all faces
2478 for (unsigned int face = 0; face < count.size(); ++face)
2479 {
2480 if (count[face] != 1) // inner face
2481 continue;
2482
2483 // boundary faces ...
2484 bids_face[face].boundary_id = 0;
2485
2486 if (dim != 3)
2487 continue;
2488
2489 // ... and the lines of quads in 3D
2490 const auto &crs = connectivity.entity_to_entities(2, 1);
2491 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
2492 tria.faces->lines.boundary_or_material_id[crs.col[i]]
2493 .boundary_id = 0;
2494 }
2495 }
2496 else // 1D
2497 {
2498 static const unsigned int t_tba = static_cast<unsigned int>(-1);
2499 static const unsigned int t_inner = static_cast<unsigned int>(-2);
2500
2501 std::vector<unsigned int> type(vertices.size(), t_tba);
2502
2503 const auto &crs = connectivity.entity_to_entities(1, 0);
2504
2505 for (unsigned int cell = 0; cell < cells.size(); ++cell)
2506 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
2507 ++i, ++j)
2508 if (type[crs.col[i]] != t_inner)
2509 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
2510
2511 for (unsigned int face = 0; face < type.size(); ++face)
2512 {
2513 // note: we also treat manifolds here!?
2516 if (type[face] != t_inner && type[face] != t_tba)
2517 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
2518 }
2519 }
2520
2521 // SubCellData: line
2522 if (dim >= 2)
2523 process_subcelldata(connectivity.entity_to_entities(1, 0),
2524 tria.faces->lines,
2525 subcelldata.boundary_lines,
2526 vertices);
2527
2528 // SubCellData: quad
2529 if (dim == 3)
2530 process_subcelldata(connectivity.entity_to_entities(2, 0),
2531 tria.faces->quads,
2532 subcelldata.boundary_quads,
2533 vertices);
2534 }
2535
2536
2537 template <int structdim, int spacedim, typename T>
2538 static void
2540 const CRS<T> & crs,
2541 TriaObjects & obj,
2542 const std::vector<CellData<structdim>> &boundary_objects_in,
2543 const std::vector<Point<spacedim>> & vertex_locations)
2544 {
2545 AssertDimension(obj.structdim, structdim);
2546
2547 if (boundary_objects_in.size() == 0)
2548 return; // empty subcelldata -> nothing to do
2549
2550 // pre-sort subcelldata
2551 auto boundary_objects = boundary_objects_in;
2552
2553 // ... sort vertices
2554 for (auto &boundary_object : boundary_objects)
2555 std::sort(boundary_object.vertices.begin(),
2556 boundary_object.vertices.end());
2557
2558 // ... sort cells
2559 std::sort(boundary_objects.begin(),
2560 boundary_objects.end(),
2561 [](const auto &a, const auto &b) {
2562 return a.vertices < b.vertices;
2563 });
2564
2565 unsigned int counter = 0;
2566
2567 std::vector<unsigned int> key;
2569
2570 for (unsigned int o = 0; o < obj.n_objects(); ++o)
2571 {
2572 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
2573 auto &manifold_id = obj.manifold_id[o];
2574
2575 // assert that object has not been visited yet and its value
2576 // has not been modified yet
2577 AssertThrow(boundary_id == 0 ||
2582
2583 // create key
2584 key.assign(crs.col.data() + crs.ptr[o],
2585 crs.col.data() + crs.ptr[o + 1]);
2586 std::sort(key.begin(), key.end());
2587
2588 // is subcelldata provided? -> binary search
2589 const auto subcell_object =
2590 std::lower_bound(boundary_objects.begin(),
2591 boundary_objects.end(),
2592 key,
2593 [&](const auto &cell, const auto &key) {
2594 return cell.vertices < key;
2595 });
2596
2597 // no subcelldata provided for this object
2598 if (subcell_object == boundary_objects.end() ||
2599 subcell_object->vertices != key)
2600 continue;
2601
2602 counter++;
2603
2604 // set manifold id
2605 manifold_id = subcell_object->manifold_id;
2606
2607 // set boundary id
2608 if (subcell_object->boundary_id !=
2610 {
2611 (void)vertex_locations;
2614 ExcMessage(
2615 "The input arguments for creating a triangulation "
2616 "specified a boundary id for an internal face. This "
2617 "is not allowed."
2618 "\n\n"
2619 "The object in question has vertex indices " +
2620 [subcell_object]() {
2621 std::string s;
2622 for (const auto v : subcell_object->vertices)
2623 s += std::to_string(v) + ',';
2624 return s;
2625 }() +
2626 " which are located at positions " +
2627 [vertex_locations, subcell_object]() {
2628 std::ostringstream s;
2629 for (const auto v : subcell_object->vertices)
2630 s << '(' << vertex_locations[v] << ')';
2631 return s.str();
2632 }() +
2633 "."));
2634 boundary_id = subcell_object->boundary_id;
2635 }
2636 }
2637
2638 // make sure that all subcelldata entries have been processed
2639 // TODO: this is not guaranteed, why?
2640 // AssertDimension(counter, boundary_objects_in.size());
2641 }
2642
2643
2644
2645 static void
2647 const unsigned structdim,
2648 const unsigned int size)
2649 {
2650 const unsigned int dim = faces.dim;
2651
2652 const unsigned int max_faces_per_cell = 2 * structdim;
2653
2654 if (dim == 3 && structdim == 2)
2655 {
2656 // quad entity types
2657 faces.quad_reference_cell.assign(size,
2659
2660 // quad line orientations
2661 faces.quads_line_orientations.assign(size * max_faces_per_cell, -1);
2662 }
2663 }
2664
2665
2666
2667 static void
2669 const unsigned int spacedim,
2670 const unsigned int size,
2671 const bool orientation_needed)
2672 {
2673 const unsigned int dim = level.dim;
2674
2675 const unsigned int max_faces_per_cell = 2 * dim;
2676
2677 level.active_cell_indices.assign(size, -1);
2678 level.subdomain_ids.assign(size, 0);
2679 level.level_subdomain_ids.assign(size, 0);
2680
2681 level.refine_flags.assign(size, 0u);
2682 level.coarsen_flags.assign(size, false);
2683
2684 level.parents.assign((size + 1) / 2, -1);
2685
2686 if (dim < spacedim)
2687 level.direction_flags.assign(size, true);
2688
2689 level.neighbors.assign(size * max_faces_per_cell, {-1, -1});
2690
2691 level.reference_cell.assign(size, ::ReferenceCells::Invalid);
2692
2693 if (orientation_needed)
2694 level.face_orientations.assign(size * max_faces_per_cell, -1);
2695
2696 level.global_active_cell_indices.assign(size,
2698 level.global_level_cell_indices.assign(size,
2700 }
2701
2702
2703
2704 static void
2705 reserve_space_(TriaObjects &obj, const unsigned int size)
2706 {
2707 const unsigned int structdim = obj.structdim;
2708
2709 const unsigned int max_children_per_cell = 1 << structdim;
2710 const unsigned int max_faces_per_cell = 2 * structdim;
2711
2712 obj.used.assign(size, true);
2713 obj.boundary_or_material_id.assign(
2714 size,
2716 BoundaryOrMaterialId());
2717 obj.manifold_id.assign(size, -1);
2718 obj.user_flags.assign(size, false);
2719 obj.user_data.resize(size);
2720
2721 if (structdim > 1) // TODO: why?
2722 obj.refinement_cases.assign(size, 0);
2723
2724 obj.children.assign(max_children_per_cell / 2 * size, -1);
2725
2726 obj.cells.assign(max_faces_per_cell * size, -1);
2727
2728 if (structdim <= 2)
2729 {
2730 obj.next_free_single = size - 1;
2731 obj.next_free_pair = 0;
2733 }
2734 else
2735 {
2736 obj.next_free_single = obj.next_free_pair = 0;
2737 }
2738 }
2739
2740
2756 template <int spacedim>
2757 static void
2760 std::vector<unsigned int> &,
2761 std::vector<unsigned int> &)
2762 {
2763 const unsigned int dim = 1;
2764
2765 // first we need to reset the
2766 // neighbor pointers of the
2767 // neighbors of this cell's
2768 // children to this cell. This is
2769 // different for one dimension,
2770 // since there neighbors can have a
2771 // refinement level differing from
2772 // that of this cell's children by
2773 // more than one level.
2774
2775 Assert(!cell->child(0)->has_children() &&
2776 !cell->child(1)->has_children(),
2778
2779 // first do it for the cells to the
2780 // left
2781 if (cell->neighbor(0).state() == IteratorState::valid)
2782 if (cell->neighbor(0)->has_children())
2783 {
2785 cell->neighbor(0);
2786 Assert(neighbor->level() == cell->level(), ExcInternalError());
2787
2788 // right child
2789 neighbor = neighbor->child(1);
2790 while (true)
2791 {
2792 Assert(neighbor->neighbor(1) == cell->child(0),
2794 neighbor->set_neighbor(1, 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(1);
2802 else
2803 break;
2804 }
2805 }
2806
2807 // now do it for the cells to the
2808 // left
2809 if (cell->neighbor(1).state() == IteratorState::valid)
2810 if (cell->neighbor(1)->has_children())
2811 {
2813 cell->neighbor(1);
2814 Assert(neighbor->level() == cell->level(), ExcInternalError());
2815
2816 // left child
2817 neighbor = neighbor->child(0);
2818 while (true)
2819 {
2820 Assert(neighbor->neighbor(0) == cell->child(1),
2822 neighbor->set_neighbor(0, cell);
2823
2824 // move on to further
2825 // children on the
2826 // boundary between this
2827 // cell and its neighbor
2828 if (neighbor->has_children())
2829 neighbor = neighbor->child(0);
2830 else
2831 break;
2832 }
2833 }
2834
2835
2836 // delete the vertex which will not
2837 // be needed anymore. This vertex
2838 // is the second of the first child
2839 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
2840
2841 // invalidate children. clear user
2842 // pointers, to avoid that they may
2843 // appear at unwanted places later
2844 // on...
2845 for (unsigned int child = 0; child < cell->n_children(); ++child)
2846 {
2847 cell->child(child)->clear_user_data();
2848 cell->child(child)->clear_user_flag();
2849 cell->child(child)->clear_used_flag();
2850 }
2851
2852
2853 // delete pointer to children
2854 cell->clear_children();
2855 cell->clear_user_flag();
2856 }
2857
2858
2859
2860 template <int spacedim>
2861 static void
2864 std::vector<unsigned int> &line_cell_count,
2865 std::vector<unsigned int> &)
2866 {
2867 const unsigned int dim = 2;
2868 const RefinementCase<dim> ref_case = cell->refinement_case();
2869
2870 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
2872
2873 // vectors to hold all lines which
2874 // may be deleted
2875 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
2876 lines_to_delete(0);
2877
2878 lines_to_delete.reserve(4 * 2 + 4);
2879
2880 // now we decrease the counters for
2881 // lines contained in the child
2882 // cells
2883 for (unsigned int c = 0; c < cell->n_children(); ++c)
2884 {
2886 cell->child(c);
2887 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
2888 --line_cell_count[child->line_index(l)];
2889 }
2890
2891
2892 // delete the vertex which will not
2893 // be needed anymore. This vertex
2894 // is the second of the second line
2895 // of the first child, if the cell
2896 // is refined with cut_xy, else there
2897 // is no inner vertex.
2898 // additionally delete unneeded inner
2899 // lines
2900 if (ref_case == RefinementCase<dim>::cut_xy)
2901 {
2903 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
2904
2905 lines_to_delete.push_back(cell->child(0)->line(1));
2906 lines_to_delete.push_back(cell->child(0)->line(3));
2907 lines_to_delete.push_back(cell->child(3)->line(0));
2908 lines_to_delete.push_back(cell->child(3)->line(2));
2909 }
2910 else
2911 {
2912 unsigned int inner_face_no =
2913 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
2914
2915 // the inner line will not be
2916 // used any more
2917 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
2918 }
2919
2920 // invalidate children
2921 for (unsigned int child = 0; child < cell->n_children(); ++child)
2922 {
2923 cell->child(child)->clear_user_data();
2924 cell->child(child)->clear_user_flag();
2925 cell->child(child)->clear_used_flag();
2926 }
2927
2928
2929 // delete pointer to children
2930 cell->clear_children();
2931 cell->clear_refinement_case();
2932 cell->clear_user_flag();
2933
2934 // look at the refinement of outer
2935 // lines. if nobody needs those
2936 // anymore we can add them to the
2937 // list of lines to be deleted.
2938 for (unsigned int line_no = 0;
2939 line_no < GeometryInfo<dim>::lines_per_cell;
2940 ++line_no)
2941 {
2943 cell->line(line_no);
2944
2945 if (line->has_children())
2946 {
2947 // if one of the cell counters is
2948 // zero, the other has to be as well
2949
2950 Assert((line_cell_count[line->child_index(0)] == 0 &&
2951 line_cell_count[line->child_index(1)] == 0) ||
2952 (line_cell_count[line->child_index(0)] > 0 &&
2953 line_cell_count[line->child_index(1)] > 0),
2955
2956 if (line_cell_count[line->child_index(0)] == 0)
2957 {
2958 for (unsigned int c = 0; c < 2; ++c)
2959 Assert(!line->child(c)->has_children(),
2961
2962 // we may delete the line's
2963 // children and the middle vertex
2964 // as no cell references them
2965 // anymore
2967 .vertices_used[line->child(0)->vertex_index(1)] = false;
2968
2969 lines_to_delete.push_back(line->child(0));
2970 lines_to_delete.push_back(line->child(1));
2971
2972 line->clear_children();
2973 }
2974 }
2975 }
2976
2977 // finally, delete unneeded lines
2978
2979 // clear user pointers, to avoid that
2980 // they may appear at unwanted places
2981 // later on...
2982 // same for user flags, then finally
2983 // delete the lines
2984 typename std::vector<
2986 line = lines_to_delete.begin(),
2987 endline = lines_to_delete.end();
2988 for (; line != endline; ++line)
2989 {
2990 (*line)->clear_user_data();
2991 (*line)->clear_user_flag();
2992 (*line)->clear_used_flag();
2993 }
2994 }
2995
2996
2997
2998 template <int spacedim>
2999 static void
3002 std::vector<unsigned int> &line_cell_count,
3003 std::vector<unsigned int> &quad_cell_count)
3004 {
3005 const unsigned int dim = 3;
3006
3007 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3009 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3011
3012 // first of all, we store the RefineCase of
3013 // this cell
3014 const RefinementCase<dim> ref_case = cell->refinement_case();
3015 // vectors to hold all lines and quads which
3016 // may be deleted
3017 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3018 lines_to_delete(0);
3019 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3020 quads_to_delete(0);
3021
3022 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3023 quads_to_delete.reserve(6 * 4 + 12);
3024
3025 // now we decrease the counters for lines and
3026 // quads contained in the child cells
3027 for (unsigned int c = 0; c < cell->n_children(); ++c)
3028 {
3030 cell->child(c);
3031 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3032 --line_cell_count[child->line_index(l)];
3033 for (auto f : GeometryInfo<dim>::face_indices())
3034 --quad_cell_count[child->quad_index(f)];
3035 }
3036
3037 //-------------------------------------
3038 // delete interior quads and lines and the
3039 // interior vertex, depending on the
3040 // refinement case of the cell
3041 //
3042 // for append quads and lines: only append
3043 // them to the list of objects to be deleted
3044
3045 switch (ref_case)
3046 {
3048 quads_to_delete.push_back(cell->child(0)->face(1));
3049 break;
3051 quads_to_delete.push_back(cell->child(0)->face(3));
3052 break;
3054 quads_to_delete.push_back(cell->child(0)->face(5));
3055 break;
3057 quads_to_delete.push_back(cell->child(0)->face(1));
3058 quads_to_delete.push_back(cell->child(0)->face(3));
3059 quads_to_delete.push_back(cell->child(3)->face(0));
3060 quads_to_delete.push_back(cell->child(3)->face(2));
3061
3062 lines_to_delete.push_back(cell->child(0)->line(11));
3063 break;
3065 quads_to_delete.push_back(cell->child(0)->face(1));
3066 quads_to_delete.push_back(cell->child(0)->face(5));
3067 quads_to_delete.push_back(cell->child(3)->face(0));
3068 quads_to_delete.push_back(cell->child(3)->face(4));
3069
3070 lines_to_delete.push_back(cell->child(0)->line(5));
3071 break;
3073 quads_to_delete.push_back(cell->child(0)->face(3));
3074 quads_to_delete.push_back(cell->child(0)->face(5));
3075 quads_to_delete.push_back(cell->child(3)->face(2));
3076 quads_to_delete.push_back(cell->child(3)->face(4));
3077
3078 lines_to_delete.push_back(cell->child(0)->line(7));
3079 break;
3081 quads_to_delete.push_back(cell->child(0)->face(1));
3082 quads_to_delete.push_back(cell->child(2)->face(1));
3083 quads_to_delete.push_back(cell->child(4)->face(1));
3084 quads_to_delete.push_back(cell->child(6)->face(1));
3085
3086 quads_to_delete.push_back(cell->child(0)->face(3));
3087 quads_to_delete.push_back(cell->child(1)->face(3));
3088 quads_to_delete.push_back(cell->child(4)->face(3));
3089 quads_to_delete.push_back(cell->child(5)->face(3));
3090
3091 quads_to_delete.push_back(cell->child(0)->face(5));
3092 quads_to_delete.push_back(cell->child(1)->face(5));
3093 quads_to_delete.push_back(cell->child(2)->face(5));
3094 quads_to_delete.push_back(cell->child(3)->face(5));
3095
3096 lines_to_delete.push_back(cell->child(0)->line(5));
3097 lines_to_delete.push_back(cell->child(0)->line(7));
3098 lines_to_delete.push_back(cell->child(0)->line(11));
3099 lines_to_delete.push_back(cell->child(7)->line(0));
3100 lines_to_delete.push_back(cell->child(7)->line(2));
3101 lines_to_delete.push_back(cell->child(7)->line(8));
3102 // delete the vertex which will not
3103 // be needed anymore. This vertex
3104 // is the vertex at the heart of
3105 // this cell, which is the sixth of
3106 // the first child
3107 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
3108 false;
3109 break;
3110 default:
3111 // only remaining case is
3112 // no_refinement, thus an error
3113 Assert(false, ExcInternalError());
3114 break;
3115 }
3116
3117
3118 // invalidate children
3119 for (unsigned int child = 0; child < cell->n_children(); ++child)
3120 {
3121 cell->child(child)->clear_user_data();
3122 cell->child(child)->clear_user_flag();
3123
3124 for (auto f : GeometryInfo<dim>::face_indices())
3125 {
3126 // set flags denoting deviations from
3127 // standard orientation of faces back
3128 // to initialization values
3129 cell->child(child)->set_face_orientation(f, true);
3130 cell->child(child)->set_face_flip(f, false);
3131 cell->child(child)->set_face_rotation(f, false);
3132 }
3133
3134 cell->child(child)->clear_used_flag();
3135 }
3136
3137
3138 // delete pointer to children
3139 cell->clear_children();
3140 cell->clear_refinement_case();
3141 cell->clear_user_flag();
3142
3143 // so far we only looked at inner quads,
3144 // lines and vertices. Now we have to
3145 // consider outer ones as well. here, we have
3146 // to check, whether there are other cells
3147 // still needing these objects. otherwise we
3148 // can delete them. first for quads (and
3149 // their inner lines).
3150
3151 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
3152 {
3154 cell->face(quad_no);
3155
3156 Assert(
3157 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
3158 quad->has_children()) ||
3159 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
3162
3163 switch (quad->refinement_case())
3164 {
3165 case RefinementCase<dim - 1>::no_refinement:
3166 // nothing to do as the quad
3167 // is not refined
3168 break;
3169 case RefinementCase<dim - 1>::cut_x:
3170 case RefinementCase<dim - 1>::cut_y:
3171 {
3172 // if one of the cell counters is
3173 // zero, the other has to be as
3174 // well
3175 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3176 quad_cell_count[quad->child_index(1)] == 0) ||
3177 (quad_cell_count[quad->child_index(0)] > 0 &&
3178 quad_cell_count[quad->child_index(1)] > 0),
3180 // it might be, that the quad is
3181 // refined twice anisotropically,
3182 // first check, whether we may
3183 // delete possible grand_children
3184 unsigned int deleted_grandchildren = 0;
3185 unsigned int number_of_child_refinements = 0;
3186
3187 for (unsigned int c = 0; c < 2; ++c)
3188 if (quad->child(c)->has_children())
3189 {
3190 ++number_of_child_refinements;
3191 // if one of the cell counters is
3192 // zero, the other has to be as
3193 // well
3194 Assert(
3195 (quad_cell_count[quad->child(c)->child_index(0)] ==
3196 0 &&
3197 quad_cell_count[quad->child(c)->child_index(1)] ==
3198 0) ||
3199 (quad_cell_count[quad->child(c)->child_index(0)] >
3200 0 &&
3201 quad_cell_count[quad->child(c)->child_index(1)] >
3202 0),
3204 if (quad_cell_count[quad->child(c)->child_index(0)] ==
3205 0)
3206 {
3207 // Assert, that the two
3208 // anisotropic
3209 // refinements add up to
3210 // isotropic refinement
3211 Assert(quad->refinement_case() +
3212 quad->child(c)->refinement_case() ==
3215 // we may delete the
3216 // quad's children and
3217 // the inner line as no
3218 // cell references them
3219 // anymore
3220 quads_to_delete.push_back(
3221 quad->child(c)->child(0));
3222 quads_to_delete.push_back(
3223 quad->child(c)->child(1));
3224 if (quad->child(c)->refinement_case() ==
3226 lines_to_delete.push_back(
3227 quad->child(c)->child(0)->line(1));
3228 else
3229 lines_to_delete.push_back(
3230 quad->child(c)->child(0)->line(3));
3231 quad->child(c)->clear_children();
3232 quad->child(c)->clear_refinement_case();
3233 ++deleted_grandchildren;
3234 }
3235 }
3236 // if no grandchildren are left, we
3237 // may as well delete the
3238 // refinement of the inner line
3239 // between our children and the
3240 // corresponding vertex
3241 if (number_of_child_refinements > 0 &&
3242 deleted_grandchildren == number_of_child_refinements)
3243 {
3245 middle_line;
3246 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3247 middle_line = quad->child(0)->line(1);
3248 else
3249 middle_line = quad->child(0)->line(3);
3250
3251 lines_to_delete.push_back(middle_line->child(0));
3252 lines_to_delete.push_back(middle_line->child(1));
3254 .vertices_used[middle_vertex_index<dim, spacedim>(
3255 middle_line)] = false;
3256 middle_line->clear_children();
3257 }
3258
3259 // now consider the direct children
3260 // of the given quad
3261 if (quad_cell_count[quad->child_index(0)] == 0)
3262 {
3263 // we may delete the quad's
3264 // children and the inner line
3265 // as no cell references them
3266 // anymore
3267 quads_to_delete.push_back(quad->child(0));
3268 quads_to_delete.push_back(quad->child(1));
3269 if (quad->refinement_case() == RefinementCase<2>::cut_x)
3270 lines_to_delete.push_back(quad->child(0)->line(1));
3271 else
3272 lines_to_delete.push_back(quad->child(0)->line(3));
3273
3274 // if the counters just dropped
3275 // to zero, otherwise the
3276 // children would have been
3277 // deleted earlier, then this
3278 // cell's children must have
3279 // contained the anisotropic
3280 // quad children. thus, if
3281 // those have again anisotropic
3282 // children, which are in
3283 // effect isotropic children of
3284 // the original quad, those are
3285 // still needed by a
3286 // neighboring cell and we
3287 // cannot delete them. instead,
3288 // we have to reset this quad's
3289 // refine case to isotropic and
3290 // set the children
3291 // accordingly.
3292 if (quad->child(0)->has_children())
3293 if (quad->refinement_case() ==
3295 {
3296 // now evereything is
3297 // quite complicated. we
3298 // have the children
3299 // numbered according to
3300 //
3301 // *---*---*
3302 // |n+1|m+1|
3303 // *---*---*
3304 // | n | m |
3305 // *---*---*
3306 //
3307 // from the original
3308 // anisotropic
3309 // refinement. we have to
3310 // reorder them as
3311 //
3312 // *---*---*
3313 // | m |m+1|
3314 // *---*---*
3315 // | n |n+1|
3316 // *---*---*
3317 //
3318 // for isotropic refinement.
3319 //
3320 // this is a bit ugly, of
3321 // course: loop over all
3322 // cells on all levels
3323 // and look for faces n+1
3324 // (switch_1) and m
3325 // (switch_2).
3326 const typename Triangulation<dim, spacedim>::
3327 quad_iterator switch_1 =
3328 quad->child(0)->child(1),
3329 switch_2 =
3330 quad->child(1)->child(0);
3331
3332 Assert(!switch_1->has_children(),
3334 Assert(!switch_2->has_children(),
3336
3337 const int switch_1_index = switch_1->index();
3338 const int switch_2_index = switch_2->index();
3339 for (unsigned int l = 0;
3340 l < triangulation.levels.size();
3341 ++l)
3342 for (unsigned int h = 0;
3343 h <
3344 triangulation.levels[l]->cells.n_objects();
3345 ++h)
3346 for (const unsigned int q :
3348 {
3349 const int index =
3350 triangulation.levels[l]
3351 ->cells.get_bounding_object_indices(
3352 h)[q];
3353 if (index == switch_1_index)
3354 triangulation.levels[l]
3355 ->cells.get_bounding_object_indices(
3356 h)[q] = switch_2_index;
3357 else if (index == switch_2_index)
3358 triangulation.levels[l]
3359 ->cells.get_bounding_object_indices(
3360 h)[q] = switch_1_index;
3361 }
3362 // now we have to copy
3363 // all information of the
3364 // two quads
3365 const int switch_1_lines[4] = {
3366 static_cast<signed int>(
3367 switch_1->line_index(0)),
3368 static_cast<signed int>(
3369 switch_1->line_index(1)),
3370 static_cast<signed int>(
3371 switch_1->line_index(2)),
3372 static_cast<signed int>(
3373 switch_1->line_index(3))};
3374 const bool switch_1_line_orientations[4] = {
3375 switch_1->line_orientation(0),
3376 switch_1->line_orientation(1),
3377 switch_1->line_orientation(2),
3378 switch_1->line_orientation(3)};
3379 const types::boundary_id switch_1_boundary_id =
3380 switch_1->boundary_id();
3381 const unsigned int switch_1_user_index =
3382 switch_1->user_index();
3383 const bool switch_1_user_flag =
3384 switch_1->user_flag_set();
3385
3386 switch_1->set_bounding_object_indices(
3387 {switch_2->line_index(0),
3388 switch_2->line_index(1),
3389 switch_2->line_index(2),
3390 switch_2->line_index(3)});
3391 switch_1->set_line_orientation(
3392 0, switch_2->line_orientation(0));
3393 switch_1->set_line_orientation(
3394 1, switch_2->line_orientation(1));
3395 switch_1->set_line_orientation(
3396 2, switch_2->line_orientation(2));
3397 switch_1->set_line_orientation(
3398 3, switch_2->line_orientation(3));
3399 switch_1->set_boundary_id_internal(
3400 switch_2->boundary_id());
3401 switch_1->set_manifold_id(
3402 switch_2->manifold_id());
3403 switch_1->set_user_index(switch_2->user_index());
3404 if (switch_2->user_flag_set())
3405 switch_1->set_user_flag();
3406 else
3407 switch_1->clear_user_flag();
3408
3409 switch_2->set_bounding_object_indices(
3410 {switch_1_lines[0],
3411 switch_1_lines[1],
3412 switch_1_lines[2],
3413 switch_1_lines[3]});
3414 switch_2->set_line_orientation(
3415 0, switch_1_line_orientations[0]);
3416 switch_2->set_line_orientation(
3417 1, switch_1_line_orientations[1]);
3418 switch_2->set_line_orientation(
3419 2, switch_1_line_orientations[2]);
3420 switch_2->set_line_orientation(
3421 3, switch_1_line_orientations[3]);
3422 switch_2->set_boundary_id_internal(
3423 switch_1_boundary_id);
3424 switch_2->set_manifold_id(
3425 switch_1->manifold_id());
3426 switch_2->set_user_index(switch_1_user_index);
3427 if (switch_1_user_flag)
3428 switch_2->set_user_flag();
3429 else
3430 switch_2->clear_user_flag();
3431
3432 const unsigned int child_0 =
3433 quad->child(0)->child_index(0);
3434 const unsigned int child_2 =
3435 quad->child(1)->child_index(0);
3436 quad->clear_children();
3437 quad->clear_refinement_case();
3438 quad->set_refinement_case(
3440 quad->set_children(0, child_0);
3441 quad->set_children(2, child_2);
3442 std::swap(quad_cell_count[child_0 + 1],
3443 quad_cell_count[child_2]);
3444 }
3445 else
3446 {
3447 // the face was refined
3448 // with cut_y, thus the
3449 // children are already
3450 // in correct order. we
3451 // only have to set them
3452 // correctly, deleting
3453 // the indirection of two
3454 // anisotropic refinement
3455 // and going directly
3456 // from the quad to
3457 // isotropic children
3458 const unsigned int child_0 =
3459 quad->child(0)->child_index(0);
3460 const unsigned int child_2 =
3461 quad->child(1)->child_index(0);
3462 quad->clear_children();
3463 quad->clear_refinement_case();
3464 quad->set_refinement_case(
3466 quad->set_children(0, child_0);
3467 quad->set_children(2, child_2);
3468 }
3469 else
3470 {
3471 quad->clear_children();
3472 quad->clear_refinement_case();
3473 }
3474 }
3475 break;
3476 }
3477 case RefinementCase<dim - 1>::cut_xy:
3478 {
3479 // if one of the cell counters is
3480 // zero, the others have to be as
3481 // well
3482
3483 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
3484 quad_cell_count[quad->child_index(1)] == 0 &&
3485 quad_cell_count[quad->child_index(2)] == 0 &&
3486 quad_cell_count[quad->child_index(3)] == 0) ||
3487 (quad_cell_count[quad->child_index(0)] > 0 &&
3488 quad_cell_count[quad->child_index(1)] > 0 &&
3489 quad_cell_count[quad->child_index(2)] > 0 &&
3490 quad_cell_count[quad->child_index(3)] > 0),
3492
3493 if (quad_cell_count[quad->child_index(0)] == 0)
3494 {
3495 // we may delete the quad's
3496 // children, the inner lines
3497 // and the middle vertex as no
3498 // cell references them anymore
3499 lines_to_delete.push_back(quad->child(0)->line(1));
3500 lines_to_delete.push_back(quad->child(3)->line(0));
3501 lines_to_delete.push_back(quad->child(0)->line(3));
3502 lines_to_delete.push_back(quad->child(3)->line(2));
3503
3504 for (unsigned int child = 0; child < quad->n_children();
3505 ++child)
3506 quads_to_delete.push_back(quad->child(child));
3507
3509 .vertices_used[quad->child(0)->vertex_index(3)] =
3510 false;
3511
3512 quad->clear_children();
3513 quad->clear_refinement_case();
3514 }
3515 }
3516 break;
3517
3518 default:
3519 Assert(false, ExcInternalError());
3520 break;
3521 }
3522 }
3523
3524 // now we repeat a similar procedure
3525 // for the outer lines of this cell.
3526
3527 // if in debug mode: check that each
3528 // of the lines for which we consider
3529 // deleting the children in fact has
3530 // children (the bits/coarsening_3d
3531 // test tripped over this initially)
3532 for (unsigned int line_no = 0;
3533 line_no < GeometryInfo<dim>::lines_per_cell;
3534 ++line_no)
3535 {
3537 cell->line(line_no);
3538
3539 Assert(
3540 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
3541 line->has_children()) ||
3542 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
3545
3546 if (line->has_children())
3547 {
3548 // if one of the cell counters is
3549 // zero, the other has to be as well
3550
3551 Assert((line_cell_count[line->child_index(0)] == 0 &&
3552 line_cell_count[line->child_index(1)] == 0) ||
3553 (line_cell_count[line->child_index(0)] > 0 &&
3554 line_cell_count[line->child_index(1)] > 0),
3556
3557 if (line_cell_count[line->child_index(0)] == 0)
3558 {
3559 for (unsigned int c = 0; c < 2; ++c)
3560 Assert(!line->child(c)->has_children(),
3562
3563 // we may delete the line's
3564 // children and the middle vertex
3565 // as no cell references them
3566 // anymore
3568 .vertices_used[line->child(0)->vertex_index(1)] = false;
3569
3570 lines_to_delete.push_back(line->child(0));
3571 lines_to_delete.push_back(line->child(1));
3572
3573 line->clear_children();
3574 }
3575 }
3576 }
3577
3578 // finally, delete unneeded quads and lines
3579
3580 // clear user pointers, to avoid that
3581 // they may appear at unwanted places
3582 // later on...
3583 // same for user flags, then finally
3584 // delete the quads and lines
3585 typename std::vector<
3587 line = lines_to_delete.begin(),
3588 endline = lines_to_delete.end();
3589 for (; line != endline; ++line)
3590 {
3591 (*line)->clear_user_data();
3592 (*line)->clear_user_flag();
3593 (*line)->clear_used_flag();
3594 }
3595
3596 typename std::vector<
3598 quad = quads_to_delete.begin(),
3599 endquad = quads_to_delete.end();
3600 for (; quad != endquad; ++quad)
3601 {
3602 (*quad)->clear_user_data();
3603 (*quad)->clear_children();
3604 (*quad)->clear_refinement_case();
3605 (*quad)->clear_user_flag();
3606 (*quad)->clear_used_flag();
3607 }
3608 }
3609
3610
3628 template <int spacedim>
3629 static void
3632 unsigned int & next_unused_vertex,
3634 &next_unused_line,
3636 &next_unused_cell,
3637 const typename Triangulation<2, spacedim>::cell_iterator &cell)
3638 {
3639 const unsigned int dim = 2;
3640 // clear refinement flag
3641 const RefinementCase<dim> ref_case = cell->refine_flag_set();
3642 cell->clear_refine_flag();
3643
3644 /* For the refinement process: since we go the levels up from the
3645 lowest, there are (unlike above) only two possibilities: a neighbor
3646 cell is on the same level or one level up (in both cases, it may or
3647 may not be refined later on, but we don't care here).
3648
3649 First:
3650 Set up an array of the 3x3 vertices, which are distributed on the
3651 cell (the array consists of indices into the @p{vertices} std::vector
3652
3653 2--7--3
3654 | | |
3655 4--8--5
3656 | | |
3657 0--6--1
3658
3659 note: in case of cut_x or cut_y not all these vertices are needed for
3660 the new cells
3661
3662 Second:
3663 Set up an array of the new lines (the array consists of iterator
3664 pointers into the lines arrays)
3665
3666 .-6-.-7-. The directions are: .->-.->-.
3667 1 9 3 ^ ^ ^
3668 .-10.11-. .->-.->-.
3669 0 8 2 ^ ^ ^
3670 .-4-.-5-. .->-.->-.
3671
3672 cut_x:
3673 .-4-.-5-.
3674 | | |
3675 0 6 1
3676 | | |
3677 .-2-.-3-.
3678
3679 cut_y:
3680 .---5---.
3681 1 3
3682 .---6---.
3683 0 2
3684 .---4---.
3685
3686
3687 Third:
3688 Set up an array of neighbors:
3689
3690 6 7
3691 .--.--.
3692 1| | |3
3693 .--.--.
3694 0| | |2
3695 .--.--.
3696 4 5
3697
3698 We need this array for two reasons: first to get the lines which will
3699 bound the four subcells (if the neighboring cell is refined, these
3700 lines already exist), and second to update neighborship information.
3701 Since if a neighbor is not refined, its neighborship record only
3702 points to the present, unrefined, cell rather than the children we
3703 are presently creating, we only need the neighborship information
3704 if the neighbor cells are refined. In all other cases, we store
3705 the unrefined neighbor address
3706
3707 We also need for every neighbor (if refined) which number among its
3708 neighbors the present (unrefined) cell has, since that number is to
3709 be replaced and because that also is the number of the subline which
3710 will be the interface between that neighbor and the to be created
3711 cell. We will store this number (between 0 and 3) in the field
3712 @p{neighbors_neighbor}.
3713
3714 It would be sufficient to use the children of the common line to the
3715 neighbor, if we only wanted to get the new sublines and the new
3716 vertex, but because we need to update the neighborship information of
3717 the two refined subcells of the neighbor, we need to search these
3718 anyway.
3719
3720 Convention:
3721 The created children are numbered like this:
3722
3723 .--.--.
3724 |2 . 3|
3725 .--.--.
3726 |0 | 1|
3727 .--.--.
3728 */
3729 // collect the indices of the eight surrounding vertices
3730 // 2--7--3
3731 // | | |
3732 // 4--8--5
3733 // | | |
3734 // 0--6--1
3735 int new_vertices[9];
3736 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
3737 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
3738 for (unsigned int line_no = 0; line_no < 4; ++line_no)
3739 if (cell->line(line_no)->has_children())
3740 new_vertices[4 + line_no] =
3741 cell->line(line_no)->child(0)->vertex_index(1);
3742
3743 if (ref_case == RefinementCase<dim>::cut_xy)
3744 {
3745 // find the next
3746 // unused vertex and
3747 // allocate it for
3748 // the new vertex we
3749 // need here
3750 while (triangulation.vertices_used[next_unused_vertex] == true)
3751 ++next_unused_vertex;
3752 Assert(next_unused_vertex < triangulation.vertices.size(),
3753 ExcMessage(
3754 "Internal error: During refinement, the triangulation "
3755 "wants to access an element of the 'vertices' array "
3756 "but it turns out that the array is not large enough."));
3757 triangulation.vertices_used[next_unused_vertex] = true;
3758
3759 new_vertices[8] = next_unused_vertex;
3760
3761 // determine middle vertex by transfinite interpolation to be
3762 // consistent with what happens to quads in a
3763 // Triangulation<3,3> when they are refined
3764 triangulation.vertices[next_unused_vertex] =
3765 cell->center(true, true);
3766 }
3767
3768
3769 // Now the lines:
3771 unsigned int lmin = 8;
3772 unsigned int lmax = 12;
3773 if (ref_case != RefinementCase<dim>::cut_xy)
3774 {
3775 lmin = 6;
3776 lmax = 7;
3777 }
3778
3779 for (unsigned int l = lmin; l < lmax; ++l)
3780 {
3781 while (next_unused_line->used() == true)
3782 ++next_unused_line;
3783 new_lines[l] = next_unused_line;
3784 ++next_unused_line;
3785
3786 AssertIsNotUsed(new_lines[l]);
3787 }
3788
3789 if (ref_case == RefinementCase<dim>::cut_xy)
3790 {
3791 // .-6-.-7-.
3792 // 1 9 3
3793 // .-10.11-.
3794 // 0 8 2
3795 // .-4-.-5-.
3796
3797 // lines 0-7 already exist, create only the four interior
3798 // lines 8-11
3799 unsigned int l = 0;
3800 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
3801 for (unsigned int c = 0; c < 2; ++c, ++l)
3802 new_lines[l] = cell->line(face_no)->child(c);
3803 Assert(l == 8, ExcInternalError());
3804
3805 new_lines[8]->set_bounding_object_indices(
3806 {new_vertices[6], new_vertices[8]});
3807 new_lines[9]->set_bounding_object_indices(
3808 {new_vertices[8], new_vertices[7]});
3809 new_lines[10]->set_bounding_object_indices(
3810 {new_vertices[4], new_vertices[8]});
3811 new_lines[11]->set_bounding_object_indices(
3812 {new_vertices[8], new_vertices[5]});
3813 }
3814 else if (ref_case == RefinementCase<dim>::cut_x)
3815 {
3816 // .-4-.-5-.
3817 // | | |
3818 // 0 6 1
3819 // | | |
3820 // .-2-.-3-.
3821 new_lines[0] = cell->line(0);
3822 new_lines[1] = cell->line(1);
3823 new_lines[2] = cell->line(2)->child(0);
3824 new_lines[3] = cell->line(2)->child(1);
3825 new_lines[4] = cell->line(3)->child(0);
3826 new_lines[5] = cell->line(3)->child(1);
3827 new_lines[6]->set_bounding_object_indices(
3828 {new_vertices[6], new_vertices[7]});
3829 }
3830 else
3831 {
3833 // .---5---.
3834 // 1 3
3835 // .---6---.
3836 // 0 2
3837 // .---4---.
3838 new_lines[0] = cell->line(0)->child(0);
3839 new_lines[1] = cell->line(0)->child(1);
3840 new_lines[2] = cell->line(1)->child(0);
3841 new_lines[3] = cell->line(1)->child(1);
3842 new_lines[4] = cell->line(2);
3843 new_lines[5] = cell->line(3);
3844 new_lines[6]->set_bounding_object_indices(
3845 {new_vertices[4], new_vertices[5]});
3846 }
3847
3848 for (unsigned int l = lmin; l < lmax; ++l)
3849 {
3850 new_lines[l]->set_used_flag();
3851 new_lines[l]->clear_user_flag();
3852 new_lines[l]->clear_user_data();
3853 new_lines[l]->clear_children();
3854 // interior line
3855 new_lines[l]->set_boundary_id_internal(
3857 new_lines[l]->set_manifold_id(cell->manifold_id());
3858 }
3859
3860 // Now add the four (two)
3861 // new cells!
3864 while (next_unused_cell->used() == true)
3865 ++next_unused_cell;
3866
3867 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
3868 for (unsigned int i = 0; i < n_children; ++i)
3869 {
3870 AssertIsNotUsed(next_unused_cell);
3871 subcells[i] = next_unused_cell;
3872 ++next_unused_cell;
3873 if (i % 2 == 1 && i < n_children - 1)
3874 while (next_unused_cell->used() == true)
3875 ++next_unused_cell;
3876 }
3877
3878 if (ref_case == RefinementCase<dim>::cut_xy)
3879 {
3880 // children:
3881 // .--.--.
3882 // |2 . 3|
3883 // .--.--.
3884 // |0 | 1|
3885 // .--.--.
3886 // lines:
3887 // .-6-.-7-.
3888 // 1 9 3
3889 // .-10.11-.
3890 // 0 8 2
3891 // .-4-.-5-.
3892 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3893 new_lines[8]->index(),
3894 new_lines[4]->index(),
3895 new_lines[10]->index()});
3896 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
3897 new_lines[2]->index(),
3898 new_lines[5]->index(),
3899 new_lines[11]->index()});
3900 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
3901 new_lines[9]->index(),
3902 new_lines[10]->index(),
3903 new_lines[6]->index()});
3904 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
3905 new_lines[3]->index(),
3906 new_lines[11]->index(),
3907 new_lines[7]->index()});
3908 }
3909 else if (ref_case == RefinementCase<dim>::cut_x)
3910 {
3911 // children:
3912 // .--.--.
3913 // | . |
3914 // .0 . 1.
3915 // | | |
3916 // .--.--.
3917 // lines:
3918 // .-4-.-5-.
3919 // | | |
3920 // 0 6 1
3921 // | | |
3922 // .-2-.-3-.
3923 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3924 new_lines[6]->index(),
3925 new_lines[2]->index(),
3926 new_lines[4]->index()});
3927 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
3928 new_lines[1]->index(),
3929 new_lines[3]->index(),
3930 new_lines[5]->index()});
3931 }
3932 else
3933 {
3935 // children:
3936 // .-----.
3937 // | 1 |
3938 // .-----.
3939 // | 0 |
3940 // .-----.
3941 // lines:
3942 // .---5---.
3943 // 1 3
3944 // .---6---.
3945 // 0 2
3946 // .---4---.
3947 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
3948 new_lines[2]->index(),
3949 new_lines[4]->index(),
3950 new_lines[6]->index()});
3951 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
3952 new_lines[3]->index(),
3953 new_lines[6]->index(),
3954 new_lines[5]->index()});
3955 }
3956
3957 types::subdomain_id subdomainid = cell->subdomain_id();
3958
3959 for (unsigned int i = 0; i < n_children; ++i)
3960 {
3961 subcells[i]->set_used_flag();
3962 subcells[i]->clear_refine_flag();
3963 subcells[i]->clear_user_flag();
3964 subcells[i]->clear_user_data();
3965 subcells[i]->clear_children();
3966 // inherit material properties
3967 subcells[i]->set_material_id(cell->material_id());
3968 subcells[i]->set_manifold_id(cell->manifold_id());
3969 subcells[i]->set_subdomain_id(subdomainid);
3970
3971 if (i % 2 == 0)
3972 subcells[i]->set_parent(cell->index());
3973 }
3974
3975
3976
3977 // set child index for even children i=0,2 (0)
3978 for (unsigned int i = 0; i < n_children / 2; ++i)
3979 cell->set_children(2 * i, subcells[2 * i]->index());
3980 // set the refine case
3981 cell->set_refinement_case(ref_case);
3982
3983 // note that the
3984 // refinement flag was
3985 // already cleared at the
3986 // beginning of this function
3987
3988 if (dim < spacedim)
3989 for (unsigned int c = 0; c < n_children; ++c)
3990 cell->child(c)->set_direction_flag(cell->direction_flag());
3991 }
3992
3993
3994
3995 template <int dim, int spacedim>
3998 const bool check_for_distorted_cells)
3999 {
4000 AssertDimension(dim, 2);
4001
4002 // Check whether a new level is needed. We have to check for
4003 // this on the highest level only
4004 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4005 triangulation.levels.size() - 1))
4006 if (cell->refine_flag_set())
4007 {
4008 triangulation.levels.push_back(
4009 std::make_unique<
4011 break;
4012 }
4013
4015 triangulation.begin_line();
4016 line != triangulation.end_line();
4017 ++line)
4018 {
4019 line->clear_user_flag();
4020 line->clear_user_data();
4021 }
4022
4023 unsigned int n_single_lines = 0;
4024 unsigned int n_lines_in_pairs = 0;
4025 unsigned int needed_vertices = 0;
4026
4027 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4028 {
4029 // count number of flagged cells on this level and compute
4030 // how many new vertices and new lines will be needed
4031 unsigned int needed_cells = 0;
4032
4033 for (const auto &cell :
4034 triangulation.active_cell_iterators_on_level(level))
4035 if (cell->refine_flag_set())
4036 {
4037 if (cell->reference_cell() ==
4039 {
4040 needed_cells += 4;
4041 needed_vertices += 0;
4042 n_single_lines += 3;
4043 }
4044 else if (cell->reference_cell() ==
4046 {
4047 needed_cells += 4;
4048 needed_vertices += 1;
4049 n_single_lines += 4;
4050 }
4051 else
4052 {
4054 }
4055
4056 for (const auto line_no : cell->face_indices())
4057 {
4058 auto line = cell->line(line_no);
4059 if (line->has_children() == false)
4060 line->set_user_flag();
4061 }
4062 }
4063
4064
4065 const unsigned int used_cells =
4066 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4067 triangulation.levels[level + 1]->cells.used.end(),
4068 true);
4069
4070
4071 reserve_space(*triangulation.levels[level + 1],
4072 used_cells + needed_cells,
4073 2,
4074 spacedim);
4075
4076 reserve_space(triangulation.levels[level + 1]->cells,
4077 needed_cells,
4078 0);
4079 }
4080
4081 for (auto line = triangulation.begin_line();
4082 line != triangulation.end_line();
4083 ++line)
4084 if (line->user_flag_set())
4085 {
4086 Assert(line->has_children() == false, ExcInternalError());
4087 n_lines_in_pairs += 2;
4088 needed_vertices += 1;
4089 }
4090
4091 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4092
4093 needed_vertices += std::count(triangulation.vertices_used.begin(),
4094 triangulation.vertices_used.end(),
4095 true);
4096
4097 if (needed_vertices > triangulation.vertices.size())
4098 {
4099 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4100 triangulation.vertices_used.resize(needed_vertices, false);
4101 }
4102
4103 unsigned int next_unused_vertex = 0;
4104
4105 {
4107 line = triangulation.begin_active_line(),
4108 endl = triangulation.end_line();
4110 next_unused_line = triangulation.begin_raw_line();
4111
4112 for (; line != endl; ++line)
4113 if (line->user_flag_set())
4114 {
4115 // this line needs to be refined
4116
4117 // find the next unused vertex and set it
4118 // appropriately
4119 while (triangulation.vertices_used[next_unused_vertex] == true)
4120 ++next_unused_vertex;
4121 Assert(
4122 next_unused_vertex < triangulation.vertices.size(),
4123 ExcMessage(
4124 "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."));
4125 triangulation.vertices_used[next_unused_vertex] = true;
4126
4127 triangulation.vertices[next_unused_vertex] = line->center(true);
4128
4129 bool pair_found = false;
4130 (void)pair_found;
4131 for (; next_unused_line != endl; ++next_unused_line)
4132 if (!next_unused_line->used() &&
4133 !(++next_unused_line)->used())
4134 {
4135 --next_unused_line;
4136 pair_found = true;
4137 break;
4138 }
4139 Assert(pair_found, ExcInternalError());
4140
4141 line->set_children(0, next_unused_line->index());
4142
4144 children[2] = {next_unused_line, ++next_unused_line};
4145
4146 AssertIsNotUsed(children[0]);
4147 AssertIsNotUsed(children[1]);
4148
4149 children[0]->set_bounding_object_indices(
4150 {line->vertex_index(0), next_unused_vertex});
4151 children[1]->set_bounding_object_indices(
4152 {next_unused_vertex, line->vertex_index(1)});
4153
4154 children[0]->set_used_flag();
4155 children[1]->set_used_flag();
4156 children[0]->clear_children();
4157 children[1]->clear_children();
4158 children[0]->clear_user_data();
4159 children[1]->clear_user_data();
4160 children[0]->clear_user_flag();
4161 children[1]->clear_user_flag();
4162
4163
4164 children[0]->set_boundary_id_internal(line->boundary_id());
4165 children[1]->set_boundary_id_internal(line->boundary_id());
4166
4167 children[0]->set_manifold_id(line->manifold_id());
4168 children[1]->set_manifold_id(line->manifold_id());
4169
4170 line->clear_user_flag();
4171 }
4172 }
4173
4174 reserve_space(triangulation.faces->lines, 0, n_single_lines);
4175
4177 cells_with_distorted_children;
4178
4180 next_unused_line = triangulation.begin_raw_line();
4181
4182 const auto create_children = [](auto & triangulation,
4183 unsigned int &next_unused_vertex,
4184 auto & next_unused_line,
4185 auto & next_unused_cell,
4186 const auto & cell) {
4187 const auto ref_case = cell->refine_flag_set();
4188 cell->clear_refine_flag();
4189
4190 unsigned int n_new_vertices = 0;
4191
4192 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4193 n_new_vertices = 6;
4194 else if (cell->reference_cell() ==
4196 n_new_vertices = 9;
4197 else
4199
4200 std::vector<int> new_vertices(n_new_vertices);
4201 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
4202 ++vertex_no)
4203 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4204 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
4205 if (cell->line(line_no)->has_children())
4206 new_vertices[cell->n_vertices() + line_no] =
4207 cell->line(line_no)->child(0)->vertex_index(1);
4208
4209 if (cell->reference_cell() == ::ReferenceCells::Quadrilateral)
4210 {
4211 while (triangulation.vertices_used[next_unused_vertex] == true)
4212 ++next_unused_vertex;
4213 Assert(
4214 next_unused_vertex < triangulation.vertices.size(),
4215 ExcMessage(
4216 "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."));
4217 triangulation.vertices_used[next_unused_vertex] = true;
4218
4219 new_vertices[8] = next_unused_vertex;
4220
4221 triangulation.vertices[next_unused_vertex] =
4222 cell->center(true, true);
4223 }
4224
4225 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
4226 12>
4227 new_lines;
4228 unsigned int lmin = 0;
4229 unsigned int lmax = 0;
4230
4231 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4232 {
4233 lmin = 6;
4234 lmax = 9;
4235 }
4236 else if (cell->reference_cell() ==
4238 {
4239 lmin = 8;
4240 lmax = 12;
4241 }
4242 else
4243 {
4245 }
4246
4247 for (unsigned int l = lmin; l < lmax; ++l)
4248 {
4249 while (next_unused_line->used() == true)
4250 ++next_unused_line;
4251 new_lines[l] = next_unused_line;
4252 ++next_unused_line;
4253
4254 AssertIsNotUsed(new_lines[l]);
4255 }
4256
4257 if (true)
4258 {
4259 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4260 {
4261 // add lines in the right order [TODO: clean up]
4262 const auto ref = [&](const unsigned int face_no,
4263 const unsigned int vertex_no) {
4264 if (cell->line(face_no)->child(0)->vertex_index(0) ==
4265 static_cast<unsigned int>(new_vertices[vertex_no]) ||
4266 cell->line(face_no)->child(0)->vertex_index(1) ==
4267 static_cast<unsigned int>(new_vertices[vertex_no]))
4268 {
4269 new_lines[2 * face_no + 0] =
4270 cell->line(face_no)->child(0);
4271 new_lines[2 * face_no + 1] =
4272 cell->line(face_no)->child(1);
4273 }
4274 else
4275 {
4276 new_lines[2 * face_no + 0] =
4277 cell->line(face_no)->child(1);
4278 new_lines[2 * face_no + 1] =
4279 cell->line(face_no)->child(0);
4280 }
4281 };
4282
4283 ref(0, 0);
4284 ref(1, 1);
4285 ref(2, 2);
4286
4287 new_lines[6]->set_bounding_object_indices(
4288 {new_vertices[3], new_vertices[4]});
4289 new_lines[7]->set_bounding_object_indices(
4290 {new_vertices[4], new_vertices[5]});
4291 new_lines[8]->set_bounding_object_indices(
4292 {new_vertices[5], new_vertices[3]});
4293 }
4294 else if (cell->reference_cell() ==
4296 {
4297 unsigned int l = 0;
4298 for (const unsigned int face_no : cell->face_indices())
4299 for (unsigned int c = 0; c < 2; ++c, ++l)
4300 new_lines[l] = cell->line(face_no)->child(c);
4301
4302 new_lines[8]->set_bounding_object_indices(
4303 {new_vertices[6], new_vertices[8]});
4304 new_lines[9]->set_bounding_object_indices(
4305 {new_vertices[8], new_vertices[7]});
4306 new_lines[10]->set_bounding_object_indices(
4307 {new_vertices[4], new_vertices[8]});
4308 new_lines[11]->set_bounding_object_indices(
4309 {new_vertices[8], new_vertices[5]});
4310 }
4311 else
4312 {
4314 }
4315 }
4316
4317
4318 for (unsigned int l = lmin; l < lmax; ++l)
4319 {
4320 new_lines[l]->set_used_flag();
4321 new_lines[l]->clear_user_flag();
4322 new_lines[l]->clear_user_data();
4323 new_lines[l]->clear_children();
4324 // interior line
4325 new_lines[l]->set_boundary_id_internal(
4327 new_lines[l]->set_manifold_id(cell->manifold_id());
4328 }
4329
4332 while (next_unused_cell->used() == true)
4333 ++next_unused_cell;
4334
4335 unsigned int n_children = 0;
4336
4337 if (cell->reference_cell() == ::ReferenceCells::Triangle)
4338 n_children = 4;
4339 else if (cell->reference_cell() ==
4341 n_children = 4;
4342 else
4344
4345 for (unsigned int i = 0; i < n_children; ++i)
4346 {
4347 AssertIsNotUsed(next_unused_cell);
4348 subcells[i] = next_unused_cell;
4349 ++next_unused_cell;
4350 if (i % 2 == 1 && i < n_children - 1)
4351 while (next_unused_cell->used() == true)
4352 ++next_unused_cell;
4353 }
4354
4355 if ((dim == 2) &&
4356 (cell->reference_cell() == ::ReferenceCells::Triangle))
4357 {
4358 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4359 new_lines[8]->index(),
4360 new_lines[5]->index()});
4361 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4362 new_lines[2]->index(),
4363 new_lines[6]->index()});
4364 subcells[2]->set_bounding_object_indices({new_lines[7]->index(),
4365 new_lines[3]->index(),
4366 new_lines[4]->index()});
4367 subcells[3]->set_bounding_object_indices({new_lines[6]->index(),
4368 new_lines[7]->index(),
4369 new_lines[8]->index()});
4370
4371 // subcell 0
4372
4373 const auto ref = [&](const unsigned int line_no,
4374 const unsigned int vertex_no,
4375 const unsigned int subcell_no,
4376 const unsigned int subcell_line_no) {
4377 if (new_lines[line_no]->vertex_index(1) !=
4378 static_cast<unsigned int>(new_vertices[vertex_no]))
4379 triangulation.levels[subcells[subcell_no]->level()]
4380 ->face_orientations[subcells[subcell_no]->index() *
4382 subcell_line_no] = 0;
4383 };
4384
4385 ref(0, 3, 0, 0);
4386 ref(8, 5, 0, 1);
4387 ref(5, 0, 0, 2);
4388
4389 ref(1, 1, 1, 0);
4390 ref(2, 4, 1, 1);
4391 ref(6, 3, 1, 2);
4392
4393 ref(7, 4, 2, 0);
4394 ref(3, 2, 2, 1);
4395 ref(4, 5, 2, 2);
4396
4397 ref(6, 4, 3, 0);
4398 ref(7, 5, 3, 1);
4399 ref(8, 3, 3, 2);
4400
4401 // triangulation.levels[subcells[1]->level()]->face_orientations[subcells[1]->index()
4402 // * GeometryInfo<2>::faces_per_cell + 2] = 0;
4403 // triangulation.levels[subcells[2]->level()]->face_orientations[subcells[2]->index()
4404 // * GeometryInfo<2>::faces_per_cell + 0] = 0;
4405 }
4406 else if ((dim == 2) && (cell->reference_cell() ==
4408 {
4409 subcells[0]->set_bounding_object_indices(
4410 {new_lines[0]->index(),
4411 new_lines[8]->index(),
4412 new_lines[4]->index(),
4413 new_lines[10]->index()});
4414 subcells[1]->set_bounding_object_indices(
4415 {new_lines[8]->index(),
4416 new_lines[2]->index(),
4417 new_lines[5]->index(),
4418 new_lines[11]->index()});
4419 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4420 new_lines[9]->index(),
4421 new_lines[10]->index(),
4422 new_lines[6]->index()});
4423 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4424 new_lines[3]->index(),
4425 new_lines[11]->index(),
4426 new_lines[7]->index()});
4427 }
4428 else
4429 {
4431 }
4432
4433 types::subdomain_id subdomainid = cell->subdomain_id();
4434
4435 for (unsigned int i = 0; i < n_children; ++i)
4436 {
4437 subcells[i]->set_used_flag();
4438 subcells[i]->clear_refine_flag();
4439 subcells[i]->clear_user_flag();
4440 subcells[i]->clear_user_data();
4441 subcells[i]->clear_children();
4442 // inherit material
4443 // properties
4444 subcells[i]->set_material_id(cell->material_id());
4445 subcells[i]->set_manifold_id(cell->manifold_id());
4446 subcells[i]->set_subdomain_id(subdomainid);
4447
4448 // TODO: here we assume that all children have the same reference
4449 // cell type as the parent! This is justified for 2D.
4450 triangulation.levels[subcells[i]->level()]
4451 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
4452
4453 if (i % 2 == 0)
4454 subcells[i]->set_parent(cell->index());
4455 }
4456
4457 for (unsigned int i = 0; i < n_children / 2; ++i)
4458 cell->set_children(2 * i, subcells[2 * i]->index());
4459
4460 cell->set_refinement_case(ref_case);
4461
4462 if (dim < spacedim)
4463 for (unsigned int c = 0; c < n_children; ++c)
4464 cell->child(c)->set_direction_flag(cell->direction_flag());
4465 };
4466
4467 for (int level = 0;
4468 level < static_cast<int>(triangulation.levels.size()) - 1;
4469 ++level)
4470 {
4472 next_unused_cell = triangulation.begin_raw(level + 1);
4473
4474 for (const auto &cell :
4475 triangulation.active_cell_iterators_on_level(level))
4476 if (cell->refine_flag_set())
4477 {
4479 next_unused_vertex,
4480 next_unused_line,
4481 next_unused_cell,
4482 cell);
4483
4484 if (cell->reference_cell() ==
4486 check_for_distorted_cells &&
4487 has_distorted_children<dim, spacedim>(cell))
4488 cells_with_distorted_children.distorted_cells.push_back(
4489 cell);
4490
4491 triangulation.signals.post_refinement_on_cell(cell);
4492 }
4493 }
4494
4495 return cells_with_distorted_children;
4496 }
4497
4498
4499
4504 template <int spacedim>
4507 const bool /*check_for_distorted_cells*/)
4508 {
4509 const unsigned int dim = 1;
4510
4511 // Check whether a new level is needed. We have to check for
4512 // this on the highest level only
4513 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4514 triangulation.levels.size() - 1))
4515 if (cell->refine_flag_set())
4516 {
4517 triangulation.levels.push_back(
4518 std::make_unique<
4520 break;
4521 }
4522
4523
4524 // check how much space is needed on every level. We need not
4525 // check the highest level since either - on the highest level
4526 // no cells are flagged for refinement - there are, but
4527 // prepare_refinement added another empty level
4528 unsigned int needed_vertices = 0;
4529 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4530 {
4531 // count number of flagged
4532 // cells on this level
4533 unsigned int flagged_cells = 0;
4534
4535 for (const auto &acell :
4536 triangulation.active_cell_iterators_on_level(level))
4537 if (acell->refine_flag_set())
4538 ++flagged_cells;
4539
4540 // count number of used cells
4541 // on the next higher level
4542 const unsigned int used_cells =
4543 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4544 triangulation.levels[level + 1]->cells.used.end(),
4545 true);
4546
4547 // reserve space for the used_cells cells already existing
4548 // on the next higher level as well as for the
4549 // 2*flagged_cells that will be created on that level
4550 reserve_space(*triangulation.levels[level + 1],
4552 flagged_cells,
4553 1,
4554 spacedim);
4555 // reserve space for 2*flagged_cells new lines on the next
4556 // higher level
4557 reserve_space(triangulation.levels[level + 1]->cells,
4559 flagged_cells,
4560 0);
4561
4562 needed_vertices += flagged_cells;
4563 }
4564
4565 // add to needed vertices how many
4566 // vertices are already in use
4567 needed_vertices += std::count(triangulation.vertices_used.begin(),
4568 triangulation.vertices_used.end(),
4569 true);
4570 // if we need more vertices: create them, if not: leave the
4571 // array as is, since shrinking is not really possible because
4572 // some of the vertices at the end may be in use
4573 if (needed_vertices > triangulation.vertices.size())
4574 {
4575 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4576 triangulation.vertices_used.resize(needed_vertices, false);
4577 }
4578
4579
4580 // Do REFINEMENT on every level; exclude highest level as
4581 // above
4582
4583 // index of next unused vertex
4584 unsigned int next_unused_vertex = 0;
4585
4586 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4587 {
4589 next_unused_cell = triangulation.begin_raw(level + 1);
4590
4591 for (const auto &cell :
4592 triangulation.active_cell_iterators_on_level(level))
4593 if (cell->refine_flag_set())
4594 {
4595 // clear refinement flag
4596 cell->clear_refine_flag();
4597
4598 // search for next unused
4599 // vertex
4600 while (triangulation.vertices_used[next_unused_vertex] ==
4601 true)
4602 ++next_unused_vertex;
4603 Assert(
4604 next_unused_vertex < triangulation.vertices.size(),
4605 ExcMessage(
4606 "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."));
4607
4608 // Now we always ask the cell itself where to put
4609 // the new point. The cell in turn will query the
4610 // manifold object internally.
4611 triangulation.vertices[next_unused_vertex] =
4612 cell->center(true);
4613
4614 triangulation.vertices_used[next_unused_vertex] = true;
4615
4616 // search for next two unused cell (++ takes care of
4617 // the end of the vector)
4619 first_child,
4620 second_child;
4621 while (next_unused_cell->used() == true)
4622 ++next_unused_cell;
4623 first_child = next_unused_cell;
4624 first_child->set_used_flag();
4625 first_child->clear_user_data();
4626 ++next_unused_cell;
4627 AssertIsNotUsed(next_unused_cell);
4628 second_child = next_unused_cell;
4629 second_child->set_used_flag();
4630 second_child->clear_user_data();
4631
4632 types::subdomain_id subdomainid = cell->subdomain_id();
4633
4634 // insert first child
4635 cell->set_children(0, first_child->index());
4636 first_child->clear_children();
4637 first_child->set_bounding_object_indices(
4638 {cell->vertex_index(0), next_unused_vertex});
4639 first_child->set_material_id(cell->material_id());
4640 first_child->set_manifold_id(cell->manifold_id());
4641 first_child->set_subdomain_id(subdomainid);
4642 first_child->set_direction_flag(cell->direction_flag());
4643
4644 first_child->set_parent(cell->index());
4645
4646 // Set manifold id of the right face. Only do this
4647 // on the first child.
4648 first_child->face(1)->set_manifold_id(cell->manifold_id());
4649
4650 // reset neighborship info (refer to
4651 // internal::TriangulationImplementation::TriaLevel<0> for
4652 // details)
4653 first_child->set_neighbor(1, second_child);
4654 if (cell->neighbor(0).state() != IteratorState::valid)
4655 first_child->set_neighbor(0, cell->neighbor(0));
4656 else if (cell->neighbor(0)->is_active())
4657 {
4658 // since the neighbors level is always <=level,
4659 // if the cell is active, then there are no
4660 // cells to the left which may want to know
4661 // about this new child cell.
4662 Assert(cell->neighbor(0)->level() <= cell->level(),
4664 first_child->set_neighbor(0, cell->neighbor(0));
4665 }
4666 else
4667 // left neighbor is refined
4668 {
4669 // set neighbor to cell on same level
4670 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
4671 first_child->set_neighbor(0,
4672 cell->neighbor(0)->child(nbnb));
4673
4674 // reset neighbor info of all right descendant
4675 // of the left neighbor of cell
4677 left_neighbor = cell->neighbor(0);
4678 while (left_neighbor->has_children())
4679 {
4680 left_neighbor = left_neighbor->child(nbnb);
4681 left_neighbor->set_neighbor(nbnb, first_child);
4682 }
4683 }
4684
4685 // insert second child
4686 second_child->clear_children();
4687 second_child->set_bounding_object_indices(
4688 {next_unused_vertex, cell->vertex_index(1)});
4689 second_child->set_neighbor(0, first_child);
4690 second_child->set_material_id(cell->material_id());
4691 second_child->set_manifold_id(cell->manifold_id());
4692 second_child->set_subdomain_id(subdomainid);
4693 second_child->set_direction_flag(cell->direction_flag());
4694
4695 if (cell->neighbor(1).state() != IteratorState::valid)
4696 second_child->set_neighbor(1, cell->neighbor(1));
4697 else if (cell->neighbor(1)->is_active())
4698 {
4699 Assert(cell->neighbor(1)->level() <= cell->level(),
4701 second_child->set_neighbor(1, cell->neighbor(1));
4702 }
4703 else
4704 // right neighbor is refined same as above
4705 {
4706 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
4707 second_child->set_neighbor(
4708 1, cell->neighbor(1)->child(nbnb));
4709
4711 right_neighbor = cell->neighbor(1);
4712 while (right_neighbor->has_children())
4713 {
4714 right_neighbor = right_neighbor->child(nbnb);
4715 right_neighbor->set_neighbor(nbnb, second_child);
4716 }
4717 }
4718 // inform all listeners that cell refinement is done
4719 triangulation.signals.post_refinement_on_cell(cell);
4720 }
4721 }
4722
4723 // in 1d, we can not have distorted children unless the parent
4724 // was already distorted (that is because we don't use
4725 // boundary information for 1d triangulations). so return an
4726 // empty list
4728 }
4729
4730
4735 template <int spacedim>
4738 const bool check_for_distorted_cells)
4739 {
4740 const unsigned int dim = 2;
4741
4742
4743 // First check whether we can get away with isotropic refinement, or
4744 // whether we need to run through the full anisotropic algorithm
4745 {
4746 bool do_isotropic_refinement = true;
4747 for (const auto &cell : triangulation.active_cell_iterators())
4748 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
4749 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
4750 {
4751 do_isotropic_refinement = false;
4752 break;
4753 }
4754
4755 if (do_isotropic_refinement)
4757 check_for_distorted_cells);
4758 }
4759
4760 // Check whether a new level is needed. We have to check for
4761 // this on the highest level only
4762 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4763 triangulation.levels.size() - 1))
4764 if (cell->refine_flag_set())
4765 {
4766 triangulation.levels.push_back(
4767 std::make_unique<
4769 break;
4770 }
4771
4772 // TODO[WB]: we clear user flags and pointers of lines; we're going
4773 // to use them to flag which lines need refinement
4775 triangulation.begin_line();
4776 line != triangulation.end_line();
4777 ++line)
4778 {
4779 line->clear_user_flag();
4780 line->clear_user_data();
4781 }
4782 // running over all cells and lines count the number
4783 // n_single_lines of lines which can be stored as single
4784 // lines, e.g. inner lines
4785 unsigned int n_single_lines = 0;
4786
4787 // New lines to be created: number lines which are stored in
4788 // pairs (the children of lines must be stored in pairs)
4789 unsigned int n_lines_in_pairs = 0;
4790
4791 // check how much space is needed on every level. We need not
4792 // check the highest level since either - on the highest level
4793 // no cells are flagged for refinement - there are, but
4794 // prepare_refinement added another empty level
4795 unsigned int needed_vertices = 0;
4796 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4797 {
4798 // count number of flagged cells on this level and compute
4799 // how many new vertices and new lines will be needed
4800 unsigned int needed_cells = 0;
4801
4802 for (const auto &cell :
4803 triangulation.active_cell_iterators_on_level(level))
4804 if (cell->refine_flag_set())
4805 {
4806 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
4807 {
4808 needed_cells += 4;
4809
4810 // new vertex at center of cell is needed in any
4811 // case
4812 ++needed_vertices;
4813
4814 // the four inner lines can be stored as singles
4815 n_single_lines += 4;
4816 }
4817 else // cut_x || cut_y
4818 {
4819 // set the flag showing that anisotropic
4820 // refinement is used for at least one cell
4821 triangulation.anisotropic_refinement = true;
4822
4823 needed_cells += 2;
4824 // no vertex at center
4825
4826 // the inner line can be stored as single
4827 n_single_lines += 1;
4828 }
4829
4830 // mark all faces (lines) for refinement; checking
4831 // locally whether the neighbor would also like to
4832 // refine them is rather difficult for lines so we
4833 // only flag them and after visiting all cells, we
4834 // decide which lines need refinement;
4835 for (const unsigned int line_no :
4837 {
4839 cell->refine_flag_set(), line_no) ==
4841 {
4843 line = cell->line(line_no);
4844 if (line->has_children() == false)
4845 line->set_user_flag();
4846 }
4847 }
4848 }
4849
4850
4851 // count number of used cells on the next higher level
4852 const unsigned int used_cells =
4853 std::count(triangulation.levels[level + 1]->cells.used.begin(),
4854 triangulation.levels[level + 1]->cells.used.end(),
4855 true);
4856
4857
4858 // reserve space for the used_cells cells already existing
4859 // on the next higher level as well as for the
4860 // needed_cells that will be created on that level
4861 reserve_space(*triangulation.levels[level + 1],
4862 used_cells + needed_cells,
4863 2,
4864 spacedim);
4865
4866 // reserve space for needed_cells new quads on the next
4867 // higher level
4868 reserve_space(triangulation.levels[level + 1]->cells,
4869 needed_cells,
4870 0);
4871 }
4872
4873 // now count the lines which were flagged for refinement
4875 triangulation.begin_line();
4876 line != triangulation.end_line();
4877 ++line)
4878 if (line->user_flag_set())
4879 {
4880 Assert(line->has_children() == false, ExcInternalError());
4881 n_lines_in_pairs += 2;
4882 needed_vertices += 1;
4883 }
4884 // reserve space for n_lines_in_pairs new lines. note, that
4885 // we can't reserve space for the single lines here as well,
4886 // as all the space reserved for lines in pairs would be
4887 // counted as unused and we would end up with too little space
4888 // to store all lines. memory reservation for n_single_lines
4889 // can only be done AFTER we refined the lines of the current
4890 // cells
4891 reserve_space(triangulation.faces->lines, n_lines_in_pairs, 0);
4892
4893 // add to needed vertices how many vertices are already in use
4894 needed_vertices += std::count(triangulation.vertices_used.begin(),
4895 triangulation.vertices_used.end(),
4896 true);
4897 // if we need more vertices: create them, if not: leave the
4898 // array as is, since shrinking is not really possible because
4899 // some of the vertices at the end may be in use
4900 if (needed_vertices > triangulation.vertices.size())
4901 {
4902 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
4903 triangulation.vertices_used.resize(needed_vertices, false);
4904 }
4905
4906
4907 // Do REFINEMENT on every level; exclude highest level as
4908 // above
4909
4910 // index of next unused vertex
4911 unsigned int next_unused_vertex = 0;
4912
4913 // first the refinement of lines. children are stored
4914 // pairwise
4915 {
4916 // only active objects can be refined further
4918 line = triangulation.begin_active_line(),
4919 endl = triangulation.end_line();
4921 next_unused_line = triangulation.begin_raw_line();
4922
4923 for (; line != endl; ++line)
4924 if (line->user_flag_set())
4925 {
4926 // this line needs to be refined
4927
4928 // find the next unused vertex and set it
4929 // appropriately
4930 while (triangulation.vertices_used[next_unused_vertex] == true)
4931 ++next_unused_vertex;
4932 Assert(
4933 next_unused_vertex < triangulation.vertices.size(),
4934 ExcMessage(
4935 "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."));
4936 triangulation.vertices_used[next_unused_vertex] = true;
4937
4938 triangulation.vertices[next_unused_vertex] = line->center(true);
4939
4940 // now that we created the right point, make up the
4941 // two child lines. To this end, find a pair of
4942 // unused lines
4943 bool pair_found = false;
4944 (void)pair_found;
4945 for (; next_unused_line != endl; ++next_unused_line)
4946 if (!next_unused_line->used() &&
4947 !(++next_unused_line)->used())
4948 {
4949 // go back to the first of the two unused
4950 // lines
4951 --next_unused_line;
4952 pair_found = true;
4953 break;
4954 }
4955 Assert(pair_found, ExcInternalError());
4956
4957 // there are now two consecutive unused lines, such
4958 // that the children of a line will be consecutive.
4959 // then set the child pointer of the present line
4960 line->set_children(0, next_unused_line->index());
4961
4962 // set the two new lines
4964 children[2] = {next_unused_line, ++next_unused_line};
4965 // some tests; if any of the iterators should be
4966 // invalid, then already dereferencing will fail
4967 AssertIsNotUsed(children[0]);
4968 AssertIsNotUsed(children[1]);
4969
4970 children[0]->set_bounding_object_indices(
4971 {line->vertex_index(0), next_unused_vertex});
4972 children[1]->set_bounding_object_indices(
4973 {next_unused_vertex, line->vertex_index(1)});
4974
4975 children[0]->set_used_flag();
4976 children[1]->set_used_flag();
4977 children[0]->clear_children();
4978 children[1]->clear_children();
4979 children[0]->clear_user_data();
4980 children[1]->clear_user_data();
4981 children[0]->clear_user_flag();
4982 children[1]->clear_user_flag();
4983
4984
4985 children[0]->set_boundary_id_internal(line->boundary_id());
4986 children[1]->set_boundary_id_internal(line->boundary_id());
4987
4988 children[0]->set_manifold_id(line->manifold_id());
4989 children[1]->set_manifold_id(line->manifold_id());
4990
4991 // finally clear flag indicating the need for
4992 // refinement
4993 line->clear_user_flag();
4994 }
4995 }
4996
4997
4998 // Now set up the new cells
4999
5000 // reserve space for inner lines (can be stored as single
5001 // lines)
5002 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5003
5005 cells_with_distorted_children;
5006
5007 // reset next_unused_line, as now also single empty places in
5008 // the vector can be used
5010 next_unused_line = triangulation.begin_raw_line();
5011
5012 for (int level = 0;
5013 level < static_cast<int>(triangulation.levels.size()) - 1;
5014 ++level)
5015 {
5017 next_unused_cell = triangulation.begin_raw(level + 1);
5018
5019 for (const auto &cell :
5020 triangulation.active_cell_iterators_on_level(level))
5021 if (cell->refine_flag_set())
5022 {
5023 // actually set up the children and update neighbor
5024 // information
5026 next_unused_vertex,
5027 next_unused_line,
5028 next_unused_cell,
5029 cell);
5030
5031 if (check_for_distorted_cells &&
5032 has_distorted_children<dim, spacedim>(cell))
5033 cells_with_distorted_children.distorted_cells.push_back(
5034 cell);
5035 // inform all listeners that cell refinement is done
5036 triangulation.signals.post_refinement_on_cell(cell);
5037 }
5038 }
5039
5040 return cells_with_distorted_children;
5041 }
5042
5043
5044 template <int spacedim>
5047 const bool check_for_distorted_cells)
5048 {
5049 static const int dim = 3;
5050 static const unsigned int X = numbers::invalid_unsigned_int;
5051
5052 Assert(spacedim == 3, ExcNotImplemented());
5053
5054 Assert(triangulation.vertices.size() ==
5055 triangulation.vertices_used.size(),
5057
5058 // Check whether a new level is needed. We have to check for
5059 // this on the highest level only
5060 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5061 triangulation.levels.size() - 1))
5062 if (cell->refine_flag_set())
5063 {
5064 triangulation.levels.push_back(
5065 std::make_unique<
5067 break;
5068 }
5069
5070 // first clear user flags for quads and lines; we're going to
5071 // use them to flag which lines and quads need refinement
5072 triangulation.faces->quads.clear_user_data();
5073
5075 triangulation.begin_line();
5076 line != triangulation.end_line();
5077 ++line)
5078 line->clear_user_flag();
5079
5081 triangulation.begin_quad();
5082 quad != triangulation.end_quad();
5083 ++quad)
5084 quad->clear_user_flag();
5085
5086 // check how much space is needed on every level. We need not
5087 // check the highest level since either
5088 // - on the highest level no cells are flagged for refinement
5089 // - there are, but prepare_refinement added another empty
5090 // level which then is the highest level
5091
5092 // variables to hold the number of newly to be created
5093 // vertices, lines and quads. as these are stored globally,
5094 // declare them outside the loop over al levels. we need lines
5095 // and quads in pairs for refinement of old ones and lines and
5096 // quads, that can be stored as single ones, as they are newly
5097 // created in the inside of an existing cell
5098 unsigned int needed_vertices = 0;
5099 unsigned int needed_lines_single = 0;
5100 unsigned int needed_quads_single = 0;
5101 unsigned int needed_lines_pair = 0;
5102 unsigned int needed_quads_pair = 0;
5103 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5104 {
5105 unsigned int new_cells = 0;
5106
5107 for (const auto &cell :
5108 triangulation.active_cell_iterators_on_level(level))
5109 if (cell->refine_flag_set())
5110 {
5111 // Only support isotropic refinement
5112 Assert(cell->refine_flag_set() ==
5115
5116 // Now count up how many new cells, faces, edges, and vertices
5117 // we will need to allocate to do this refinement.
5118 new_cells += cell->reference_cell().n_isotropic_children();
5119
5120 if (cell->reference_cell() == ReferenceCells::Hexahedron)
5121 {
5122 ++needed_vertices;
5123 needed_lines_single += 6;
5124 needed_quads_single += 12;
5125 }
5126 else if (cell->reference_cell() ==
5128 {
5129 needed_lines_single += 1;
5130 needed_quads_single += 8;
5131 }
5132 else
5133 {
5134 Assert(false, ExcInternalError());
5135 }
5136
5137 // Also check whether we have to refine any of the faces and
5138 // edges that bound this cell. They may of course already be
5139 // refined, so we only *mark* them for refinement by setting
5140 // the user flags
5141 for (const auto face : cell->face_indices())
5142 if (cell->face(face)->n_children() == 0)
5143 cell->face(face)->set_user_flag();
5144 else
5145 Assert(cell->face(face)->n_children() ==
5146 cell->reference_cell()
5147 .face_reference_cell(face)
5148 .n_isotropic_children(),
5150
5151 for (const auto line : cell->line_indices())
5152 if (cell->line(line)->has_children() == false)
5153 cell->line(line)->set_user_flag();
5154 else
5155 Assert(cell->line(line)->n_children() == 2,
5157 }
5158
5159 const unsigned int used_cells =
5160 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5161 triangulation.levels[level + 1]->cells.used.end(),
5162 true);
5163
5164 reserve_space(*triangulation.levels[level + 1],
5165 used_cells + new_cells,
5166 3,
5167 spacedim);
5168
5169 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
5170 }
5171
5172 // now count the quads and lines which were flagged for
5173 // refinement
5175 triangulation.begin_quad();
5176 quad != triangulation.end_quad();
5177 ++quad)
5178 {
5179 if (quad->user_flag_set() == false)
5180 continue;
5181
5182 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
5183 {
5184 needed_quads_pair += 4;
5185 needed_lines_pair += 4;
5186 needed_vertices += 1;
5187 }
5188 else if (quad->reference_cell() == ReferenceCells::Triangle)
5189 {
5190 needed_quads_pair += 4;
5191 needed_lines_single += 3;
5192 }
5193 else
5194 {
5195 Assert(false, ExcInternalError());
5196 }
5197 }
5198
5200 triangulation.begin_line();
5201 line != triangulation.end_line();
5202 ++line)
5203 {
5204 if (line->user_flag_set() == false)
5205 continue;
5206
5207 needed_lines_pair += 2;
5208 needed_vertices += 1;
5209 }
5210
5211 reserve_space(triangulation.faces->lines,
5212 needed_lines_pair,
5213 needed_lines_single);
5215 needed_quads_pair,
5216 needed_quads_single);
5217 reserve_space(triangulation.faces->quads,
5218 needed_quads_pair,
5219 needed_quads_single);
5220
5221
5222 // add to needed vertices how many vertices are already in use
5223 needed_vertices += std::count(triangulation.vertices_used.begin(),
5224 triangulation.vertices_used.end(),
5225 true);
5226
5227 if (needed_vertices > triangulation.vertices.size())
5228 {
5229 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5230 triangulation.vertices_used.resize(needed_vertices, false);
5231 }
5232
5233 //-----------------------------------------
5234 // Before we start with the actual refinement, we do some
5235 // sanity checks if in debug mode. especially, we try to catch
5236 // the notorious problem with lines being twice refined,
5237 // i.e. there are cells adjacent at one line ("around the
5238 // edge", but not at a face), with two cells differing by more
5239 // than one refinement level
5240 //
5241 // this check is very simple to implement here, since we have
5242 // all lines flagged if they shall be refined
5243#ifdef DEBUG
5244 for (const auto &cell : triangulation.active_cell_iterators())
5245 if (!cell->refine_flag_set())
5246 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
5247 if (cell->line(line_n)->has_children())
5248 for (unsigned int c = 0; c < 2; ++c)
5249 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
5251#endif
5252
5253 unsigned int current_vertex = 0;
5254
5255 // helper function - find the next available vertex number and mark it
5256 // as used.
5257 auto get_next_unused_vertex = [](const unsigned int current_vertex,
5258 std::vector<bool> &vertices_used) {
5259 unsigned int next_vertex = current_vertex;
5260 while (next_vertex < vertices_used.size() &&
5261 vertices_used[next_vertex] == true)
5262 ++next_vertex;
5263 Assert(next_vertex < vertices_used.size(), ExcInternalError());
5264 vertices_used[next_vertex] = true;
5265
5266 return next_vertex;
5267 };
5268
5269 // LINES
5270 {
5272 line = triangulation.begin_active_line(),
5273 endl = triangulation.end_line();
5275 next_unused_line = triangulation.begin_raw_line();
5276
5277 for (; line != endl; ++line)
5278 {
5279 if (line->user_flag_set() == false)
5280 continue;
5281
5282 current_vertex =
5283 get_next_unused_vertex(current_vertex,
5284 triangulation.vertices_used);
5285 triangulation.vertices[current_vertex] = line->center(true);
5286
5287 next_unused_line =
5288 triangulation.faces->lines.template next_free_pair_object<1>(
5290 Assert(next_unused_line.state() == IteratorState::valid,
5292
5293 // now we found two consecutive unused lines, such
5294 // that the children of a line will be consecutive.
5295 // then set the child pointer of the present line
5296 line->set_children(0, next_unused_line->index());
5297
5299 children[2] = {next_unused_line, ++next_unused_line};
5300
5301 AssertIsNotUsed(children[0]);
5302 AssertIsNotUsed(children[1]);
5303
5304 children[0]->set_bounding_object_indices(
5305 {line->vertex_index(0), current_vertex});
5306 children[1]->set_bounding_object_indices(
5307 {current_vertex, line->vertex_index(1)});
5308
5309 children[0]->set_used_flag();
5310 children[1]->set_used_flag();
5311 children[0]->clear_children();
5312 children[1]->clear_children();
5313 children[0]->clear_user_data();
5314 children[1]->clear_user_data();
5315 children[0]->clear_user_flag();
5316 children[1]->clear_user_flag();
5317
5318 children[0]->set_boundary_id_internal(line->boundary_id());
5319 children[1]->set_boundary_id_internal(line->boundary_id());
5320
5321 children[0]->set_manifold_id(line->manifold_id());
5322 children[1]->set_manifold_id(line->manifold_id());
5323
5324 line->clear_user_flag();
5325 }
5326 }
5327
5328 // QUADS
5329 {
5331 quad = triangulation.begin_quad(),
5332 endq = triangulation.end_quad();
5334 next_unused_line = triangulation.begin_raw_line();
5336 next_unused_quad = triangulation.begin_raw_quad();
5337
5338 for (; quad != endq; ++quad)
5339 {
5340 if (quad->user_flag_set() == false)
5341 continue;
5342
5343 const auto reference_face_type = quad->reference_cell();
5344
5345 // 1) create new vertex (at the center of the face)
5346 if (reference_face_type == ReferenceCells::Quadrilateral)
5347 {
5348 current_vertex =
5349 get_next_unused_vertex(current_vertex,
5350 triangulation.vertices_used);
5351 triangulation.vertices[current_vertex] =
5352 quad->center(true, true);
5353 }
5354
5355 // 2) create new lines (property is set later)
5356 boost::container::small_vector<
5359 new_lines(quad->n_lines());
5360 {
5361 for (unsigned int i = 0; i < new_lines.size(); ++i)
5362 {
5363 if (reference_face_type == ReferenceCells::Quadrilateral)
5364 {
5365 if (i % 2 == 0)
5366 next_unused_line =
5367 triangulation.faces->lines
5368 .template next_free_pair_object<1>(triangulation);
5369 }
5370 else if (reference_face_type == ReferenceCells::Triangle)
5371 {
5372 next_unused_line =
5373 triangulation.faces->lines
5374 .template next_free_single_object<1>(triangulation);
5375 }
5376 else
5377 {
5378 Assert(false, ExcNotImplemented());
5379 }
5380
5381 new_lines[i] = next_unused_line;
5382 ++next_unused_line;
5383 AssertIsNotUsed(new_lines[i]);
5384 }
5385 }
5386
5387 // 3) create new quads (properties are set below). Both triangles
5388 // and quads are divided in four.
5389 std::array<
5391 4>
5392 new_quads;
5393 {
5394 next_unused_quad =
5395 triangulation.faces->quads.template next_free_pair_object<2>(
5397
5398 new_quads[0] = next_unused_quad;
5399 AssertIsNotUsed(new_quads[0]);
5400
5401 ++next_unused_quad;
5402 new_quads[1] = next_unused_quad;
5403 AssertIsNotUsed(new_quads[1]);
5404
5405 next_unused_quad =
5406 triangulation.faces->quads.template next_free_pair_object<2>(
5408 new_quads[2] = next_unused_quad;
5409 AssertIsNotUsed(new_quads[2]);
5410
5411 ++next_unused_quad;
5412 new_quads[3] = next_unused_quad;
5413 AssertIsNotUsed(new_quads[3]);
5414
5415 quad->set_children(0, new_quads[0]->index());
5416 quad->set_children(2, new_quads[2]->index());
5417 quad->set_refinement_case(RefinementCase<2>::cut_xy);
5418 }
5419
5420 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
5421 // for Triangle)
5422 std::array<unsigned int, 9> vertex_indices = {};
5423 {
5424 unsigned int k = 0;
5425 for (const auto i : quad->vertex_indices())
5426 vertex_indices[k++] = quad->vertex_index(i);
5427
5428 for (const auto i : quad->line_indices())
5429 vertex_indices[k++] =
5430 quad->line(i)->child(0)->vertex_index(1);
5431
5432 vertex_indices[k++] = current_vertex;
5433 }
5434
5435 boost::container::small_vector<
5437 12>
5438 lines(reference_face_type == ReferenceCells::Quadrilateral ?
5439 12 :
5440 9);
5441 {
5442 unsigned int k = 0;
5443
5444 for (unsigned int l = 0; l < quad->n_lines(); ++l)
5445 for (unsigned int c = 0; c < 2; ++c)
5446 {
5447 static constexpr std::array<std::array<unsigned int, 2>,
5448 2>
5449 index = {// child 0, line_orientation=false and true
5450 {{{1, 0}},
5451 // child 1, line_orientation=false and true
5452 {{0, 1}}}};
5453
5454 lines[k++] = quad->line(l)->child(
5455 index[c][quad->line_orientation(l)]);
5456 }
5457
5458 for (unsigned int l = 0; l < new_lines.size(); ++l)
5459 lines[k++] = new_lines[l];
5460 }
5461
5462 boost::container::small_vector<int, 12> line_indices(
5463 lines.size());
5464 for (unsigned int i = 0; i < line_indices.size(); ++i)
5465 line_indices[i] = lines[i]->index();
5466
5467 static constexpr std::array<std::array<unsigned int, 2>, 12>
5468 line_vertices_quad{{{{0, 4}},
5469 {{4, 2}},
5470 {{1, 5}},
5471 {{5, 3}},
5472 {{0, 6}},
5473 {{6, 1}},
5474 {{2, 7}},
5475 {{7, 3}},
5476 {{6, 8}},
5477 {{8, 7}},
5478 {{4, 8}},
5479 {{8, 5}}}};
5480
5481 static constexpr std::array<std::array<unsigned int, 4>, 4>
5482 quad_lines_quad{{{{0, 8, 4, 10}},
5483 {{8, 2, 5, 11}},
5484 {{1, 9, 10, 6}},
5485 {{9, 3, 11, 7}}}};
5486
5487 static constexpr std::
5488 array<std::array<std::array<unsigned int, 2>, 4>, 4>
5489 quad_line_vertices_quad{
5490 {{{{{0, 4}}, {{6, 8}}, {{0, 6}}, {{4, 8}}}},
5491 {{{{6, 8}}, {{1, 5}}, {{6, 1}}, {{8, 5}}}},
5492 {{{{4, 2}}, {{8, 7}}, {{4, 8}}, {{2, 7}}}},
5493 {{{{8, 7}}, {{5, 3}}, {{8, 5}}, {{7, 3}}}}}};
5494
5495 static constexpr std::array<std::array<unsigned int, 2>, 12>
5496 line_vertices_tri{{{{0, 3}},
5497 {{3, 1}},
5498 {{1, 4}},
5499 {{4, 2}},
5500 {{2, 5}},
5501 {{5, 0}},
5502 {{3, 4}},
5503 {{4, 5}},
5504 {{3, 5}},
5505 {{X, X}},
5506 {{X, X}},
5507 {{X, X}}}};
5508
5509 static constexpr std::array<std::array<unsigned int, 4>, 4>
5510 quad_lines_tri{{{{0, 8, 5, X}},
5511 {{1, 2, 6, X}},
5512 {{7, 3, 4, X}},
5513 {{6, 7, 8, X}}}};
5514
5515 static constexpr std::
5516 array<std::array<std::array<unsigned int, 2>, 4>, 4>
5517 quad_line_vertices_tri{
5518 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
5519 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
5520 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
5521 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
5522
5523 const auto &line_vertices =
5524 (reference_face_type == ReferenceCells::Quadrilateral) ?
5525 line_vertices_quad :
5526 line_vertices_tri;
5527 const auto &quad_lines =
5528 (reference_face_type == ReferenceCells::Quadrilateral) ?
5529 quad_lines_quad :
5530 quad_lines_tri;
5531 const auto &quad_line_vertices =
5532 (reference_face_type == ReferenceCells::Quadrilateral) ?
5533 quad_line_vertices_quad :
5534 quad_line_vertices_tri;
5535
5536 // 4) set properties of lines
5537 for (unsigned int i = 0, j = lines.size() - new_lines.size();
5538 i < new_lines.size();
5539 ++i, ++j)
5540 {
5541 auto &new_line = new_lines[i];
5542 new_line->set_bounding_object_indices(
5543 {vertex_indices[line_vertices[j][0]],
5544 vertex_indices[line_vertices[j][1]]});
5545 new_line->set_used_flag();
5546 new_line->clear_user_flag();
5547 new_line->clear_user_data();
5548 new_line->clear_children();
5549 new_line->set_boundary_id_internal(quad->boundary_id());
5550 new_line->set_manifold_id(quad->manifold_id());
5551 }
5552
5553 // 5) set properties of quads
5554 for (unsigned int i = 0; i < new_quads.size(); ++i)
5555 {
5556 auto &new_quad = new_quads[i];
5557
5558 // TODO: we assume here that all children have the same type
5559 // as the parent
5560 triangulation.faces->quad_reference_cell[new_quad->index()] =
5561 reference_face_type;
5562
5563 if (new_quad->n_lines() == 3)
5564 new_quad->set_bounding_object_indices(
5565 {line_indices[quad_lines[i][0]],
5566 line_indices[quad_lines[i][1]],
5567 line_indices[quad_lines[i][2]]});
5568 else if (new_quad->n_lines() == 4)
5569 new_quad->set_bounding_object_indices(
5570 {line_indices[quad_lines[i][0]],
5571 line_indices[quad_lines[i][1]],
5572 line_indices[quad_lines[i][2]],
5573 line_indices[quad_lines[i][3]]});
5574 else
5575 Assert(false, ExcNotImplemented());
5576
5577 new_quad->set_used_flag();
5578 new_quad->clear_user_flag();
5579 new_quad->clear_user_data();
5580 new_quad->clear_children();
5581 new_quad->set_boundary_id_internal(quad->boundary_id());
5582 new_quad->set_manifold_id(quad->manifold_id());
5583
5584#ifdef DEBUG
5585 std::set<unsigned int> s;
5586#endif
5587
5588 // ... and fix orientation of faces (lines) of quad
5589 for (const auto f : new_quad->line_indices())
5590 {
5591 std::array<unsigned int, 2> vertices_0, vertices_1;
5592
5593 for (unsigned int v = 0; v < 2; ++v)
5594 vertices_0[v] =
5595 lines[quad_lines[i][f]]->vertex_index(v);
5596
5597 for (unsigned int v = 0; v < 2; ++v)
5598 vertices_1[v] =
5599 vertex_indices[quad_line_vertices[i][f][v]];
5600
5601 const auto orientation =
5603 vertices_1);
5604
5605#ifdef DEBUG
5606 for (const auto i : vertices_0)
5607 s.insert(i);
5608 for (const auto i : vertices_1)
5609 s.insert(i);
5610#endif
5611
5612 new_quad->set_line_orientation(f, orientation);
5613 }
5614#ifdef DEBUG
5616 s.size(),
5617 (reference_face_type == ReferenceCells::Quadrilateral ? 4 :
5618 3));
5619#endif
5620 }
5621
5622 quad->clear_user_flag();
5623 }
5624 }
5625
5627 cells_with_distorted_children;
5628
5629 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
5630 ++level)
5631 {
5633 hex = triangulation.begin_active_hex(level),
5634 endh = triangulation.begin_active_hex(level + 1);
5636 next_unused_hex = triangulation.begin_raw_hex(level + 1);
5637
5638 for (; hex != endh; ++hex)
5639 {
5640 if (hex->refine_flag_set() ==
5642 continue;
5643
5644 const auto &reference_cell_type = hex->reference_cell();
5645
5646 const RefinementCase<dim> ref_case = hex->refine_flag_set();
5647 hex->clear_refine_flag();
5648 hex->set_refinement_case(ref_case);
5649
5650 unsigned int n_new_lines = 0;
5651 unsigned int n_new_quads = 0;
5652 unsigned int n_new_hexes = 0;
5653
5654 if (reference_cell_type == ReferenceCells::Hexahedron)
5655 {
5656 n_new_lines = 6;
5657 n_new_quads = 12;
5658 n_new_hexes = 8;
5659 }
5660 else if (reference_cell_type == ReferenceCells::Tetrahedron)
5661 {
5662 n_new_lines = 1;
5663 n_new_quads = 8;
5664 n_new_hexes = 8;
5665 }
5666 else
5667 Assert(false, ExcNotImplemented());
5668
5669 // Hexes add a single new internal vertex
5670 if (reference_cell_type == ReferenceCells::Hexahedron)
5671 {
5672 current_vertex =
5673 get_next_unused_vertex(current_vertex,
5674 triangulation.vertices_used);
5675 triangulation.vertices[current_vertex] =
5676 hex->center(true, true);
5677 }
5678
5679 boost::container::small_vector<
5681 6>
5682 new_lines(n_new_lines);
5683 for (unsigned int i = 0; i < n_new_lines; ++i)
5684 {
5685 new_lines[i] =
5686 triangulation.faces->lines
5687 .template next_free_single_object<1>(triangulation);
5688
5689 AssertIsNotUsed(new_lines[i]);
5690 new_lines[i]->set_used_flag();
5691 new_lines[i]->clear_user_flag();
5692 new_lines[i]->clear_user_data();
5693 new_lines[i]->clear_children();
5694 new_lines[i]->set_boundary_id_internal(
5696 new_lines[i]->set_manifold_id(hex->manifold_id());
5697 }
5698
5699 boost::container::small_vector<
5701 12>
5702 new_quads(n_new_quads);
5703 for (unsigned int i = 0; i < n_new_quads; ++i)
5704 {
5705 new_quads[i] =
5706 triangulation.faces->quads
5707 .template next_free_single_object<2>(triangulation);
5708
5709 auto &new_quad = new_quads[i];
5710
5711 // TODO: faces of children have the same type as the faces
5712 // of the parent
5713 triangulation.faces
5714 ->quad_reference_cell[new_quad->index()] =
5715 (reference_cell_type == ReferenceCells::Hexahedron) ?
5718
5719 AssertIsNotUsed(new_quad);
5720 new_quad->set_used_flag();
5721 new_quad->clear_user_flag();
5722 new_quad->clear_user_data();
5723 new_quad->clear_children();
5724 new_quad->set_boundary_id_internal(
5726 new_quad->set_manifold_id(hex->manifold_id());
5727 for (const auto j : new_quads[i]->line_indices())
5728 new_quad->set_line_orientation(j, true);
5729 }
5730
5731 // we always get 8 children per refined cell
5732 std::array<
5734 8>
5735 new_hexes;
5736 {
5737 for (unsigned int i = 0; i < n_new_hexes; ++i)
5738 {
5739 if (i % 2 == 0)
5740 next_unused_hex =
5741 triangulation.levels[level + 1]->cells.next_free_hex(
5742 triangulation, level + 1);
5743 else
5744 ++next_unused_hex;
5745
5746 new_hexes[i] = next_unused_hex;
5747
5748 auto &new_hex = new_hexes[i];
5749
5750 // TODO: children have the same type as the parent
5751 triangulation.levels[new_hex->level()]
5752 ->reference_cell[new_hex->index()] =
5753 reference_cell_type;
5754
5755 AssertIsNotUsed(new_hex);
5756 new_hex->set_used_flag();
5757 new_hex->clear_user_flag();
5758 new_hex->clear_user_data();
5759 new_hex->clear_children();
5760 new_hex->set_material_id(hex->material_id());
5761 new_hex->set_manifold_id(hex->manifold_id());
5762 new_hex->set_subdomain_id(hex->subdomain_id());
5763
5764 if (i % 2)
5765 new_hex->set_parent(hex->index());
5766 // set the face_orientation flag to true for all
5767 // faces initially, as this is the default value
5768 // which is true for all faces interior to the
5769 // hex. later on go the other way round and
5770 // reset faces that are at the boundary of the
5771 // mother cube
5772 //
5773 // the same is true for the face_flip and
5774 // face_rotation flags. however, the latter two
5775 // are set to false by default as this is the
5776 // standard value
5777 for (const auto f : new_hex->face_indices())
5778 {
5779 new_hex->set_face_orientation(f, true);
5780 new_hex->set_face_flip(f, false);
5781 new_hex->set_face_rotation(f, false);
5782 }
5783 }
5784 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
5785 hex->set_children(2 * i, new_hexes[2 * i]->index());
5786 }
5787
5788 {
5789 // load vertex indices
5790 std::array<unsigned int, 27> vertex_indices = {};
5791
5792 {
5793 unsigned int k = 0;
5794
5795 for (const unsigned int i : hex->vertex_indices())
5796 vertex_indices[k++] = hex->vertex_index(i);
5797
5798 for (const unsigned int i : hex->line_indices())
5799 vertex_indices[k++] =
5800 hex->line(i)->child(0)->vertex_index(1);
5801
5802 if (reference_cell_type == ReferenceCells::Hexahedron)
5803 {
5804 for (const unsigned int i : hex->face_indices())
5805 vertex_indices[k++] =
5806 middle_vertex_index<dim, spacedim>(hex->face(i));
5807
5808 vertex_indices[k++] = current_vertex;
5809 }
5810 }
5811
5812 // set up new lines
5813 {
5814 static constexpr std::array<std::array<unsigned int, 2>, 6>
5815 new_line_vertices_hex = {{{{22, 26}},
5816 {{26, 23}},
5817 {{20, 26}},
5818 {{26, 21}},
5819 {{24, 26}},
5820 {{26, 25}}}};
5821
5822 static constexpr std::array<std::array<unsigned int, 2>, 6>
5823 new_line_vertices_tet = {{{{6, 8}},
5824 {{X, X}},
5825 {{X, X}},
5826 {{X, X}},
5827 {{X, X}},
5828 {{X, X}}}};
5829
5830 const auto &new_line_vertices =
5831 (reference_cell_type == ReferenceCells::Hexahedron) ?
5832 new_line_vertices_hex :
5833 new_line_vertices_tet;
5834
5835 for (unsigned int i = 0; i < new_lines.size(); ++i)
5836 new_lines[i]->set_bounding_object_indices(
5837 {vertex_indices[new_line_vertices[i][0]],
5838 vertex_indices[new_line_vertices[i][1]]});
5839 }
5840
5841 // set up new quads
5842 {
5843 boost::container::small_vector<
5845 30>
5846 relevant_lines(0);
5847
5848 if (reference_cell_type == ReferenceCells::Hexahedron)
5849 {
5850 relevant_lines.resize(30);
5851 for (unsigned int f = 0, k = 0; f < 6; ++f)
5852 for (unsigned int c = 0; c < 4; ++c, ++k)
5853 {
5854 static constexpr std::
5855 array<std::array<unsigned int, 2>, 4>
5856 temp = {
5857 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
5858
5859 relevant_lines[k] =
5860 hex->face(f)
5861 ->isotropic_child(
5863 standard_to_real_face_vertex(
5864 temp[c][0],
5865 hex->face_orientation(f),
5866 hex->face_flip(f),
5867 hex->face_rotation(f)))
5868 ->line(GeometryInfo<dim>::
5869 standard_to_real_face_line(
5870 temp[c][1],
5871 hex->face_orientation(f),
5872 hex->face_flip(f),
5873 hex->face_rotation(f)));
5874 }
5875
5876 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
5877 relevant_lines[k] = new_lines[i];
5878 }
5879 else if (reference_cell_type == ReferenceCells::Tetrahedron)
5880 {
5881 relevant_lines.resize(13);
5882
5883 unsigned int k = 0;
5884 for (unsigned int f = 0; f < 4; ++f)
5885 for (unsigned int l = 0; l < 3; ++l, ++k)
5886 {
5887 // TODO: add comment
5888 static const std::
5889 array<std::array<unsigned int, 3>, 6>
5890 table = {{{{1, 0, 2}}, // 0
5891 {{0, 1, 2}},
5892 {{0, 2, 1}}, // 2
5893 {{1, 2, 0}},
5894 {{2, 1, 0}}, // 4
5895 {{2, 0, 1}}}};
5896
5897 relevant_lines[k] =
5898 hex->face(f)
5899 ->child(3 /*center triangle*/)
5900 ->line(
5901 table[triangulation.levels[hex->level()]
5902 ->face_orientations
5903 [hex->index() *
5905 dim>::faces_per_cell +
5906 f]][l]);
5907 }
5908
5909 relevant_lines[k++] = new_lines[0];
5910
5911 AssertDimension(k, 13);
5912 }
5913 else
5914 Assert(false, ExcNotImplemented());
5915
5916 boost::container::small_vector<unsigned int, 30>
5917 relevant_line_indices(relevant_lines.size());
5918 for (unsigned int i = 0; i < relevant_line_indices.size();
5919 ++i)
5920 relevant_line_indices[i] = relevant_lines[i]->index();
5921
5922 static constexpr std::array<std::array<unsigned int, 4>, 12>
5923 new_quad_lines_hex = {{{{10, 28, 16, 24}},
5924 {{28, 14, 17, 25}},
5925 {{11, 29, 24, 20}},
5926 {{29, 15, 25, 21}},
5927 {{18, 26, 0, 28}},
5928 {{26, 22, 1, 29}},
5929 {{19, 27, 28, 4}},
5930 {{27, 23, 29, 5}},
5931 {{2, 24, 8, 26}},
5932 {{24, 6, 9, 27}},
5933 {{3, 25, 26, 12}},
5934 {{25, 7, 27, 13}}}};
5935
5936 static constexpr std::array<std::array<unsigned int, 4>, 12>
5937 new_quad_lines_tet = {{{{2, 3, 8, X}},
5938 {{0, 9, 5, X}},
5939 {{1, 6, 11, X}},
5940 {{4, 10, 7, X}},
5941 {{2, 12, 5, X}},
5942 {{1, 9, 12, X}},
5943 {{4, 8, 12, X}},
5944 {{6, 12, 10, X}},
5945 {{X, X, X, X}},
5946 {{X, X, X, X}},
5947 {{X, X, X, X}},
5948 {{X, X, X, X}}}};
5949
5950 static constexpr std::
5951 array<std::array<std::array<unsigned int, 2>, 4>, 12>
5952 table_hex = {
5953 {{{{{10, 22}}, {{24, 26}}, {{10, 24}}, {{22, 26}}}},
5954 {{{{24, 26}}, {{11, 23}}, {{24, 11}}, {{26, 23}}}},
5955 {{{{22, 14}}, {{26, 25}}, {{22, 26}}, {{14, 25}}}},
5956 {{{{26, 25}}, {{23, 15}}, {{26, 23}}, {{25, 15}}}},
5957 {{{{8, 24}}, {{20, 26}}, {{8, 20}}, {{24, 26}}}},
5958 {{{{20, 26}}, {{12, 25}}, {{20, 12}}, {{26, 25}}}},
5959 {{{{24, 9}}, {{26, 21}}, {{24, 26}}, {{9, 21}}}},
5960 {{{{26, 21}}, {{25, 13}}, {{26, 25}}, {{21, 13}}}},
5961 {{{{16, 20}}, {{22, 26}}, {{16, 22}}, {{20, 26}}}},
5962 {{{{22, 26}}, {{17, 21}}, {{22, 17}}, {{26, 21}}}},
5963 {{{{20, 18}}, {{26, 23}}, {{20, 26}}, {{18, 23}}}},
5964 {{{{26, 23}}, {{21, 19}}, {{26, 21}}, {{23, 19}}}}}};
5965
5966 static constexpr std::
5967 array<std::array<std::array<unsigned int, 2>, 4>, 12>
5968 table_tet = {
5969 {{{{{6, 4}}, {{4, 7}}, {{7, 6}}, {{X, X}}}},
5970 {{{{4, 5}}, {{5, 8}}, {{8, 4}}, {{X, X}}}},
5971 {{{{5, 6}}, {{6, 9}}, {{9, 5}}, {{X, X}}}},
5972 {{{{7, 8}}, {{8, 9}}, {{9, 7}}, {{X, X}}}},
5973 {{{{4, 6}}, {{6, 8}}, {{8, 4}}, {{X, X}}}},
5974 {{{{6, 5}}, {{5, 8}}, {{8, 6}}, {{X, X}}}},
5975 {{{{8, 7}}, {{7, 6}}, {{6, 8}}, {{X, X}}}},
5976 {{{{9, 6}}, {{6, 8}}, {{8, 9}}, {{X, X}}}},
5977 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5978 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5979 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}},
5980 {{{{X, X}}, {{X, X}}, {{X, X}}, {{X, X}}}}}};
5981
5982 const auto &new_quad_lines =
5983 (reference_cell_type == ReferenceCells::Hexahedron) ?
5984 new_quad_lines_hex :
5985 new_quad_lines_tet;
5986
5987 const auto &table =
5988 (reference_cell_type == ReferenceCells::Hexahedron) ?
5989 table_hex :
5990 table_tet;
5991
5992 for (unsigned int q = 0; q < new_quads.size(); ++q)
5993 {
5994 for (unsigned int l = 0; l < 3; ++l)
5995 {
5996 std::array<unsigned int, 2> vertices_0, vertices_1;
5997
5998 for (unsigned int v = 0; v < 2; ++v)
5999 vertices_0[v] =
6000 relevant_lines[new_quad_lines[q][l]]
6001 ->vertex_index(v);
6002
6003 for (unsigned int v = 0; v < 2; ++v)
6004 vertices_1[v] = vertex_indices[table[q][l][v]];
6005 }
6006 }
6007
6008 for (unsigned int q = 0; q < new_quads.size(); ++q)
6009 {
6010 auto &new_quad = new_quads[q];
6011
6012 if (new_quad->n_lines() == 3)
6013 new_quad->set_bounding_object_indices(
6014 {relevant_line_indices[new_quad_lines[q][0]],
6015 relevant_line_indices[new_quad_lines[q][1]],
6016 relevant_line_indices[new_quad_lines[q][2]]});
6017 else if (new_quad->n_lines() == 4)
6018 new_quad->set_bounding_object_indices(
6019 {relevant_line_indices[new_quad_lines[q][0]],
6020 relevant_line_indices[new_quad_lines[q][1]],
6021 relevant_line_indices[new_quad_lines[q][2]],
6022 relevant_line_indices[new_quad_lines[q][3]]});
6023 else
6024 Assert(false, ExcNotImplemented());
6025
6026 for (const auto l : new_quad->line_indices())
6027 {
6028 std::array<unsigned int, 2> vertices_0, vertices_1;
6029
6030 for (unsigned int v = 0; v < 2; ++v)
6031 vertices_0[v] =
6032 relevant_lines[new_quad_lines[q][l]]
6033 ->vertex_index(v);
6034
6035 for (unsigned int v = 0; v < 2; ++v)
6036 vertices_1[v] = vertex_indices[table[q][l][v]];
6037
6038 const auto orientation =
6040 vertices_0, vertices_1);
6041
6042 new_quad->set_line_orientation(l, orientation);
6043 }
6044 }
6045 }
6046
6047 // set up new hex
6048 {
6049 std::array<int, 36> quad_indices;
6050
6051 if (reference_cell_type == ReferenceCells::Hexahedron)
6052 {
6053 for (unsigned int i = 0; i < new_quads.size(); ++i)
6054 quad_indices[i] = new_quads[i]->index();
6055
6056 for (unsigned int f = 0, k = new_quads.size(); f < 6;
6057 ++f)
6058 for (unsigned int c = 0; c < 4; ++c, ++k)
6059 quad_indices[k] =
6060 hex->face(f)->isotropic_child_index(
6062 c,
6063 hex->face_orientation(f),
6064 hex->face_flip(f),
6065 hex->face_rotation(f)));
6066 }
6067 else if (reference_cell_type == ReferenceCells::Tetrahedron)
6068 {
6069 for (unsigned int i = 0; i < new_quads.size(); ++i)
6070 quad_indices[i] = new_quads[i]->index();
6071
6072 for (unsigned int f = 0, k = new_quads.size(); f < 4;
6073 ++f)
6074 for (unsigned int c = 0; c < 4; ++c, ++k)
6075 {
6076 quad_indices[k] = hex->face(f)->child_index(
6077 (c == 3) ?
6078 3 :
6079 reference_cell_type
6080 .standard_to_real_face_vertex(
6081 c,
6082 f,
6083 triangulation.levels[hex->level()]
6084 ->face_orientations
6085 [hex->index() *
6087 f]));
6088 }
6089 }
6090 else
6091 {
6092 Assert(false, ExcNotImplemented());
6093 }
6094
6095 static constexpr std::array<std::array<unsigned int, 6>, 8>
6096 cell_quads_hex = {{
6097 {{12, 0, 20, 4, 28, 8}}, // bottom children
6098 {{0, 16, 22, 6, 29, 9}}, //
6099 {{13, 1, 4, 24, 30, 10}}, //
6100 {{1, 17, 6, 26, 31, 11}}, //
6101 {{14, 2, 21, 5, 8, 32}}, // top children
6102 {{2, 18, 23, 7, 9, 33}}, //
6103 {{15, 3, 5, 25, 10, 34}}, //
6104 {{3, 19, 7, 27, 11, 35}} //
6105 }};
6106
6107 static constexpr std::array<std::array<unsigned int, 6>, 8>
6108 cell_quads_tet{{{{8, 13, 16, 0, X, X}},
6109 {{9, 12, 1, 21, X, X}},
6110 {{10, 2, 17, 20, X, X}},
6111 {{3, 14, 18, 22, X, X}},
6112 {{11, 1, 4, 5, X, X}},
6113 {{15, 0, 4, 6, X, X}},
6114 {{19, 7, 6, 3, X, X}},
6115 {{23, 5, 2, 7, X, X}}}};
6116
6117 static constexpr std::
6118 array<std::array<std::array<unsigned int, 4>, 6>, 8>
6119 cell_face_vertices_hex{{{{{{0, 8, 16, 20}},
6120 {{10, 24, 22, 26}},
6121 {{0, 16, 10, 22}},
6122 {{8, 20, 24, 26}},
6123 {{0, 10, 8, 24}},
6124 {{16, 22, 20, 26}}}},
6125 {{{{10, 24, 22, 26}},
6126 {{1, 9, 17, 21}},
6127 {{10, 22, 1, 17}},
6128 {{24, 26, 9, 21}},
6129 {{10, 1, 24, 9}},
6130 {{22, 17, 26, 21}}}},
6131 {{{{8, 2, 20, 18}},
6132 {{24, 11, 26, 23}},
6133 {{8, 20, 24, 26}},
6134 {{2, 18, 11, 23}},
6135 {{8, 24, 2, 11}},
6136 {{20, 26, 18, 23}}}},
6137 {{{{24, 11, 26, 23}},
6138 {{9, 3, 21, 19}},
6139 {{24, 26, 9, 21}},
6140 {{11, 23, 3, 19}},
6141 {{24, 9, 11, 3}},
6142 {{26, 21, 23, 19}}}},
6143 {{{{16, 20, 4, 12}},
6144 {{22, 26, 14, 25}},
6145 {{16, 4, 22, 14}},
6146 {{20, 12, 26, 25}},
6147 {{16, 22, 20, 26}},
6148 {{4, 14, 12, 25}}}},
6149 {{{{22, 26, 14, 25}},
6150 {{17, 21, 5, 13}},
6151 {{22, 14, 17, 5}},
6152 {{26, 25, 21, 13}},
6153 {{22, 17, 26, 21}},
6154 {{14, 5, 25, 13}}}},
6155 {{{{20, 18, 12, 6}},
6156 {{26, 23, 25, 15}},
6157 {{20, 12, 26, 25}},
6158 {{18, 6, 23, 15}},
6159 {{20, 26, 18, 23}},
6160 {{12, 25, 6, 15}}}},
6161 {{{{26, 23, 25, 15}},
6162 {{21, 19, 13, 7}},
6163 {{26, 25, 21, 13}},
6164 {{23, 15, 19, 7}},
6165 {{26, 21, 23, 19}},
6166 {{25, 13, 15, 7}}}}}};
6167
6168 static constexpr std::
6169 array<std::array<std::array<unsigned int, 4>, 6>, 8>
6170 cell_face_vertices_tet{{{{{{0, 4, 6, X}},
6171 {{4, 0, 7, X}},
6172 {{0, 6, 7, X}},
6173 {{6, 4, 7, X}},
6174 {{X, X, X, X}},
6175 {{X, X, X, X}}}},
6176 {{{{4, 1, 5, X}},
6177 {{1, 4, 8, X}},
6178 {{4, 5, 8, X}},
6179 {{5, 1, 8, X}},
6180 {{X, X, X, X}},
6181 {{X, X, X, X}}}},
6182 {{{{6, 5, 2, X}},
6183 {{5, 6, 9, X}},
6184 {{6, 2, 9, X}},
6185 {{2, 5, 9, X}},
6186 {{X, X, X, X}},
6187 {{X, X, X, X}}}},
6188 {{{{7, 8, 9, X}},
6189 {{8, 7, 3, X}},
6190 {{7, 9, 3, X}},
6191 {{9, 8, 3, X}},
6192 {{X, X, X, X}},
6193 {{X, X, X, X}}}},
6194 {{{{4, 5, 6, X}},
6195 {{5, 4, 8, X}},
6196 {{4, 6, 8, X}},
6197 {{6, 5, 8, X}},
6198 {{X, X, X, X}},
6199 {{X, X, X, X}}}},
6200 {{{{4, 7, 8, X}},
6201 {{7, 4, 6, X}},
6202 {{4, 8, 6, X}},
6203 {{8, 7, 6, X}},
6204 {{X, X, X, X}},
6205 {{X, X, X, X}}}},
6206 {{{{6, 9, 7, X}},
6207 {{9, 6, 8, X}},
6208 {{6, 7, 8, X}},
6209 {{7, 9, 8, X}},
6210 {{X, X, X, X}},
6211 {{X, X, X, X}}}},
6212 {{{{5, 8, 9, X}},
6213 {{8, 5, 6, X}},
6214 {{5, 9, 6, X}},
6215 {{9, 8, 6, X}},
6216 {{X, X, X, X}},
6217 {{X, X, X, X}}}}}};
6218
6219 const auto &cell_quads =
6220 (reference_cell_type == ReferenceCells::Hexahedron) ?
6221 cell_quads_hex :
6222 cell_quads_tet;
6223
6224 const auto &cell_face_vertices =
6225 (reference_cell_type == ReferenceCells::Hexahedron) ?
6226 cell_face_vertices_hex :
6227 cell_face_vertices_tet;
6228
6229 for (unsigned int c = 0;
6230 c < GeometryInfo<dim>::max_children_per_cell;
6231 ++c)
6232 {
6233 auto &new_hex = new_hexes[c];
6234
6235 if (new_hex->n_faces() == 4)
6236 new_hex->set_bounding_object_indices(
6237 {quad_indices[cell_quads[c][0]],
6238 quad_indices[cell_quads[c][1]],
6239 quad_indices[cell_quads[c][2]],
6240 quad_indices[cell_quads[c][3]]});
6241 else if (new_hex->n_faces() == 6)
6242 new_hex->set_bounding_object_indices(
6243 {quad_indices[cell_quads[c][0]],
6244 quad_indices[cell_quads[c][1]],
6245 quad_indices[cell_quads[c][2]],
6246 quad_indices[cell_quads[c][3]],
6247 quad_indices[cell_quads[c][4]],
6248 quad_indices[cell_quads[c][5]]});
6249 else
6250 Assert(false, ExcNotImplemented());
6251
6252 for (const auto f : new_hex->face_indices())
6253 {
6254 std::array<unsigned int, 4> vertices_0, vertices_1;
6255
6256 const auto &face = new_hex->face(f);
6257
6258 for (const auto i : face->vertex_indices())
6259 vertices_0[i] = face->vertex_index(i);
6260
6261 for (const auto i : face->vertex_indices())
6262 vertices_1[i] =
6263 vertex_indices[cell_face_vertices[c][f][i]];
6264
6265 const auto orientation =
6266 face->reference_cell().compute_orientation(
6267 vertices_1, vertices_0);
6268
6269 new_hex->set_face_orientation(
6270 f, Utilities::get_bit(orientation, 0));
6271 new_hex->set_face_flip(
6272 f, Utilities::get_bit(orientation, 2));
6273 new_hex->set_face_rotation(
6274 f, Utilities::get_bit(orientation, 1));
6275 }
6276 }
6277 }
6278 }
6279
6280 if (check_for_distorted_cells &&
6281 has_distorted_children<dim, spacedim>(hex))
6282 cells_with_distorted_children.distorted_cells.push_back(hex);
6283
6284 triangulation.signals.post_refinement_on_cell(hex);
6285 }
6286 }
6287
6288 triangulation.faces->quads.clear_user_data();
6289
6290 return cells_with_distorted_children;
6291 }
6292
6297 template <int spacedim>
6300 const bool check_for_distorted_cells)
6301 {
6302 const unsigned int dim = 3;
6303
6304 {
6305 bool flag_isotropic_mesh = true;
6307 cell = triangulation.begin(),
6308 endc = triangulation.end();
6309 for (; cell != endc; ++cell)
6310 if (cell->used())
6311 if (triangulation.get_anisotropic_refinement_flag() ||
6312 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
6313 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
6314 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
6315 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
6316 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
6317 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
6318 {
6319 flag_isotropic_mesh = false;
6320 break;
6321 }
6322
6323 if (flag_isotropic_mesh)
6324 return execute_refinement_isotropic(triangulation,
6325 check_for_distorted_cells);
6326 }
6327
6328 // this function probably also works for spacedim>3 but it
6329 // isn't tested. it will probably be necessary to pull new
6330 // vertices onto the manifold just as we do for the other
6331 // functions above.
6332 Assert(spacedim == 3, ExcNotImplemented());
6333
6334 // Check whether a new level is needed. We have to check for
6335 // this on the highest level only
6336 for (const auto &cell : triangulation.active_cell_iterators_on_level(
6337 triangulation.levels.size() - 1))
6338 if (cell->refine_flag_set())
6339 {
6340 triangulation.levels.push_back(
6341 std::make_unique<
6343 break;
6344 }
6345
6346
6347 // first clear user flags for quads and lines; we're going to
6348 // use them to flag which lines and quads need refinement
6349 triangulation.faces->quads.clear_user_data();
6350
6352 triangulation.begin_line();
6353 line != triangulation.end_line();
6354 ++line)
6355 line->clear_user_flag();
6357 triangulation.begin_quad();
6358 quad != triangulation.end_quad();
6359 ++quad)
6360 quad->clear_user_flag();
6361
6362 // create an array of face refine cases. User indices of faces
6363 // will be set to values corresponding with indices in this
6364 // array.
6365 const RefinementCase<dim - 1> face_refinement_cases[4] = {
6366 RefinementCase<dim - 1>::no_refinement,
6367 RefinementCase<dim - 1>::cut_x,
6368 RefinementCase<dim - 1>::cut_y,
6369 RefinementCase<dim - 1>::cut_xy};
6370
6371 // check how much space is needed on every level. We need not
6372 // check the highest level since either
6373 // - on the highest level no cells are flagged for refinement
6374 // - there are, but prepare_refinement added another empty
6375 // level which then is the highest level
6376
6377 // variables to hold the number of newly to be created
6378 // vertices, lines and quads. as these are stored globally,
6379 // declare them outside the loop over al levels. we need lines
6380 // and quads in pairs for refinement of old ones and lines and
6381 // quads, that can be stored as single ones, as they are newly
6382 // created in the inside of an existing cell
6383 unsigned int needed_vertices = 0;
6384 unsigned int needed_lines_single = 0;
6385 unsigned int needed_quads_single = 0;
6386 unsigned int needed_lines_pair = 0;
6387 unsigned int needed_quads_pair = 0;
6388 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
6389 {
6390 // count number of flagged cells on this level and compute
6391 // how many new vertices and new lines will be needed
6392 unsigned int new_cells = 0;
6393
6394 for (const auto &acell :
6395 triangulation.active_cell_iterators_on_level(level))
6396 if (acell->refine_flag_set())
6397 {
6398 RefinementCase<dim> ref_case = acell->refine_flag_set();
6399
6400 // now for interior vertices, lines and quads, which
6401 // are needed in any case
6402 if (ref_case == RefinementCase<dim>::cut_x ||
6403 ref_case == RefinementCase<dim>::cut_y ||
6404 ref_case == RefinementCase<dim>::cut_z)
6405 {
6406 ++needed_quads_single;
6407 new_cells += 2;
6408 triangulation.anisotropic_refinement = true;
6409 }
6410 else if (ref_case == RefinementCase<dim>::cut_xy ||
6411 ref_case == RefinementCase<dim>::cut_xz ||
6412 ref_case == RefinementCase<dim>::cut_yz)
6413 {
6414 ++needed_lines_single;
6415 needed_quads_single += 4;
6416 new_cells += 4;
6417 triangulation.anisotropic_refinement = true;
6418 }
6419 else if (ref_case == RefinementCase<dim>::cut_xyz)
6420 {
6421 ++needed_vertices;
6422 needed_lines_single += 6;
6423 needed_quads_single += 12;
6424 new_cells += 8;
6425 }
6426 else
6427 {
6428 // we should never get here
6429 Assert(false, ExcInternalError());
6430 }
6431
6432 // mark all faces for refinement; checking locally
6433 // if and how the neighbor would like to refine
6434 // these is difficult so we only flag them and after
6435 // visiting all cells, we decide which faces need
6436 // which refinement;
6437 for (const unsigned int face :
6439 {
6441 aface = acell->face(face);
6442 // get the RefineCase this faces has for the
6443 // given RefineCase of the cell
6444 RefinementCase<dim - 1> face_ref_case =
6446 ref_case,
6447 face,
6448 acell->face_orientation(face),
6449 acell->face_flip(face),
6450 acell->face_rotation(face));
6451 // only do something, if this face has to be
6452 // refined
6453 if (face_ref_case)
6454 {
6455 if (face_ref_case ==
6457 {
6458 if (aface->n_active_descendants() < 4)
6459 // we use user_flags to denote needed
6460 // isotropic refinement
6461 aface->set_user_flag();
6462 }
6463 else if (aface->refinement_case() != face_ref_case)
6464 // we use user_indices to denote needed
6465 // anisotropic refinement. note, that we
6466 // can have at most one anisotropic
6467 // refinement case for this face, as
6468 // otherwise prepare_refinement() would
6469 // have changed one of the cells to yield
6470 // isotropic refinement at this
6471 // face. therefore we set the user_index
6472 // uniquely
6473 {
6474 Assert(aface->refinement_case() ==
6476 dim - 1>::isotropic_refinement ||
6477 aface->refinement_case() ==
6480 aface->set_user_index(face_ref_case);
6481 }
6482 }
6483 } // for all faces
6484
6485 // flag all lines, that have to be refined
6486 for (unsigned int line = 0;
6487 line < GeometryInfo<dim>::lines_per_cell;
6488 ++line)
6490 line) &&
6491 !acell->line(line)->has_children())
6492 acell->line(line)->set_user_flag();
6493
6494 } // if refine_flag set and for all cells on this level
6495
6496
6497 // count number of used cells on the next higher level
6498 const unsigned int used_cells =
6499 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6500 triangulation.levels[level + 1]->cells.used.end(),
6501 true);
6502
6503
6504 // reserve space for the used_cells cells already existing
6505 // on the next higher level as well as for the
6506 // 8*flagged_cells that will be created on that level
6507 reserve_space(*triangulation.levels[level + 1],
6508 used_cells + new_cells,
6509 3,
6510 spacedim);
6511 // reserve space for 8*flagged_cells new hexes on the next
6512 // higher level
6513 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6514 } // for all levels
6515 // now count the quads and lines which were flagged for
6516 // refinement
6518 triangulation.begin_quad();
6519 quad != triangulation.end_quad();
6520 ++quad)
6521 {
6522 if (quad->user_flag_set())
6523 {
6524 // isotropic refinement: 1 interior vertex, 4 quads
6525 // and 4 interior lines. we store the interior lines
6526 // in pairs in case the face is already or will be
6527 // refined anisotropically
6528 needed_quads_pair += 4;
6529 needed_lines_pair += 4;
6530 needed_vertices += 1;
6531 }
6532 if (quad->user_index())
6533 {
6534 // anisotropic refinement: 1 interior
6535 // line and two quads
6536 needed_quads_pair += 2;
6537 needed_lines_single += 1;
6538 // there is a kind of complicated situation here which
6539 // requires our attention. if the quad is refined
6540 // isotropcally, two of the interior lines will get a
6541 // new mother line - the interior line of our
6542 // anisotropically refined quad. if those two lines
6543 // are not consecutive, we cannot do so and have to
6544 // replace them by two lines that are consecutive. we
6545 // try to avoid that situation, but it may happen
6546 // nevertheless through repeated refinement and
6547 // coarsening. thus we have to check here, as we will
6548 // need some additional space to store those new lines
6549 // in case we need them...
6550 if (quad->has_children())
6551 {
6552 Assert(quad->refinement_case() ==
6555 if ((face_refinement_cases[quad->user_index()] ==
6557 (quad->child(0)->line_index(1) + 1 !=
6558 quad->child(2)->line_index(1))) ||
6559 (face_refinement_cases[quad->user_index()] ==
6561 (quad->child(0)->line_index(3) + 1 !=
6562 quad->child(1)->line_index(3))))
6563 needed_lines_pair += 2;
6564 }
6565 }
6566 }
6567
6569 triangulation.begin_line();
6570 line != triangulation.end_line();
6571 ++line)
6572 if (line->user_flag_set())
6573 {
6574 needed_lines_pair += 2;
6575 needed_vertices += 1;
6576 }
6577
6578 // reserve space for needed_lines new lines stored in pairs
6579 reserve_space(triangulation.faces->lines,
6580 needed_lines_pair,
6581 needed_lines_single);
6582 // reserve space for needed_quads new quads stored in pairs
6584 needed_quads_pair,
6585 needed_quads_single);
6586 reserve_space(triangulation.faces->quads,
6587 needed_quads_pair,
6588 needed_quads_single);
6589
6590
6591 // add to needed vertices how many vertices are already in use
6592 needed_vertices += std::count(triangulation.vertices_used.begin(),
6593 triangulation.vertices_used.end(),
6594 true);
6595 // if we need more vertices: create them, if not: leave the
6596 // array as is, since shrinking is not really possible because
6597 // some of the vertices at the end may be in use
6598 if (needed_vertices > triangulation.vertices.size())
6599 {
6600 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6601 triangulation.vertices_used.resize(needed_vertices, false);
6602 }
6603
6604
6605 //-----------------------------------------
6606 // Before we start with the actual refinement, we do some
6607 // sanity checks if in debug mode. especially, we try to catch
6608 // the notorious problem with lines being twice refined,
6609 // i.e. there are cells adjacent at one line ("around the
6610 // edge", but not at a face), with two cells differing by more
6611 // than one refinement level
6612 //
6613 // this check is very simple to implement here, since we have
6614 // all lines flagged if they shall be refined
6615#ifdef DEBUG
6616 for (const auto &cell : triangulation.active_cell_iterators())
6617 if (!cell->refine_flag_set())
6618 for (unsigned int line = 0;
6619 line < GeometryInfo<dim>::lines_per_cell;
6620 ++line)
6621 if (cell->line(line)->has_children())
6622 for (unsigned int c = 0; c < 2; ++c)
6623 Assert(cell->line(line)->child(c)->user_flag_set() == false,
6625#endif
6626
6627 //-----------------------------------------
6628 // Do refinement on every level
6629 //
6630 // To make life a bit easier, we first refine those lines and
6631 // quads that were flagged for refinement and then compose the
6632 // newly to be created cells.
6633 //
6634 // index of next unused vertex
6635 unsigned int next_unused_vertex = 0;
6636
6637 // first for lines
6638 {
6639 // only active objects can be refined further
6641 line = triangulation.begin_active_line(),
6642 endl = triangulation.end_line();
6644 next_unused_line = triangulation.begin_raw_line();
6645
6646 for (; line != endl; ++line)
6647 if (line->user_flag_set())
6648 {
6649 // this line needs to be refined
6650
6651 // find the next unused vertex and set it
6652 // appropriately
6653 while (triangulation.vertices_used[next_unused_vertex] == true)
6654 ++next_unused_vertex;
6655 Assert(
6656 next_unused_vertex < triangulation.vertices.size(),
6657 ExcMessage(
6658 "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."));
6659 triangulation.vertices_used[next_unused_vertex] = true;
6660
6661 triangulation.vertices[next_unused_vertex] = line->center(true);
6662
6663 // now that we created the right point, make up the
6664 // two child lines (++ takes care of the end of the
6665 // vector)
6666 next_unused_line =
6667 triangulation.faces->lines.template next_free_pair_object<1>(
6669 Assert(next_unused_line.state() == IteratorState::valid,
6671
6672 // now we found two consecutive unused lines, such
6673 // that the children of a line will be consecutive.
6674 // then set the child pointer of the present line
6675 line->set_children(0, next_unused_line->index());
6676
6677 // set the two new lines
6679 children[2] = {next_unused_line, ++next_unused_line};
6680
6681 // some tests; if any of the iterators should be
6682 // invalid, then already dereferencing will fail
6683 AssertIsNotUsed(children[0]);
6684 AssertIsNotUsed(children[1]);
6685
6686 children[0]->set_bounding_object_indices(
6687 {line->vertex_index(0), next_unused_vertex});
6688 children[1]->set_bounding_object_indices(
6689 {next_unused_vertex, line->vertex_index(1)});
6690
6691 children[0]->set_used_flag();
6692 children[1]->set_used_flag();
6693 children[0]->clear_children();
6694 children[1]->clear_children();
6695 children[0]->clear_user_data();
6696 children[1]->clear_user_data();
6697 children[0]->clear_user_flag();
6698 children[1]->clear_user_flag();
6699
6700 children[0]->set_boundary_id_internal(line->boundary_id());
6701 children[1]->set_boundary_id_internal(line->boundary_id());
6702
6703 children[0]->set_manifold_id(line->manifold_id());
6704 children[1]->set_manifold_id(line->manifold_id());
6705
6706 // finally clear flag
6707 // indicating the need
6708 // for refinement
6709 line->clear_user_flag();
6710 }
6711 }
6712
6713
6714 //-------------------------------------
6715 // now refine marked quads
6716 //-------------------------------------
6717
6718 // here we encounter several cases:
6719
6720 // a) the quad is unrefined and shall be refined isotropically
6721
6722 // b) the quad is unrefined and shall be refined
6723 // anisotropically
6724
6725 // c) the quad is unrefined and shall be refined both
6726 // anisotropically and isotropically (this is reduced to case
6727 // b) and then case b) for the children again)
6728
6729 // d) the quad is refined anisotropically and shall be refined
6730 // isotropically (this is reduced to case b) for the
6731 // anisotropic children)
6732
6733 // e) the quad is refined isotropically and shall be refined
6734 // anisotropically (this is transformed to case c), however we
6735 // might have to renumber/rename children...)
6736
6737 // we need a loop in cases c) and d), as the anisotropic
6738 // children might have a lower index than the mother quad
6739 for (unsigned int loop = 0; loop < 2; ++loop)
6740 {
6741 // usually, only active objects can be refined
6742 // further. however, in cases d) and e) that is not true,
6743 // so we have to use 'normal' iterators here
6745 quad = triangulation.begin_quad(),
6746 endq = triangulation.end_quad();
6748 next_unused_line = triangulation.begin_raw_line();
6750 next_unused_quad = triangulation.begin_raw_quad();
6751
6752 for (; quad != endq; ++quad)
6753 {
6754 if (quad->user_index())
6755 {
6756 RefinementCase<dim - 1> aniso_quad_ref_case =
6757 face_refinement_cases[quad->user_index()];
6758 // there is one unlikely event here, where we
6759 // already have refind the face: if the face was
6760 // refined anisotropically and we want to refine
6761 // it isotropically, both children are flagged for
6762 // anisotropic refinement. however, if those
6763 // children were already flagged for anisotropic
6764 // refinement, they might already be processed and
6765 // refined.
6766 if (aniso_quad_ref_case == quad->refinement_case())
6767 continue;
6768
6769 Assert(quad->refinement_case() ==
6771 quad->refinement_case() ==
6774
6775 // this quad needs to be refined anisotropically
6776 Assert(quad->user_index() ==
6778 quad->user_index() ==
6781
6782 // make the new line interior to the quad
6784 new_line;
6785
6786 new_line =
6787 triangulation.faces->lines
6788 .template next_free_single_object<1>(triangulation);
6789 AssertIsNotUsed(new_line);
6790
6791 // first collect the
6792 // indices of the vertices:
6793 // *--1--*
6794 // | | |
6795 // | | | cut_x
6796 // | | |
6797 // *--0--*
6798 //
6799 // *-----*
6800 // | |
6801 // 0-----1 cut_y
6802 // | |
6803 // *-----*
6804 unsigned int vertex_indices[2];
6805 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6806 {
6807 vertex_indices[0] =
6808 quad->line(2)->child(0)->vertex_index(1);
6809 vertex_indices[1] =
6810 quad->line(3)->child(0)->vertex_index(1);
6811 }
6812 else
6813 {
6814 vertex_indices[0] =
6815 quad->line(0)->child(0)->vertex_index(1);
6816 vertex_indices[1] =
6817 quad->line(1)->child(0)->vertex_index(1);
6818 }
6819
6820 new_line->set_bounding_object_indices(
6822 new_line->set_used_flag();
6823 new_line->clear_user_flag();
6824 new_line->clear_user_data();
6825 new_line->clear_children();
6826 new_line->set_boundary_id_internal(quad->boundary_id());
6827 new_line->set_manifold_id(quad->manifold_id());
6828
6829 // child 0 and 1 of a line are switched if the
6830 // line orientation is false. set up a miniature
6831 // table, indicating which child to take for line
6832 // orientations false and true. first index: child
6833 // index in standard orientation, second index:
6834 // line orientation
6835 const unsigned int index[2][2] = {
6836 {1, 0}, // child 0, line_orientation=false and true
6837 {0, 1}}; // child 1, line_orientation=false and true
6838
6839 // find some space (consecutive) for the two newly
6840 // to be created quads.
6842 new_quads[2];
6843
6844 next_unused_quad =
6845 triangulation.faces->quads
6846 .template next_free_pair_object<2>(triangulation);
6847 new_quads[0] = next_unused_quad;
6848 AssertIsNotUsed(new_quads[0]);
6849
6850 ++next_unused_quad;
6851 new_quads[1] = next_unused_quad;
6852 AssertIsNotUsed(new_quads[1]);
6853
6854 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6855 {
6856 new_quads[0]->set_bounding_object_indices(
6857 {static_cast<int>(quad->line_index(0)),
6858 new_line->index(),
6859 quad->line(2)
6860 ->child(index[0][quad->line_orientation(2)])
6861 ->index(),
6862 quad->line(3)
6863 ->child(index[0][quad->line_orientation(3)])
6864 ->index()});
6865 new_quads[1]->set_bounding_object_indices(
6866 {new_line->index(),
6867 static_cast<int>(quad->line_index(1)),
6868 quad->line(2)
6869 ->child(index[1][quad->line_orientation(2)])
6870 ->index(),
6871 quad->line(3)
6872 ->child(index[1][quad->line_orientation(3)])
6873 ->index()});
6874 }
6875 else
6876 {
6877 new_quads[0]->set_bounding_object_indices(
6878 {quad->line(0)
6879 ->child(index[0][quad->line_orientation(0)])
6880 ->index(),
6881 quad->line(1)
6882 ->child(index[0][quad->line_orientation(1)])
6883 ->index(),
6884 static_cast<int>(quad->line_index(2)),
6885 new_line->index()});
6886 new_quads[1]->set_bounding_object_indices(
6887 {quad->line(0)
6888 ->child(index[1][quad->line_orientation(0)])
6889 ->index(),
6890 quad->line(1)
6891 ->child(index[1][quad->line_orientation(1)])
6892 ->index(),
6893 new_line->index(),
6894 static_cast<int>(quad->line_index(3))});
6895 }
6896
6897 for (const auto &new_quad : new_quads)
6898 {
6899 new_quad->set_used_flag();
6900 new_quad->clear_user_flag();
6901 new_quad->clear_user_data();
6902 new_quad->clear_children();
6903 new_quad->set_boundary_id_internal(quad->boundary_id());
6904 new_quad->set_manifold_id(quad->manifold_id());
6905 // set all line orientations to true, change
6906 // this after the loop, as we have to consider
6907 // different lines for each child
6908 for (unsigned int j = 0;
6909 j < GeometryInfo<dim>::lines_per_face;
6910 ++j)
6911 new_quad->set_line_orientation(j, true);
6912 }
6913 // now set the line orientation of children of
6914 // outer lines correctly, the lines in the
6915 // interior of the refined quad are automatically
6916 // oriented conforming to the standard
6917 new_quads[0]->set_line_orientation(
6918 0, quad->line_orientation(0));
6919 new_quads[0]->set_line_orientation(
6920 2, quad->line_orientation(2));
6921 new_quads[1]->set_line_orientation(
6922 1, quad->line_orientation(1));
6923 new_quads[1]->set_line_orientation(
6924 3, quad->line_orientation(3));
6925 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
6926 {
6927 new_quads[0]->set_line_orientation(
6928 3, quad->line_orientation(3));
6929 new_quads[1]->set_line_orientation(
6930 2, quad->line_orientation(2));
6931 }
6932 else
6933 {
6934 new_quads[0]->set_line_orientation(
6935 1, quad->line_orientation(1));
6936 new_quads[1]->set_line_orientation(
6937 0, quad->line_orientation(0));
6938 }
6939
6940 // test, whether this face is refined
6941 // isotropically already. if so, set the correct
6942 // children pointers.
6943 if (quad->refinement_case() ==
6944 RefinementCase<dim - 1>::cut_xy)
6945 {
6946 // we will put a new refinemnt level of
6947 // anisotropic refinement between the
6948 // unrefined and isotropically refined quad
6949 // ending up with the same fine quads but
6950 // introducing anisotropically refined ones as
6951 // children of the unrefined quad and mother
6952 // cells of the original fine ones.
6953
6954 // this process includes the creation of a new
6955 // middle line which we will assign as the
6956 // mother line of two of the existing inner
6957 // lines. If those inner lines are not
6958 // consecutive in memory, we won't find them
6959 // later on, so we have to create new ones
6960 // instead and replace all occurrences of the
6961 // old ones with those new ones. As this is
6962 // kind of ugly, we hope we don't have to do
6963 // it often...
6965 old_child[2];
6966 if (aniso_quad_ref_case ==
6968 {
6969 old_child[0] = quad->child(0)->line(1);
6970 old_child[1] = quad->child(2)->line(1);
6971 }
6972 else
6973 {
6974 Assert(aniso_quad_ref_case ==
6977
6978 old_child[0] = quad->child(0)->line(3);
6979 old_child[1] = quad->child(1)->line(3);
6980 }
6981
6982 if (old_child[0]->index() + 1 != old_child[1]->index())
6983 {
6984 // this is exactly the ugly case we taked
6985 // about. so, no coimplaining, lets get
6986 // two new lines and copy all info
6987 typename Triangulation<dim,
6988 spacedim>::raw_line_iterator
6989 new_child[2];
6990
6991 new_child[0] = new_child[1] =
6992 triangulation.faces->lines
6993 .template next_free_pair_object<1>(
6995 ++new_child[1];
6996
6997 new_child[0]->set_used_flag();
6998 new_child[1]->set_used_flag();
6999
7000 const int old_index_0 = old_child[0]->index(),
7001 old_index_1 = old_child[1]->index(),
7002 new_index_0 = new_child[0]->index(),
7003 new_index_1 = new_child[1]->index();
7004
7005 // loop over all quads and replace the old
7006 // lines
7007 for (unsigned int q = 0;
7008 q < triangulation.faces->quads.n_objects();
7009 ++q)
7010 for (unsigned int l = 0;
7011 l < GeometryInfo<dim>::lines_per_face;
7012 ++l)
7013 {
7014 const int this_index =
7015 triangulation.faces->quads
7016 .get_bounding_object_indices(q)[l];
7017 if (this_index == old_index_0)
7018 triangulation.faces->quads
7019 .get_bounding_object_indices(q)[l] =
7020 new_index_0;
7021 else if (this_index == old_index_1)
7022 triangulation.faces->quads
7023 .get_bounding_object_indices(q)[l] =
7024 new_index_1;
7025 }
7026 // now we have to copy all information of
7027 // the two lines
7028 for (unsigned int i = 0; i < 2; ++i)
7029 {
7030 Assert(!old_child[i]->has_children(),
7032
7033 new_child[i]->set_bounding_object_indices(
7034 {old_child[i]->vertex_index(0),
7035 old_child[i]->vertex_index(1)});
7036 new_child[i]->set_boundary_id_internal(
7037 old_child[i]->boundary_id());
7038 new_child[i]->set_manifold_id(
7039 old_child[i]->manifold_id());
7040 new_child[i]->set_user_index(
7041 old_child[i]->user_index());
7042 if (old_child[i]->user_flag_set())
7043 new_child[i]->set_user_flag();
7044 else
7045 new_child[i]->clear_user_flag();
7046
7047 new_child[i]->clear_children();
7048
7049 old_child[i]->clear_user_flag();
7050 old_child[i]->clear_user_index();
7051 old_child[i]->clear_used_flag();
7052 }
7053 }
7054 // now that we cared about the lines, go on
7055 // with the quads themselves, where we might
7056 // encounter similar situations...
7057 if (aniso_quad_ref_case ==
7059 {
7060 new_line->set_children(
7061 0, quad->child(0)->line_index(1));
7062 Assert(new_line->child(1) ==
7063 quad->child(2)->line(1),
7065 // now evereything is quite
7066 // complicated. we have the children
7067 // numbered according to
7068 //
7069 // *---*---*
7070 // |n+2|n+3|
7071 // *---*---*
7072 // | n |n+1|
7073 // *---*---*
7074 //
7075 // from the original isotropic
7076 // refinement. we have to reorder them as
7077 //
7078 // *---*---*
7079 // |n+1|n+3|
7080 // *---*---*
7081 // | n |n+2|
7082 // *---*---*
7083 //
7084 // such that n and n+1 are consecutive
7085 // children of m and n+2 and n+3 are
7086 // consecutive children of m+1, where m
7087 // and m+1 are given as in
7088 //
7089 // *---*---*
7090 // | | |
7091 // | m |m+1|
7092 // | | |
7093 // *---*---*
7094 //
7095 // this is a bit ugly, of course: loop
7096 // over all cells on all levels and look
7097 // for faces n+1 (switch_1) and n+2
7098 // (switch_2).
7099 const typename Triangulation<dim, spacedim>::
7100 quad_iterator switch_1 = quad->child(1),
7101 switch_2 = quad->child(2);
7102 const int switch_1_index = switch_1->index();
7103 const int switch_2_index = switch_2->index();
7104 for (unsigned int l = 0;
7105 l < triangulation.levels.size();
7106 ++l)
7107 for (unsigned int h = 0;
7108 h <
7109 triangulation.levels[l]->cells.n_objects();
7110 ++h)
7111 for (const unsigned int q :
7113 {
7114 const int face_index =
7115 triangulation.levels[l]
7116 ->cells.get_bounding_object_indices(
7117 h)[q];
7118 if (face_index == switch_1_index)
7119 triangulation.levels[l]
7120 ->cells.get_bounding_object_indices(
7121 h)[q] = switch_2_index;
7122 else if (face_index == switch_2_index)
7123 triangulation.levels[l]
7124 ->cells.get_bounding_object_indices(
7125 h)[q] = switch_1_index;
7126 }
7127 // now we have to copy all information of
7128 // the two quads
7129 const unsigned int switch_1_lines[4] = {
7130 switch_1->line_index(0),
7131 switch_1->line_index(1),
7132 switch_1->line_index(2),
7133 switch_1->line_index(3)};
7134 const bool switch_1_line_orientations[4] = {
7135 switch_1->line_orientation(0),
7136 switch_1->line_orientation(1),
7137 switch_1->line_orientation(2),
7138 switch_1->line_orientation(3)};
7139 const types::boundary_id switch_1_boundary_id =
7140 switch_1->boundary_id();
7141 const unsigned int switch_1_user_index =
7142 switch_1->user_index();
7143 const bool switch_1_user_flag =
7144 switch_1->user_flag_set();
7145 const RefinementCase<dim - 1>
7146 switch_1_refinement_case =
7147 switch_1->refinement_case();
7148 const int switch_1_first_child_pair =
7149 (switch_1_refinement_case ?
7150 switch_1->child_index(0) :
7151 -1);
7152 const int switch_1_second_child_pair =
7153 (switch_1_refinement_case ==
7154 RefinementCase<dim - 1>::cut_xy ?
7155 switch_1->child_index(2) :
7156 -1);
7157
7158 switch_1->set_bounding_object_indices(
7159 {switch_2->line_index(0),
7160 switch_2->line_index(1),
7161 switch_2->line_index(2),
7162 switch_2->line_index(3)});
7163 switch_1->set_line_orientation(
7164 0, switch_2->line_orientation(0));
7165 switch_1->set_line_orientation(
7166 1, switch_2->line_orientation(1));
7167 switch_1->set_line_orientation(
7168 2, switch_2->line_orientation(2));
7169 switch_1->set_line_orientation(
7170 3, switch_2->line_orientation(3));
7171 switch_1->set_boundary_id_internal(
7172 switch_2->boundary_id());
7173 switch_1->set_manifold_id(switch_2->manifold_id());
7174 switch_1->set_user_index(switch_2->user_index());
7175 if (switch_2->user_flag_set())
7176 switch_1->set_user_flag();
7177 else
7178 switch_1->clear_user_flag();
7179 switch_1->clear_refinement_case();
7180 switch_1->set_refinement_case(
7181 switch_2->refinement_case());
7182 switch_1->clear_children();
7183 if (switch_2->refinement_case())
7184 switch_1->set_children(0,
7185 switch_2->child_index(0));
7186 if (switch_2->refinement_case() ==
7187 RefinementCase<dim - 1>::cut_xy)
7188 switch_1->set_children(2,
7189 switch_2->child_index(2));
7190
7191 switch_2->set_bounding_object_indices(
7192 {switch_1_lines[0],
7193 switch_1_lines[1],
7194 switch_1_lines[2],
7195 switch_1_lines[3]});
7196 switch_2->set_line_orientation(
7197 0, switch_1_line_orientations[0]);
7198 switch_2->set_line_orientation(
7199 1, switch_1_line_orientations[1]);
7200 switch_2->set_line_orientation(
7201 2, switch_1_line_orientations[2]);
7202 switch_2->set_line_orientation(
7203 3, switch_1_line_orientations[3]);
7204 switch_2->set_boundary_id_internal(
7205 switch_1_boundary_id);
7206 switch_2->set_manifold_id(switch_1->manifold_id());
7207 switch_2->set_user_index(switch_1_user_index);
7208 if (switch_1_user_flag)
7209 switch_2->set_user_flag();
7210 else
7211 switch_2->clear_user_flag();
7212 switch_2->clear_refinement_case();
7213 switch_2->set_refinement_case(
7214 switch_1_refinement_case);
7215 switch_2->clear_children();
7216 switch_2->set_children(0,
7217 switch_1_first_child_pair);
7218 switch_2->set_children(2,
7219 switch_1_second_child_pair);
7220
7221 new_quads[0]->set_refinement_case(
7223 new_quads[0]->set_children(0, quad->child_index(0));
7224 new_quads[1]->set_refinement_case(
7226 new_quads[1]->set_children(0, quad->child_index(2));
7227 }
7228 else
7229 {
7230 new_quads[0]->set_refinement_case(
7232 new_quads[0]->set_children(0, quad->child_index(0));
7233 new_quads[1]->set_refinement_case(
7235 new_quads[1]->set_children(0, quad->child_index(2));
7236 new_line->set_children(
7237 0, quad->child(0)->line_index(3));
7238 Assert(new_line->child(1) ==
7239 quad->child(1)->line(3),
7241 }
7242 quad->clear_children();
7243 }
7244
7245 // note these quads as children to the present one
7246 quad->set_children(0, new_quads[0]->index());
7247
7248 quad->set_refinement_case(aniso_quad_ref_case);
7249
7250 // finally clear flag indicating the need for
7251 // refinement
7252 quad->clear_user_data();
7253 } // if (anisotropic refinement)
7254
7255 if (quad->user_flag_set())
7256 {
7257 // this quad needs to be refined isotropically
7258
7259 // first of all: we only get here in the first run
7260 // of the loop
7261 Assert(loop == 0, ExcInternalError());
7262
7263 // find the next unused vertex. we'll need this in
7264 // any case
7265 while (triangulation.vertices_used[next_unused_vertex] ==
7266 true)
7267 ++next_unused_vertex;
7268 Assert(
7269 next_unused_vertex < triangulation.vertices.size(),
7270 ExcMessage(
7271 "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."));
7272
7273 // now: if the quad is refined anisotropically
7274 // already, set the anisotropic refinement flag
7275 // for both children. Additionally, we have to
7276 // refine the inner line, as it is an outer line
7277 // of the two (anisotropic) children
7278 const RefinementCase<dim - 1> quad_ref_case =
7279 quad->refinement_case();
7280
7281 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
7282 quad_ref_case == RefinementCase<dim - 1>::cut_y)
7283 {
7284 // set the 'opposite' refine case for children
7285 quad->child(0)->set_user_index(
7286 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
7287 quad->child(1)->set_user_index(
7288 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
7289 // refine the inner line
7291 middle_line;
7292 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
7293 middle_line = quad->child(0)->line(1);
7294 else
7295 middle_line = quad->child(0)->line(3);
7296
7297 // if the face has been refined
7298 // anisotropically in the last refinement step
7299 // it might be, that it is flagged already and
7300 // that the middle line is thus refined
7301 // already. if not create children.
7302 if (!middle_line->has_children())
7303 {
7304 // set the middle vertex
7305 // appropriately. double refinement of
7306 // quads can only happen in the interior
7307 // of the domain, so we need not care
7308 // about boundary quads here
7309 triangulation.vertices[next_unused_vertex] =
7310 middle_line->center(true);
7311 triangulation.vertices_used[next_unused_vertex] =
7312 true;
7313
7314 // now search a slot for the two
7315 // child lines
7316 next_unused_line =
7317 triangulation.faces->lines
7318 .template next_free_pair_object<1>(
7320
7321 // set the child pointer of the present
7322 // line
7323 middle_line->set_children(
7324 0, next_unused_line->index());
7325
7326 // set the two new lines
7327 const typename Triangulation<dim, spacedim>::
7328 raw_line_iterator children[2] = {
7329 next_unused_line, ++next_unused_line};
7330
7331 // some tests; if any of the iterators
7332 // should be invalid, then already
7333 // dereferencing will fail
7334 AssertIsNotUsed(children[0]);
7335 AssertIsNotUsed(children[1]);
7336
7337 children[0]->set_bounding_object_indices(
7338 {middle_line->vertex_index(0),
7339 next_unused_vertex});
7340 children[1]->set_bounding_object_indices(
7341 {next_unused_vertex,
7342 middle_line->vertex_index(1)});
7343
7344 children[0]->set_used_flag();
7345 children[1]->set_used_flag();
7346 children[0]->clear_children();
7347 children[1]->clear_children();
7348 children[0]->clear_user_data();
7349 children[1]->clear_user_data();
7350 children[0]->clear_user_flag();
7351 children[1]->clear_user_flag();
7352
7353 children[0]->set_boundary_id_internal(
7354 middle_line->boundary_id());
7355 children[1]->set_boundary_id_internal(
7356 middle_line->boundary_id());
7357
7358 children[0]->set_manifold_id(
7359 middle_line->manifold_id());
7360 children[1]->set_manifold_id(
7361 middle_line->manifold_id());
7362 }
7363 // now remove the flag from the quad and go to
7364 // the next quad, the actual refinement of the
7365 // quad takes place later on in this pass of
7366 // the loop or in the next one
7367 quad->clear_user_flag();
7368 continue;
7369 } // if (several refinement cases)
7370
7371 // if we got here, we have an unrefined quad and
7372 // have to do the usual work like in an purely
7373 // isotropic refinement
7374 Assert(quad_ref_case ==
7377
7378 // set the middle vertex appropriately: it might be that
7379 // the quad itself is not at the boundary, but that one of
7380 // its lines actually is. in this case, the newly created
7381 // vertices at the centers of the lines are not
7382 // necessarily the mean values of the adjacent vertices,
7383 // so do not compute the new vertex as the mean value of
7384 // the 4 vertices of the face, but rather as a weighted
7385 // mean value of the 8 vertices which we already have (the
7386 // four old ones, and the four ones inserted as middle
7387 // points for the four lines). summing up some more points
7388 // is generally cheaper than first asking whether one of
7389 // the lines is at the boundary
7390 //
7391 // note that the exact weights are chosen such as to
7392 // minimize the distortion of the four new quads from the
7393 // optimal shape. their description uses the formulas
7394 // underlying the TransfiniteInterpolationManifold
7395 // implementation
7396 triangulation.vertices[next_unused_vertex] =
7397 quad->center(true, true);
7398 triangulation.vertices_used[next_unused_vertex] = true;
7399
7400 // now that we created the right point, make up
7401 // the four lines interior to the quad (++ takes
7402 // care of the end of the vector)
7404 new_lines[4];
7405
7406 for (unsigned int i = 0; i < 4; ++i)
7407 {
7408 if (i % 2 == 0)
7409 // search a free pair of lines for 0. and
7410 // 2. line, so that two of them end up
7411 // together, which is necessary if later on
7412 // we want to refine the quad
7413 // anisotropically and the two lines end up
7414 // as children of new line
7415 next_unused_line =
7416 triangulation.faces->lines
7417 .template next_free_pair_object<1>(triangulation);
7418
7419 new_lines[i] = next_unused_line;
7420 ++next_unused_line;
7421
7422 AssertIsNotUsed(new_lines[i]);
7423 }
7424
7425 // set the data of the four lines. first collect
7426 // the indices of the five vertices:
7427 //
7428 // *--3--*
7429 // | | |
7430 // 0--4--1
7431 // | | |
7432 // *--2--*
7433 //
7434 // the lines are numbered as follows:
7435 //
7436 // *--*--*
7437 // | 1 |
7438 // *2-*-3*
7439 // | 0 |
7440 // *--*--*
7441
7442 const unsigned int vertex_indices[5] = {
7443 quad->line(0)->child(0)->vertex_index(1),
7444 quad->line(1)->child(0)->vertex_index(1),
7445 quad->line(2)->child(0)->vertex_index(1),
7446 quad->line(3)->child(0)->vertex_index(1),
7447 next_unused_vertex};
7448
7449 new_lines[0]->set_bounding_object_indices(
7451 new_lines[1]->set_bounding_object_indices(
7453 new_lines[2]->set_bounding_object_indices(
7455 new_lines[3]->set_bounding_object_indices(
7457
7458 for (const auto &new_line : new_lines)
7459 {
7460 new_line->set_used_flag();
7461 new_line->clear_user_flag();
7462 new_line->clear_user_data();
7463 new_line->clear_children();
7464 new_line->set_boundary_id_internal(quad->boundary_id());
7465 new_line->set_manifold_id(quad->manifold_id());
7466 }
7467
7468 // now for the quads. again, first collect some
7469 // data about the indices of the lines, with the
7470 // following numbering:
7471 //
7472 // .-6-.-7-.
7473 // 1 9 3
7474 // .-10.11-.
7475 // 0 8 2
7476 // .-4-.-5-.
7477
7478 // child 0 and 1 of a line are switched if the
7479 // line orientation is false. set up a miniature
7480 // table, indicating which child to take for line
7481 // orientations false and true. first index: child
7482 // index in standard orientation, second index:
7483 // line orientation
7484 const unsigned int index[2][2] = {
7485 {1, 0}, // child 0, line_orientation=false and true
7486 {0, 1}}; // child 1, line_orientation=false and true
7487
7488 const int line_indices[12] = {
7489 quad->line(0)
7490 ->child(index[0][quad->line_orientation(0)])
7491 ->index(),
7492 quad->line(0)
7493 ->child(index[1][quad->line_orientation(0)])
7494 ->index(),
7495 quad->line(1)
7496 ->child(index[0][quad->line_orientation(1)])
7497 ->index(),
7498 quad->line(1)
7499 ->child(index[1][quad->line_orientation(1)])
7500 ->index(),
7501 quad->line(2)
7502 ->child(index[0][quad->line_orientation(2)])
7503 ->index(),
7504 quad->line(2)
7505 ->child(index[1][quad->line_orientation(2)])
7506 ->index(),
7507 quad->line(3)
7508 ->child(index[0][quad->line_orientation(3)])
7509 ->index(),
7510 quad->line(3)
7511 ->child(index[1][quad->line_orientation(3)])
7512 ->index(),
7513 new_lines[0]->index(),
7514 new_lines[1]->index(),
7515 new_lines[2]->index(),
7516 new_lines[3]->index()};
7517
7518 // find some space (consecutive)
7519 // for the first two newly to be
7520 // created quads.
7522 new_quads[4];
7523
7524 next_unused_quad =
7525 triangulation.faces->quads
7526 .template next_free_pair_object<2>(triangulation);
7527
7528 new_quads[0] = next_unused_quad;
7529 AssertIsNotUsed(new_quads[0]);
7530
7531 ++next_unused_quad;
7532 new_quads[1] = next_unused_quad;
7533 AssertIsNotUsed(new_quads[1]);
7534
7535 next_unused_quad =
7536 triangulation.faces->quads
7537 .template next_free_pair_object<2>(triangulation);
7538 new_quads[2] = next_unused_quad;
7539 AssertIsNotUsed(new_quads[2]);
7540
7541 ++next_unused_quad;
7542 new_quads[3] = next_unused_quad;
7543 AssertIsNotUsed(new_quads[3]);
7544
7545 // note these quads as children to the present one
7546 quad->set_children(0, new_quads[0]->index());
7547 quad->set_children(2, new_quads[2]->index());
7548 quad->set_refinement_case(RefinementCase<2>::cut_xy);
7549
7550 new_quads[0]->set_bounding_object_indices(
7551 {line_indices[0],
7552 line_indices[8],
7553 line_indices[4],
7554 line_indices[10]});
7555 new_quads[1]->set_bounding_object_indices(
7556 {line_indices[8],
7557 line_indices[2],
7558 line_indices[5],
7559 line_indices[11]});
7560 new_quads[2]->set_bounding_object_indices(
7561 {line_indices[1],
7562 line_indices[9],
7563 line_indices[10],
7564 line_indices[6]});
7565 new_quads[3]->set_bounding_object_indices(
7566 {line_indices[9],
7567 line_indices[3],
7568 line_indices[11],
7569 line_indices[7]});
7570 for (const auto &new_quad : new_quads)
7571 {
7572 new_quad->set_used_flag();
7573 new_quad->clear_user_flag();
7574 new_quad->clear_user_data();
7575 new_quad->clear_children();
7576 new_quad->set_boundary_id_internal(quad->boundary_id());
7577 new_quad->set_manifold_id(quad->manifold_id());
7578 // set all line orientations to true, change
7579 // this after the loop, as we have to consider
7580 // different lines for each child
7581 for (unsigned int j = 0;
7582 j < GeometryInfo<dim>::lines_per_face;
7583 ++j)
7584 new_quad->set_line_orientation(j, true);
7585 }
7586 // now set the line orientation of children of
7587 // outer lines correctly, the lines in the
7588 // interior of the refined quad are automatically
7589 // oriented conforming to the standard
7590 new_quads[0]->set_line_orientation(
7591 0, quad->line_orientation(0));
7592 new_quads[0]->set_line_orientation(
7593 2, quad->line_orientation(2));
7594 new_quads[1]->set_line_orientation(
7595 1, quad->line_orientation(1));
7596 new_quads[1]->set_line_orientation(
7597 2, quad->line_orientation(2));
7598 new_quads[2]->set_line_orientation(
7599 0, quad->line_orientation(0));
7600 new_quads[2]->set_line_orientation(
7601 3, quad->line_orientation(3));
7602 new_quads[3]->set_line_orientation(
7603 1, quad->line_orientation(1));
7604 new_quads[3]->set_line_orientation(
7605 3, quad->line_orientation(3));
7606
7607 // finally clear flag indicating the need for
7608 // refinement
7609 quad->clear_user_flag();
7610 } // if (isotropic refinement)
7611 } // for all quads
7612 } // looped two times over all quads, all quads refined now
7613
7614 //---------------------------------
7615 // Now, finally, set up the new
7616 // cells
7617 //---------------------------------
7618
7620 cells_with_distorted_children;
7621
7622 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
7623 ++level)
7624 {
7625 // only active objects can be refined further; remember
7626 // that we won't operate on the finest level, so
7627 // triangulation.begin_*(level+1) is allowed
7629 hex = triangulation.begin_active_hex(level),
7630 endh = triangulation.begin_active_hex(level + 1);
7632 next_unused_hex = triangulation.begin_raw_hex(level + 1);
7633
7634 for (; hex != endh; ++hex)
7635 if (hex->refine_flag_set())
7636 {
7637 // this hex needs to be refined
7638
7639 // clear flag indicating the need for refinement. do
7640 // it here already, since we can't do it anymore
7641 // once the cell has children
7642 const RefinementCase<dim> ref_case = hex->refine_flag_set();
7643 hex->clear_refine_flag();
7644 hex->set_refinement_case(ref_case);
7645
7646 // depending on the refine case we might have to
7647 // create additional vertices, lines and quads
7648 // interior of the hex before the actual children
7649 // can be set up.
7650
7651 // in a first step: reserve the needed space for
7652 // lines, quads and hexes and initialize them
7653 // correctly
7654
7655 unsigned int n_new_lines = 0;
7656 unsigned int n_new_quads = 0;
7657 unsigned int n_new_hexes = 0;
7658 switch (ref_case)
7659 {
7663 n_new_lines = 0;
7664 n_new_quads = 1;
7665 n_new_hexes = 2;
7666 break;
7670 n_new_lines = 1;
7671 n_new_quads = 4;
7672 n_new_hexes = 4;
7673 break;
7675 n_new_lines = 6;
7676 n_new_quads = 12;
7677 n_new_hexes = 8;
7678 break;
7679 default:
7680 Assert(false, ExcInternalError());
7681 break;
7682 }
7683
7684 // find some space for the newly to be created
7685 // interior lines and initialize them.
7686 std::vector<
7688 new_lines(n_new_lines);
7689 for (unsigned int i = 0; i < n_new_lines; ++i)
7690 {
7691 new_lines[i] =
7692 triangulation.faces->lines
7693 .template next_free_single_object<1>(triangulation);
7694
7695 AssertIsNotUsed(new_lines[i]);
7696 new_lines[i]->set_used_flag();
7697 new_lines[i]->clear_user_flag();
7698 new_lines[i]->clear_user_data();
7699 new_lines[i]->clear_children();
7700 // interior line
7701 new_lines[i]->set_boundary_id_internal(
7703 // they inherit geometry description of the hex they
7704 // belong to
7705 new_lines[i]->set_manifold_id(hex->manifold_id());
7706 }
7707
7708 // find some space for the newly to be created
7709 // interior quads and initialize them.
7710 std::vector<
7712 new_quads(n_new_quads);
7713 for (unsigned int i = 0; i < n_new_quads; ++i)
7714 {
7715 new_quads[i] =
7716 triangulation.faces->quads
7717 .template next_free_single_object<2>(triangulation);
7718
7719 AssertIsNotUsed(new_quads[i]);
7720 new_quads[i]->set_used_flag();
7721 new_quads[i]->clear_user_flag();
7722 new_quads[i]->clear_user_data();
7723 new_quads[i]->clear_children();
7724 // interior quad
7725 new_quads[i]->set_boundary_id_internal(
7727 // they inherit geometry description of the hex they
7728 // belong to
7729 new_quads[i]->set_manifold_id(hex->manifold_id());
7730 // set all line orientation flags to true by
7731 // default, change this afterwards, if necessary
7732 for (unsigned int j = 0;
7733 j < GeometryInfo<dim>::lines_per_face;
7734 ++j)
7735 new_quads[i]->set_line_orientation(j, true);
7736 }
7737
7738 types::subdomain_id subdomainid = hex->subdomain_id();
7739
7740 // find some space for the newly to be created hexes
7741 // and initialize them.
7742 std::vector<
7744 new_hexes(n_new_hexes);
7745 for (unsigned int i = 0; i < n_new_hexes; ++i)
7746 {
7747 if (i % 2 == 0)
7748 next_unused_hex =
7749 triangulation.levels[level + 1]->cells.next_free_hex(
7750 triangulation, level + 1);
7751 else
7752 ++next_unused_hex;
7753
7754 new_hexes[i] = next_unused_hex;
7755
7756 AssertIsNotUsed(new_hexes[i]);
7757 new_hexes[i]->set_used_flag();
7758 new_hexes[i]->clear_user_flag();
7759 new_hexes[i]->clear_user_data();
7760 new_hexes[i]->clear_children();
7761 // inherit material
7762 // properties
7763 new_hexes[i]->set_material_id(hex->material_id());
7764 new_hexes[i]->set_manifold_id(hex->manifold_id());
7765 new_hexes[i]->set_subdomain_id(subdomainid);
7766
7767 if (i % 2)
7768 new_hexes[i]->set_parent(hex->index());
7769 // set the face_orientation flag to true for all
7770 // faces initially, as this is the default value
7771 // which is true for all faces interior to the
7772 // hex. later on go the other way round and
7773 // reset faces that are at the boundary of the
7774 // mother cube
7775 //
7776 // the same is true for the face_flip and
7777 // face_rotation flags. however, the latter two
7778 // are set to false by default as this is the
7779 // standard value
7780 for (const unsigned int f :
7782 {
7783 new_hexes[i]->set_face_orientation(f, true);
7784 new_hexes[i]->set_face_flip(f, false);
7785 new_hexes[i]->set_face_rotation(f, false);
7786 }
7787 }
7788 // note these hexes as children to the present cell
7789 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
7790 hex->set_children(2 * i, new_hexes[2 * i]->index());
7791
7792 // we have to take into account whether the
7793 // different faces are oriented correctly or in the
7794 // opposite direction, so store that up front
7795
7796 // face_orientation
7797 const bool f_or[6] = {hex->face_orientation(0),
7798 hex->face_orientation(1),
7799 hex->face_orientation(2),
7800 hex->face_orientation(3),
7801 hex->face_orientation(4),
7802 hex->face_orientation(5)};
7803
7804 // face_flip
7805 const bool f_fl[6] = {hex->face_flip(0),
7806 hex->face_flip(1),
7807 hex->face_flip(2),
7808 hex->face_flip(3),
7809 hex->face_flip(4),
7810 hex->face_flip(5)};
7811
7812 // face_rotation
7813 const bool f_ro[6] = {hex->face_rotation(0),
7814 hex->face_rotation(1),
7815 hex->face_rotation(2),
7816 hex->face_rotation(3),
7817 hex->face_rotation(4),
7818 hex->face_rotation(5)};
7819
7820 // little helper table, indicating, whether the
7821 // child with index 0 or with index 1 can be found
7822 // at the standard origin of an anisotropically
7823 // refined quads in real orientation index 1:
7824 // (RefineCase - 1) index 2: face_flip
7825
7826 // index 3: face rotation
7827 // note: face orientation has no influence
7828 const unsigned int child_at_origin[2][2][2] = {
7829 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
7830 // face_rotation=false and true
7831 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
7832 // face_rotation=false and true
7833 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
7834 // face_rotation=false and true
7835 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
7836 // face_rotation=false and true
7837
7838 //-------------------------------------
7839 //
7840 // in the following we will do the same thing for
7841 // each refinement case: create a new vertex (if
7842 // needed), create new interior lines (if needed),
7843 // create new interior quads and afterwards build
7844 // the children hexes out of these and the existing
7845 // subfaces of the outer quads (which have been
7846 // created above). However, even if the steps are
7847 // quite similar, the actual work strongly depends
7848 // on the actual refinement case. therefore, we use
7849 // separate blocks of code for each of these cases,
7850 // which hopefully increases the readability to some
7851 // extend.
7852
7853 switch (ref_case)
7854 {
7856 {
7857 //----------------------------
7858 //
7859 // RefinementCase<dim>::cut_x
7860 //
7861 // the refined cube will look
7862 // like this:
7863 //
7864 // *----*----*
7865 // / / /|
7866 // / / / |
7867 // / / / |
7868 // *----*----* |
7869 // | | | |
7870 // | | | *
7871 // | | | /
7872 // | | | /
7873 // | | |/
7874 // *----*----*
7875 //
7876 // again, first collect some data about the
7877 // indices of the lines, with the following
7878 // numbering:
7879
7880 // face 2: front plane
7881 // (note: x,y exchanged)
7882 // *---*---*
7883 // | | |
7884 // | 0 |
7885 // | | |
7886 // *---*---*
7887 // m0
7888 // face 3: back plane
7889 // (note: x,y exchanged)
7890 // m1
7891 // *---*---*
7892 // | | |
7893 // | 1 |
7894 // | | |
7895 // *---*---*
7896 // face 4: bottom plane
7897 // *---*---*
7898 // / / /
7899 // / 2 /
7900 // / / /
7901 // *---*---*
7902 // m0
7903 // face 5: top plane
7904 // m1
7905 // *---*---*
7906 // / / /
7907 // / 3 /
7908 // / / /
7909 // *---*---*
7910
7911 // set up a list of line iterators first. from
7912 // this, construct lists of line_indices and
7913 // line orientations later on
7914 const typename Triangulation<dim, spacedim>::
7915 raw_line_iterator lines[4] = {
7916 hex->face(2)->child(0)->line(
7917 (hex->face(2)->refinement_case() ==
7919 1 :
7920 3), // 0
7921 hex->face(3)->child(0)->line(
7922 (hex->face(3)->refinement_case() ==
7924 1 :
7925 3), // 1
7926 hex->face(4)->child(0)->line(
7927 (hex->face(4)->refinement_case() ==
7929 1 :
7930 3), // 2
7931 hex->face(5)->child(0)->line(
7932 (hex->face(5)->refinement_case() ==
7934 1 :
7935 3) // 3
7936 };
7937
7938 unsigned int line_indices[4];
7939 for (unsigned int i = 0; i < 4; ++i)
7940 line_indices[i] = lines[i]->index();
7941
7942 // the orientation of lines for the inner quads
7943 // is quite tricky. as these lines are newly
7944 // created ones and thus have no parents, they
7945 // cannot inherit this property. set up an array
7946 // and fill it with the respective values
7947 bool line_orientation[4];
7948
7949 // the middle vertex marked as m0 above is the
7950 // start vertex for lines 0 and 2 in standard
7951 // orientation, whereas m1 is the end vertex of
7952 // lines 1 and 3 in standard orientation
7953 const unsigned int middle_vertices[2] = {
7954 hex->line(2)->child(0)->vertex_index(1),
7955 hex->line(7)->child(0)->vertex_index(1)};
7956
7957 for (unsigned int i = 0; i < 4; ++i)
7958 if (lines[i]->vertex_index(i % 2) ==
7959 middle_vertices[i % 2])
7960 line_orientation[i] = true;
7961 else
7962 {
7963 // it must be the other
7964 // way round then
7965 Assert(lines[i]->vertex_index((i + 1) % 2) ==
7966 middle_vertices[i % 2],
7968 line_orientation[i] = false;
7969 }
7970
7971 // set up the new quad, line numbering is as
7972 // indicated above
7973 new_quads[0]->set_bounding_object_indices(
7974 {line_indices[0],
7975 line_indices[1],
7976 line_indices[2],
7977 line_indices[3]});
7978
7979 new_quads[0]->set_line_orientation(
7980 0, line_orientation[0]);
7981 new_quads[0]->set_line_orientation(
7982 1, line_orientation[1]);
7983 new_quads[0]->set_line_orientation(
7984 2, line_orientation[2]);
7985 new_quads[0]->set_line_orientation(
7986 3, line_orientation[3]);
7987
7988 // the quads are numbered as follows:
7989 //
7990 // planes in the interior of the old hex:
7991 //
7992 // *
7993 // /|
7994 // / | x
7995 // / | *-------* *---------*
7996 // * | | | / /
7997 // | 0 | | | / /
7998 // | * | | / /
7999 // | / *-------*y *---------*x
8000 // | /
8001 // |/
8002 // *
8003 //
8004 // children of the faces of the old hex
8005 //
8006 // *---*---* *---*---*
8007 // /| | | / / /|
8008 // / | | | / 9 / 10/ |
8009 // / | 5 | 6 | / / / |
8010 // * | | | *---*---* |
8011 // | 1 *---*---* | | | 2 *
8012 // | / / / | | | /
8013 // | / 7 / 8 / | 3 | 4 | /
8014 // |/ / / | | |/
8015 // *---*---* *---*---*
8016 //
8017 // note that we have to take care of the
8018 // orientation of faces.
8019 const int quad_indices[11] = {
8020 new_quads[0]->index(), // 0
8021
8022 hex->face(0)->index(), // 1
8023
8024 hex->face(1)->index(), // 2
8025
8026 hex->face(2)->child_index(
8027 child_at_origin[hex->face(2)->refinement_case() -
8028 1][f_fl[2]][f_ro[2]]), // 3
8029 hex->face(2)->child_index(
8030 1 -
8031 child_at_origin[hex->face(2)->refinement_case() -
8032 1][f_fl[2]][f_ro[2]]),
8033
8034 hex->face(3)->child_index(
8035 child_at_origin[hex->face(3)->refinement_case() -
8036 1][f_fl[3]][f_ro[3]]), // 5
8037 hex->face(3)->child_index(
8038 1 -
8039 child_at_origin[hex->face(3)->refinement_case() -
8040 1][f_fl[3]][f_ro[3]]),
8041
8042 hex->face(4)->child_index(
8043 child_at_origin[hex->face(4)->refinement_case() -
8044 1][f_fl[4]][f_ro[4]]), // 7
8045 hex->face(4)->child_index(
8046 1 -
8047 child_at_origin[hex->face(4)->refinement_case() -
8048 1][f_fl[4]][f_ro[4]]),
8049
8050 hex->face(5)->child_index(
8051 child_at_origin[hex->face(5)->refinement_case() -
8052 1][f_fl[5]][f_ro[5]]), // 9
8053 hex->face(5)->child_index(
8054 1 -
8055 child_at_origin[hex->face(5)->refinement_case() -
8056 1][f_fl[5]][f_ro[5]])
8057
8058 };
8059
8060 new_hexes[0]->set_bounding_object_indices(
8061 {quad_indices[1],
8062 quad_indices[0],
8063 quad_indices[3],
8064 quad_indices[5],
8065 quad_indices[7],
8066 quad_indices[9]});
8067 new_hexes[1]->set_bounding_object_indices(
8068 {quad_indices[0],
8069 quad_indices[2],
8070 quad_indices[4],
8071 quad_indices[6],
8072 quad_indices[8],
8073 quad_indices[10]});
8074 break;
8075 }
8076
8078 {
8079 //----------------------------
8080 //
8081 // RefinementCase<dim>::cut_y
8082 //
8083 // the refined cube will look like this:
8084 //
8085 // *---------*
8086 // / /|
8087 // *---------* |
8088 // / /| |
8089 // *---------* | |
8090 // | | | |
8091 // | | | *
8092 // | | |/
8093 // | | *
8094 // | |/
8095 // *---------*
8096 //
8097 // again, first collect some data about the
8098 // indices of the lines, with the following
8099 // numbering:
8100
8101 // face 0: left plane
8102 // *
8103 // /|
8104 // * |
8105 // /| |
8106 // * | |
8107 // | 0 |
8108 // | | *
8109 // | |/
8110 // | *m0
8111 // |/
8112 // *
8113 // face 1: right plane
8114 // *
8115 // /|
8116 // m1* |
8117 // /| |
8118 // * | |
8119 // | 1 |
8120 // | | *
8121 // | |/
8122 // | *
8123 // |/
8124 // *
8125 // face 4: bottom plane
8126 // *-------*
8127 // / /
8128 // m0*---2---*
8129 // / /
8130 // *-------*
8131 // face 5: top plane
8132 // *-------*
8133 // / /
8134 // *---3---*m1
8135 // / /
8136 // *-------*
8137
8138 // set up a list of line iterators first. from
8139 // this, construct lists of line_indices and
8140 // line orientations later on
8141 const typename Triangulation<dim, spacedim>::
8142 raw_line_iterator lines[4] = {
8143 hex->face(0)->child(0)->line(
8144 (hex->face(0)->refinement_case() ==
8146 1 :
8147 3), // 0
8148 hex->face(1)->child(0)->line(
8149 (hex->face(1)->refinement_case() ==
8151 1 :
8152 3), // 1
8153 hex->face(4)->child(0)->line(
8154 (hex->face(4)->refinement_case() ==
8156 1 :
8157 3), // 2
8158 hex->face(5)->child(0)->line(
8159 (hex->face(5)->refinement_case() ==
8161 1 :
8162 3) // 3
8163 };
8164
8165 unsigned int line_indices[4];
8166 for (unsigned int i = 0; i < 4; ++i)
8167 line_indices[i] = lines[i]->index();
8168
8169 // the orientation of lines for the inner quads
8170 // is quite tricky. as these lines are newly
8171 // created ones and thus have no parents, they
8172 // cannot inherit this property. set up an array
8173 // and fill it with the respective values
8174 bool line_orientation[4];
8175
8176 // the middle vertex marked as m0 above is the
8177 // start vertex for lines 0 and 2 in standard
8178 // orientation, whereas m1 is the end vertex of
8179 // lines 1 and 3 in standard orientation
8180 const unsigned int middle_vertices[2] = {
8181 hex->line(0)->child(0)->vertex_index(1),
8182 hex->line(5)->child(0)->vertex_index(1)};
8183
8184 for (unsigned int i = 0; i < 4; ++i)
8185 if (lines[i]->vertex_index(i % 2) ==
8186 middle_vertices[i % 2])
8187 line_orientation[i] = true;
8188 else
8189 {
8190 // it must be the other way round then
8191 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8192 middle_vertices[i % 2],
8194 line_orientation[i] = false;
8195 }
8196
8197 // set up the new quad, line numbering is as
8198 // indicated above
8199 new_quads[0]->set_bounding_object_indices(
8200 {line_indices[2],
8201 line_indices[3],
8202 line_indices[0],
8203 line_indices[1]});
8204
8205 new_quads[0]->set_line_orientation(
8206 0, line_orientation[2]);
8207 new_quads[0]->set_line_orientation(
8208 1, line_orientation[3]);
8209 new_quads[0]->set_line_orientation(
8210 2, line_orientation[0]);
8211 new_quads[0]->set_line_orientation(
8212 3, line_orientation[1]);
8213
8214 // the quads are numbered as follows:
8215 //
8216 // planes in the interior of the old hex:
8217 //
8218 // *
8219 // /|
8220 // / | x
8221 // / | *-------* *---------*
8222 // * | | | / /
8223 // | | | 0 | / /
8224 // | * | | / /
8225 // | / *-------*y *---------*x
8226 // | /
8227 // |/
8228 // *
8229 //
8230 // children of the faces of the old hex
8231 //
8232 // *-------* *-------*
8233 // /| | / 10 /|
8234 // * | | *-------* |
8235 // /| | 6 | / 9 /| |
8236 // * |2| | *-------* |4|
8237 // | | *-------* | | | *
8238 // |1|/ 8 / | |3|/
8239 // | *-------* | 5 | *
8240 // |/ 7 / | |/
8241 // *-------* *-------*
8242 //
8243 // note that we have to take care of the
8244 // orientation of faces.
8245 const int quad_indices[11] = {
8246 new_quads[0]->index(), // 0
8247
8248 hex->face(0)->child_index(
8249 child_at_origin[hex->face(0)->refinement_case() -
8250 1][f_fl[0]][f_ro[0]]), // 1
8251 hex->face(0)->child_index(
8252 1 -
8253 child_at_origin[hex->face(0)->refinement_case() -
8254 1][f_fl[0]][f_ro[0]]),
8255
8256 hex->face(1)->child_index(
8257 child_at_origin[hex->face(1)->refinement_case() -
8258 1][f_fl[1]][f_ro[1]]), // 3
8259 hex->face(1)->child_index(
8260 1 -
8261 child_at_origin[hex->face(1)->refinement_case() -
8262 1][f_fl[1]][f_ro[1]]),
8263
8264 hex->face(2)->index(), // 5
8265
8266 hex->face(3)->index(), // 6
8267
8268 hex->face(4)->child_index(
8269 child_at_origin[hex->face(4)->refinement_case() -
8270 1][f_fl[4]][f_ro[4]]), // 7
8271 hex->face(4)->child_index(
8272 1 -
8273 child_at_origin[hex->face(4)->refinement_case() -
8274 1][f_fl[4]][f_ro[4]]),
8275
8276 hex->face(5)->child_index(
8277 child_at_origin[hex->face(5)->refinement_case() -
8278 1][f_fl[5]][f_ro[5]]), // 9
8279 hex->face(5)->child_index(
8280 1 -
8281 child_at_origin[hex->face(5)->refinement_case() -
8282 1][f_fl[5]][f_ro[5]])
8283
8284 };
8285
8286 new_hexes[0]->set_bounding_object_indices(
8287 {quad_indices[1],
8288 quad_indices[3],
8289 quad_indices[5],
8290 quad_indices[0],
8291 quad_indices[7],
8292 quad_indices[9]});
8293 new_hexes[1]->set_bounding_object_indices(
8294 {quad_indices[2],
8295 quad_indices[4],
8296 quad_indices[0],
8297 quad_indices[6],
8298 quad_indices[8],
8299 quad_indices[10]});
8300 break;
8301 }
8302
8304 {
8305 //----------------------------
8306 //
8307 // RefinementCase<dim>::cut_z
8308 //
8309 // the refined cube will look like this:
8310 //
8311 // *---------*
8312 // / /|
8313 // / / |
8314 // / / *
8315 // *---------* /|
8316 // | | / |
8317 // | |/ *
8318 // *---------* /
8319 // | | /
8320 // | |/
8321 // *---------*
8322 //
8323 // again, first collect some data about the
8324 // indices of the lines, with the following
8325 // numbering:
8326
8327 // face 0: left plane
8328 // *
8329 // /|
8330 // / |
8331 // / *
8332 // * /|
8333 // | 0 |
8334 // |/ *
8335 // m0* /
8336 // | /
8337 // |/
8338 // *
8339 // face 1: right plane
8340 // *
8341 // /|
8342 // / |
8343 // / *m1
8344 // * /|
8345 // | 1 |
8346 // |/ *
8347 // * /
8348 // | /
8349 // |/
8350 // *
8351 // face 2: front plane
8352 // (note: x,y exchanged)
8353 // *-------*
8354 // | |
8355 // m0*---2---*
8356 // | |
8357 // *-------*
8358 // face 3: back plane
8359 // (note: x,y exchanged)
8360 // *-------*
8361 // | |
8362 // *---3---*m1
8363 // | |
8364 // *-------*
8365
8366 // set up a list of line iterators first. from
8367 // this, construct lists of line_indices and
8368 // line orientations later on
8369 const typename Triangulation<dim, spacedim>::
8370 raw_line_iterator lines[4] = {
8371 hex->face(0)->child(0)->line(
8372 (hex->face(0)->refinement_case() ==
8374 1 :
8375 3), // 0
8376 hex->face(1)->child(0)->line(
8377 (hex->face(1)->refinement_case() ==
8379 1 :
8380 3), // 1
8381 hex->face(2)->child(0)->line(
8382 (hex->face(2)->refinement_case() ==
8384 1 :
8385 3), // 2
8386 hex->face(3)->child(0)->line(
8387 (hex->face(3)->refinement_case() ==
8389 1 :
8390 3) // 3
8391 };
8392
8393 unsigned int line_indices[4];
8394 for (unsigned int i = 0; i < 4; ++i)
8395 line_indices[i] = lines[i]->index();
8396
8397 // the orientation of lines for the inner quads
8398 // is quite tricky. as these lines are newly
8399 // created ones and thus have no parents, they
8400 // cannot inherit this property. set up an array
8401 // and fill it with the respective values
8402 bool line_orientation[4];
8403
8404 // the middle vertex marked as m0 above is the
8405 // start vertex for lines 0 and 2 in standard
8406 // orientation, whereas m1 is the end vertex of
8407 // lines 1 and 3 in standard orientation
8408 const unsigned int middle_vertices[2] = {
8409 middle_vertex_index<dim, spacedim>(hex->line(8)),
8410 middle_vertex_index<dim, spacedim>(hex->line(11))};
8411
8412 for (unsigned int i = 0; i < 4; ++i)
8413 if (lines[i]->vertex_index(i % 2) ==
8414 middle_vertices[i % 2])
8415 line_orientation[i] = true;
8416 else
8417 {
8418 // it must be the other way round then
8419 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8420 middle_vertices[i % 2],
8422 line_orientation[i] = false;
8423 }
8424
8425 // set up the new quad, line numbering is as
8426 // indicated above
8427 new_quads[0]->set_bounding_object_indices(
8428 {line_indices[0],
8429 line_indices[1],
8430 line_indices[2],
8431 line_indices[3]});
8432
8433 new_quads[0]->set_line_orientation(
8434 0, line_orientation[0]);
8435 new_quads[0]->set_line_orientation(
8436 1, line_orientation[1]);
8437 new_quads[0]->set_line_orientation(
8438 2, line_orientation[2]);
8439 new_quads[0]->set_line_orientation(
8440 3, line_orientation[3]);
8441
8442 // the quads are numbered as follows:
8443 //
8444 // planes in the interior of the old hex:
8445 //
8446 // *
8447 // /|
8448 // / | x
8449 // / | *-------* *---------*
8450 // * | | | / /
8451 // | | | | / 0 /
8452 // | * | | / /
8453 // | / *-------*y *---------*x
8454 // | /
8455 // |/
8456 // *
8457 //
8458 // children of the faces of the old hex
8459 //
8460 // *---*---* *-------*
8461 // /| 8 | / /|
8462 // / | | / 10 / |
8463 // / *-------* / / *
8464 // * 2/| | *-------* 4/|
8465 // | / | 7 | | 6 | / |
8466 // |/1 *-------* | |/3 *
8467 // * / / *-------* /
8468 // | / 9 / | | /
8469 // |/ / | 5 |/
8470 // *-------* *---*---*
8471 //
8472 // note that we have to take care of the
8473 // orientation of faces.
8474 const int quad_indices[11] = {
8475 new_quads[0]->index(), // 0
8476
8477 hex->face(0)->child_index(
8478 child_at_origin[hex->face(0)->refinement_case() -
8479 1][f_fl[0]][f_ro[0]]), // 1
8480 hex->face(0)->child_index(
8481 1 -
8482 child_at_origin[hex->face(0)->refinement_case() -
8483 1][f_fl[0]][f_ro[0]]),
8484
8485 hex->face(1)->child_index(
8486 child_at_origin[hex->face(1)->refinement_case() -
8487 1][f_fl[1]][f_ro[1]]), // 3
8488 hex->face(1)->child_index(
8489 1 -
8490 child_at_origin[hex->face(1)->refinement_case() -
8491 1][f_fl[1]][f_ro[1]]),
8492
8493 hex->face(2)->child_index(
8494 child_at_origin[hex->face(2)->refinement_case() -
8495 1][f_fl[2]][f_ro[2]]), // 5
8496 hex->face(2)->child_index(
8497 1 -
8498 child_at_origin[hex->face(2)->refinement_case() -
8499 1][f_fl[2]][f_ro[2]]),
8500
8501 hex->face(3)->child_index(
8502 child_at_origin[hex->face(3)->refinement_case() -
8503 1][f_fl[3]][f_ro[3]]), // 7
8504 hex->face(3)->child_index(
8505 1 -
8506 child_at_origin[hex->face(3)->refinement_case() -
8507 1][f_fl[3]][f_ro[3]]),
8508
8509 hex->face(4)->index(), // 9
8510
8511 hex->face(5)->index() // 10
8512 };
8513
8514 new_hexes[0]->set_bounding_object_indices(
8515 {quad_indices[1],
8516 quad_indices[3],
8517 quad_indices[5],
8518 quad_indices[7],
8519 quad_indices[9],
8520 quad_indices[0]});
8521 new_hexes[1]->set_bounding_object_indices(
8522 {quad_indices[2],
8523 quad_indices[4],
8524 quad_indices[6],
8525 quad_indices[8],
8526 quad_indices[0],
8527 quad_indices[10]});
8528 break;
8529 }
8530
8532 {
8533 //----------------------------
8534 //
8535 // RefinementCase<dim>::cut_xy
8536 //
8537 // the refined cube will look like this:
8538 //
8539 // *----*----*
8540 // / / /|
8541 // *----*----* |
8542 // / / /| |
8543 // *----*----* | |
8544 // | | | | |
8545 // | | | | *
8546 // | | | |/
8547 // | | | *
8548 // | | |/
8549 // *----*----*
8550 //
8551
8552 // first, create the new internal line
8553 new_lines[0]->set_bounding_object_indices(
8554 {middle_vertex_index<dim, spacedim>(hex->face(4)),
8555 middle_vertex_index<dim, spacedim>(hex->face(5))});
8556
8557 // again, first collect some data about the
8558 // indices of the lines, with the following
8559 // numbering:
8560
8561 // face 0: left plane
8562 // *
8563 // /|
8564 // * |
8565 // /| |
8566 // * | |
8567 // | 0 |
8568 // | | *
8569 // | |/
8570 // | *
8571 // |/
8572 // *
8573 // face 1: right plane
8574 // *
8575 // /|
8576 // * |
8577 // /| |
8578 // * | |
8579 // | 1 |
8580 // | | *
8581 // | |/
8582 // | *
8583 // |/
8584 // *
8585 // face 2: front plane
8586 // (note: x,y exchanged)
8587 // *---*---*
8588 // | | |
8589 // | 2 |
8590 // | | |
8591 // *-------*
8592 // face 3: back plane
8593 // (note: x,y exchanged)
8594 // *---*---*
8595 // | | |
8596 // | 3 |
8597 // | | |
8598 // *---*---*
8599 // face 4: bottom plane
8600 // *---*---*
8601 // / 5 /
8602 // *-6-*-7-*
8603 // / 4 /
8604 // *---*---*
8605 // face 5: top plane
8606 // *---*---*
8607 // / 9 /
8608 // *10-*-11*
8609 // / 8 /
8610 // *---*---*
8611 // middle planes
8612 // *-------* *---*---*
8613 // / / | | |
8614 // / / | 12 |
8615 // / / | | |
8616 // *-------* *---*---*
8617
8618 // set up a list of line iterators first. from
8619 // this, construct lists of line_indices and
8620 // line orientations later on
8621 const typename Triangulation<
8622 dim,
8623 spacedim>::raw_line_iterator lines[13] = {
8624 hex->face(0)->child(0)->line(
8625 (hex->face(0)->refinement_case() ==
8627 1 :
8628 3), // 0
8629 hex->face(1)->child(0)->line(
8630 (hex->face(1)->refinement_case() ==
8632 1 :
8633 3), // 1
8634 hex->face(2)->child(0)->line(
8635 (hex->face(2)->refinement_case() ==
8637 1 :
8638 3), // 2
8639 hex->face(3)->child(0)->line(
8640 (hex->face(3)->refinement_case() ==
8642 1 :
8643 3), // 3
8644
8645 hex->face(4)
8646 ->isotropic_child(
8648 0, f_or[4], f_fl[4], f_ro[4]))
8649 ->line(
8651 1, f_or[4], f_fl[4], f_ro[4])), // 4
8652 hex->face(4)
8653 ->isotropic_child(
8655 3, f_or[4], f_fl[4], f_ro[4]))
8656 ->line(
8658 0, f_or[4], f_fl[4], f_ro[4])), // 5
8659 hex->face(4)
8660 ->isotropic_child(
8662 0, f_or[4], f_fl[4], f_ro[4]))
8663 ->line(
8665 3, f_or[4], f_fl[4], f_ro[4])), // 6
8666 hex->face(4)
8667 ->isotropic_child(
8669 3, f_or[4], f_fl[4], f_ro[4]))
8670 ->line(
8672 2, f_or[4], f_fl[4], f_ro[4])), // 7
8673
8674 hex->face(5)
8675 ->isotropic_child(
8677 0, f_or[5], f_fl[5], f_ro[5]))
8678 ->line(
8680 1, f_or[5], f_fl[5], f_ro[5])), // 8
8681 hex->face(5)
8682 ->isotropic_child(
8684 3, f_or[5], f_fl[5], f_ro[5]))
8685 ->line(
8687 0, f_or[5], f_fl[5], f_ro[5])), // 9
8688 hex->face(5)
8689 ->isotropic_child(
8691 0, f_or[5], f_fl[5], f_ro[5]))
8692 ->line(
8694 3, f_or[5], f_fl[5], f_ro[5])), // 10
8695 hex->face(5)
8696 ->isotropic_child(
8698 3, f_or[5], f_fl[5], f_ro[5]))
8699 ->line(
8701 2, f_or[5], f_fl[5], f_ro[5])), // 11
8702
8703 new_lines[0] // 12
8704 };
8705
8706 unsigned int line_indices[13];
8707 for (unsigned int i = 0; i < 13; ++i)
8708 line_indices[i] = lines[i]->index();
8709
8710 // the orientation of lines for the inner quads
8711 // is quite tricky. as these lines are newly
8712 // created ones and thus have no parents, they
8713 // cannot inherit this property. set up an array
8714 // and fill it with the respective values
8715 bool line_orientation[13];
8716
8717 // the middle vertices of the lines of our
8718 // bottom face
8719 const unsigned int middle_vertices[4] = {
8720 hex->line(0)->child(0)->vertex_index(1),
8721 hex->line(1)->child(0)->vertex_index(1),
8722 hex->line(2)->child(0)->vertex_index(1),
8723 hex->line(3)->child(0)->vertex_index(1),
8724 };
8725
8726 // note: for lines 0 to 3 the orientation of the
8727 // line is 'true', if vertex 0 is on the bottom
8728 // face
8729 for (unsigned int i = 0; i < 4; ++i)
8730 if (lines[i]->vertex_index(0) == middle_vertices[i])
8731 line_orientation[i] = true;
8732 else
8733 {
8734 // it must be the other way round then
8735 Assert(lines[i]->vertex_index(1) ==
8736 middle_vertices[i],
8738 line_orientation[i] = false;
8739 }
8740
8741 // note: for lines 4 to 11 (inner lines of the
8742 // outer quads) the following holds: the second
8743 // vertex of the even lines in standard
8744 // orientation is the vertex in the middle of
8745 // the quad, whereas for odd lines the first
8746 // vertex is the same middle vertex.
8747 for (unsigned int i = 4; i < 12; ++i)
8748 if (lines[i]->vertex_index((i + 1) % 2) ==
8749 middle_vertex_index<dim, spacedim>(
8750 hex->face(3 + i / 4)))
8751 line_orientation[i] = true;
8752 else
8753 {
8754 // it must be the other way
8755 // round then
8756 Assert(lines[i]->vertex_index(i % 2) ==
8757 (middle_vertex_index<dim, spacedim>(
8758 hex->face(3 + i / 4))),
8760 line_orientation[i] = false;
8761 }
8762 // for the last line the line orientation is
8763 // always true, since it was just constructed
8764 // that way
8765 line_orientation[12] = true;
8766
8767 // set up the 4 quads, numbered as follows (left
8768 // quad numbering, right line numbering
8769 // extracted from above)
8770 //
8771 // * *
8772 // /| 9|
8773 // * | * |
8774 // y/| | 8| 3
8775 // * |1| * | |
8776 // | | |x | 12|
8777 // |0| * | | *
8778 // | |/ 2 |5
8779 // | * | *
8780 // |/ |4
8781 // * *
8782 //
8783 // x
8784 // *---*---* *10-*-11*
8785 // | | | | | |
8786 // | 2 | 3 | 0 12 1
8787 // | | | | | |
8788 // *---*---*y *-6-*-7-*
8789
8790 new_quads[0]->set_bounding_object_indices(
8791 {line_indices[2],
8792 line_indices[12],
8793 line_indices[4],
8794 line_indices[8]});
8795 new_quads[1]->set_bounding_object_indices(
8796 {line_indices[12],
8797 line_indices[3],
8798 line_indices[5],
8799 line_indices[9]});
8800 new_quads[2]->set_bounding_object_indices(
8801 {line_indices[6],
8802 line_indices[10],
8803 line_indices[0],
8804 line_indices[12]});
8805 new_quads[3]->set_bounding_object_indices(
8806 {line_indices[7],
8807 line_indices[11],
8808 line_indices[12],
8809 line_indices[1]});
8810
8811 new_quads[0]->set_line_orientation(
8812 0, line_orientation[2]);
8813 new_quads[0]->set_line_orientation(
8814 2, line_orientation[4]);
8815 new_quads[0]->set_line_orientation(
8816 3, line_orientation[8]);
8817
8818 new_quads[1]->set_line_orientation(
8819 1, line_orientation[3]);
8820 new_quads[1]->set_line_orientation(
8821 2, line_orientation[5]);
8822 new_quads[1]->set_line_orientation(
8823 3, line_orientation[9]);
8824
8825 new_quads[2]->set_line_orientation(
8826 0, line_orientation[6]);
8827 new_quads[2]->set_line_orientation(
8828 1, line_orientation[10]);
8829 new_quads[2]->set_line_orientation(
8830 2, line_orientation[0]);
8831
8832 new_quads[3]->set_line_orientation(
8833 0, line_orientation[7]);
8834 new_quads[3]->set_line_orientation(
8835 1, line_orientation[11]);
8836 new_quads[3]->set_line_orientation(
8837 3, line_orientation[1]);
8838
8839 // the quads are numbered as follows:
8840 //
8841 // planes in the interior of the old hex:
8842 //
8843 // *
8844 // /|
8845 // * | x
8846 // /| | *---*---* *---------*
8847 // * |1| | | | / /
8848 // | | | | 2 | 3 | / /
8849 // |0| * | | | / /
8850 // | |/ *---*---*y *---------*x
8851 // | *
8852 // |/
8853 // *
8854 //
8855 // children of the faces of the old hex
8856 //
8857 // *---*---* *---*---*
8858 // /| | | /18 / 19/|
8859 // * |10 | 11| /---/---* |
8860 // /| | | | /16 / 17/| |
8861 // * |5| | | *---*---* |7|
8862 // | | *---*---* | | | | *
8863 // |4|/14 / 15/ | | |6|/
8864 // | *---/---/ | 8 | 9 | *
8865 // |/12 / 13/ | | |/
8866 // *---*---* *---*---*
8867 //
8868 // note that we have to take care of the
8869 // orientation of faces.
8870 const int quad_indices[20] = {
8871 new_quads[0]->index(), // 0
8872 new_quads[1]->index(),
8873 new_quads[2]->index(),
8874 new_quads[3]->index(),
8875
8876 hex->face(0)->child_index(
8877 child_at_origin[hex->face(0)->refinement_case() -
8878 1][f_fl[0]][f_ro[0]]), // 4
8879 hex->face(0)->child_index(
8880 1 -
8881 child_at_origin[hex->face(0)->refinement_case() -
8882 1][f_fl[0]][f_ro[0]]),
8883
8884 hex->face(1)->child_index(
8885 child_at_origin[hex->face(1)->refinement_case() -
8886 1][f_fl[1]][f_ro[1]]), // 6
8887 hex->face(1)->child_index(
8888 1 -
8889 child_at_origin[hex->face(1)->refinement_case() -
8890 1][f_fl[1]][f_ro[1]]),
8891
8892 hex->face(2)->child_index(
8893 child_at_origin[hex->face(2)->refinement_case() -
8894 1][f_fl[2]][f_ro[2]]), // 8
8895 hex->face(2)->child_index(
8896 1 -
8897 child_at_origin[hex->face(2)->refinement_case() -
8898 1][f_fl[2]][f_ro[2]]),
8899
8900 hex->face(3)->child_index(
8901 child_at_origin[hex->face(3)->refinement_case() -
8902 1][f_fl[3]][f_ro[3]]), // 10
8903 hex->face(3)->child_index(
8904 1 -
8905 child_at_origin[hex->face(3)->refinement_case() -
8906 1][f_fl[3]][f_ro[3]]),
8907
8908 hex->face(4)->isotropic_child_index(
8910 0, f_or[4], f_fl[4], f_ro[4])), // 12
8911 hex->face(4)->isotropic_child_index(
8913 1, f_or[4], f_fl[4], f_ro[4])),
8914 hex->face(4)->isotropic_child_index(
8916 2, f_or[4], f_fl[4], f_ro[4])),
8917 hex->face(4)->isotropic_child_index(
8919 3, f_or[4], f_fl[4], f_ro[4])),
8920
8921 hex->face(5)->isotropic_child_index(
8923 0, f_or[5], f_fl[5], f_ro[5])), // 16
8924 hex->face(5)->isotropic_child_index(
8926 1, f_or[5], f_fl[5], f_ro[5])),
8927 hex->face(5)->isotropic_child_index(
8929 2, f_or[5], f_fl[5], f_ro[5])),
8930 hex->face(5)->isotropic_child_index(
8932 3, f_or[5], f_fl[5], f_ro[5]))};
8933
8934 new_hexes[0]->set_bounding_object_indices(
8935 {quad_indices[4],
8936 quad_indices[0],
8937 quad_indices[8],
8938 quad_indices[2],
8939 quad_indices[12],
8940 quad_indices[16]});
8941 new_hexes[1]->set_bounding_object_indices(
8942 {quad_indices[0],
8943 quad_indices[6],
8944 quad_indices[9],
8945 quad_indices[3],
8946 quad_indices[13],
8947 quad_indices[17]});
8948 new_hexes[2]->set_bounding_object_indices(
8949 {quad_indices[5],
8950 quad_indices[1],
8951 quad_indices[2],
8952 quad_indices[10],
8953 quad_indices[14],
8954 quad_indices[18]});
8955 new_hexes[3]->set_bounding_object_indices(
8956 {quad_indices[1],
8957 quad_indices[7],
8958 quad_indices[3],
8959 quad_indices[11],
8960 quad_indices[15],
8961 quad_indices[19]});
8962 break;
8963 }
8964
8966 {
8967 //----------------------------
8968 //
8969 // RefinementCase<dim>::cut_xz
8970 //
8971 // the refined cube will look like this:
8972 //
8973 // *----*----*
8974 // / / /|
8975 // / / / |
8976 // / / / *
8977 // *----*----* /|
8978 // | | | / |
8979 // | | |/ *
8980 // *----*----* /
8981 // | | | /
8982 // | | |/
8983 // *----*----*
8984 //
8985
8986 // first, create the new internal line
8987 new_lines[0]->set_bounding_object_indices(
8988 {middle_vertex_index<dim, spacedim>(hex->face(2)),
8989 middle_vertex_index<dim, spacedim>(hex->face(3))});
8990
8991 // again, first collect some data about the
8992 // indices of the lines, with the following
8993 // numbering:
8994
8995 // face 0: left plane
8996 // *
8997 // /|
8998 // / |
8999 // / *
9000 // * /|
9001 // | 0 |
9002 // |/ *
9003 // * /
9004 // | /
9005 // |/
9006 // *
9007 // face 1: right plane
9008 // *
9009 // /|
9010 // / |
9011 // / *
9012 // * /|
9013 // | 1 |
9014 // |/ *
9015 // * /
9016 // | /
9017 // |/
9018 // *
9019 // face 2: front plane
9020 // (note: x,y exchanged)
9021 // *---*---*
9022 // | 5 |
9023 // *-6-*-7-*
9024 // | 4 |
9025 // *---*---*
9026 // face 3: back plane
9027 // (note: x,y exchanged)
9028 // *---*---*
9029 // | 9 |
9030 // *10-*-11*
9031 // | 8 |
9032 // *---*---*
9033 // face 4: bottom plane
9034 // *---*---*
9035 // / / /
9036 // / 2 /
9037 // / / /
9038 // *---*---*
9039 // face 5: top plane
9040 // *---*---*
9041 // / / /
9042 // / 3 /
9043 // / / /
9044 // *---*---*
9045 // middle planes
9046 // *---*---* *-------*
9047 // / / / | |
9048 // / 12 / | |
9049 // / / / | |
9050 // *---*---* *-------*
9051
9052 // set up a list of line iterators first. from
9053 // this, construct lists of line_indices and
9054 // line orientations later on
9055 const typename Triangulation<
9056 dim,
9057 spacedim>::raw_line_iterator lines[13] = {
9058 hex->face(0)->child(0)->line(
9059 (hex->face(0)->refinement_case() ==
9061 1 :
9062 3), // 0
9063 hex->face(1)->child(0)->line(
9064 (hex->face(1)->refinement_case() ==
9066 1 :
9067 3), // 1
9068 hex->face(4)->child(0)->line(
9069 (hex->face(4)->refinement_case() ==
9071 1 :
9072 3), // 2
9073 hex->face(5)->child(0)->line(
9074 (hex->face(5)->refinement_case() ==
9076 1 :
9077 3), // 3
9078
9079 hex->face(2)
9080 ->isotropic_child(
9082 0, f_or[2], f_fl[2], f_ro[2]))
9083 ->line(
9085 3, f_or[2], f_fl[2], f_ro[2])), // 4
9086 hex->face(2)
9087 ->isotropic_child(
9089 3, f_or[2], f_fl[2], f_ro[2]))
9090 ->line(
9092 2, f_or[2], f_fl[2], f_ro[2])), // 5
9093 hex->face(2)
9094 ->isotropic_child(
9096 0, f_or[2], f_fl[2], f_ro[2]))
9097 ->line(
9099 1, f_or[2], f_fl[2], f_ro[2])), // 6
9100 hex->face(2)
9101 ->isotropic_child(
9103 3, f_or[2], f_fl[2], f_ro[2]))
9104 ->line(
9106 0, f_or[2], f_fl[2], f_ro[2])), // 7
9107
9108 hex->face(3)
9109 ->isotropic_child(
9111 0, f_or[3], f_fl[3], f_ro[3]))
9112 ->line(
9114 3, f_or[3], f_fl[3], f_ro[3])), // 8
9115 hex->face(3)
9116 ->isotropic_child(
9118 3, f_or[3], f_fl[3], f_ro[3]))
9119 ->line(
9121 2, f_or[3], f_fl[3], f_ro[3])), // 9
9122 hex->face(3)
9123 ->isotropic_child(
9125 0, f_or[3], f_fl[3], f_ro[3]))
9126 ->line(
9128 1, f_or[3], f_fl[3], f_ro[3])), // 10
9129 hex->face(3)
9130 ->isotropic_child(
9132 3, f_or[3], f_fl[3], f_ro[3]))
9133 ->line(
9135 0, f_or[3], f_fl[3], f_ro[3])), // 11
9136
9137 new_lines[0] // 12
9138 };
9139
9140 unsigned int line_indices[13];
9141 for (unsigned int i = 0; i < 13; ++i)
9142 line_indices[i] = lines[i]->index();
9143
9144 // the orientation of lines for the inner quads
9145 // is quite tricky. as these lines are newly
9146 // created ones and thus have no parents, they
9147 // cannot inherit this property. set up an array
9148 // and fill it with the respective values
9149 bool line_orientation[13];
9150
9151 // the middle vertices of the
9152 // lines of our front face
9153 const unsigned int middle_vertices[4] = {
9154 hex->line(8)->child(0)->vertex_index(1),
9155 hex->line(9)->child(0)->vertex_index(1),
9156 hex->line(2)->child(0)->vertex_index(1),
9157 hex->line(6)->child(0)->vertex_index(1),
9158 };
9159
9160 // note: for lines 0 to 3 the orientation of the
9161 // line is 'true', if vertex 0 is on the front
9162 for (unsigned int i = 0; i < 4; ++i)
9163 if (lines[i]->vertex_index(0) == middle_vertices[i])
9164 line_orientation[i] = true;
9165 else
9166 {
9167 // it must be the other way round then
9168 Assert(lines[i]->vertex_index(1) ==
9169 middle_vertices[i],
9171 line_orientation[i] = false;
9172 }
9173
9174 // note: for lines 4 to 11 (inner lines of the
9175 // outer quads) the following holds: the second
9176 // vertex of the even lines in standard
9177 // orientation is the vertex in the middle of
9178 // the quad, whereas for odd lines the first
9179 // vertex is the same middle vertex.
9180 for (unsigned int i = 4; i < 12; ++i)
9181 if (lines[i]->vertex_index((i + 1) % 2) ==
9182 middle_vertex_index<dim, spacedim>(
9183 hex->face(1 + i / 4)))
9184 line_orientation[i] = true;
9185 else
9186 {
9187 // it must be the other way
9188 // round then
9189 Assert(lines[i]->vertex_index(i % 2) ==
9190 (middle_vertex_index<dim, spacedim>(
9191 hex->face(1 + i / 4))),
9193 line_orientation[i] = false;
9194 }
9195 // for the last line the line orientation is
9196 // always true, since it was just constructed
9197 // that way
9198 line_orientation[12] = true;
9199
9200 // set up the 4 quads, numbered as follows (left
9201 // quad numbering, right line numbering
9202 // extracted from above), the drawings denote
9203 // middle planes
9204 //
9205 // * *
9206 // /| /|
9207 // / | 3 9
9208 // y/ * / *
9209 // * 3/| * /|
9210 // | / |x 5 12|8
9211 // |/ * |/ *
9212 // * 2/ * /
9213 // | / 4 2
9214 // |/ |/
9215 // * *
9216 //
9217 // y
9218 // *----*----* *-10-*-11-*
9219 // / / / / / /
9220 // / 0 / 1 / 0 12 1
9221 // / / / / / /
9222 // *----*----*x *--6-*--7-*
9223
9224 new_quads[0]->set_bounding_object_indices(
9225 {line_indices[0],
9226 line_indices[12],
9227 line_indices[6],
9228 line_indices[10]});
9229 new_quads[1]->set_bounding_object_indices(
9230 {line_indices[12],
9231 line_indices[1],
9232 line_indices[7],
9233 line_indices[11]});
9234 new_quads[2]->set_bounding_object_indices(
9235 {line_indices[4],
9236 line_indices[8],
9237 line_indices[2],
9238 line_indices[12]});
9239 new_quads[3]->set_bounding_object_indices(
9240 {line_indices[5],
9241 line_indices[9],
9242 line_indices[12],
9243 line_indices[3]});
9244
9245 new_quads[0]->set_line_orientation(
9246 0, line_orientation[0]);
9247 new_quads[0]->set_line_orientation(
9248 2, line_orientation[6]);
9249 new_quads[0]->set_line_orientation(
9250 3, line_orientation[10]);
9251
9252 new_quads[1]->set_line_orientation(
9253 1, line_orientation[1]);
9254 new_quads[1]->set_line_orientation(
9255 2, line_orientation[7]);
9256 new_quads[1]->set_line_orientation(
9257 3, line_orientation[11]);
9258
9259 new_quads[2]->set_line_orientation(
9260 0, line_orientation[4]);
9261 new_quads[2]->set_line_orientation(
9262 1, line_orientation[8]);
9263 new_quads[2]->set_line_orientation(
9264 2, line_orientation[2]);
9265
9266 new_quads[3]->set_line_orientation(
9267 0, line_orientation[5]);
9268 new_quads[3]->set_line_orientation(
9269 1, line_orientation[9]);
9270 new_quads[3]->set_line_orientation(
9271 3, line_orientation[3]);
9272
9273 // the quads are numbered as follows:
9274 //
9275 // planes in the interior of the old hex:
9276 //
9277 // *
9278 // /|
9279 // / | x
9280 // /3 * *-------* *----*----*
9281 // * /| | | / / /
9282 // | / | | | / 0 / 1 /
9283 // |/ * | | / / /
9284 // * 2/ *-------*y *----*----*x
9285 // | /
9286 // |/
9287 // *
9288 //
9289 // children of the faces
9290 // of the old hex
9291 // *---*---* *---*---*
9292 // /|13 | 15| / / /|
9293 // / | | | /18 / 19/ |
9294 // / *---*---* / / / *
9295 // * 5/| | | *---*---* 7/|
9296 // | / |12 | 14| | 9 | 11| / |
9297 // |/4 *---*---* | | |/6 *
9298 // * / / / *---*---* /
9299 // | /16 / 17/ | | | /
9300 // |/ / / | 8 | 10|/
9301 // *---*---* *---*---*
9302 //
9303 // note that we have to take care of the
9304 // orientation of faces.
9305 const int quad_indices[20] = {
9306 new_quads[0]->index(), // 0
9307 new_quads[1]->index(),
9308 new_quads[2]->index(),
9309 new_quads[3]->index(),
9310
9311 hex->face(0)->child_index(
9312 child_at_origin[hex->face(0)->refinement_case() -
9313 1][f_fl[0]][f_ro[0]]), // 4
9314 hex->face(0)->child_index(
9315 1 -
9316 child_at_origin[hex->face(0)->refinement_case() -
9317 1][f_fl[0]][f_ro[0]]),
9318
9319 hex->face(1)->child_index(
9320 child_at_origin[hex->face(1)->refinement_case() -
9321 1][f_fl[1]][f_ro[1]]), // 6
9322 hex->face(1)->child_index(
9323 1 -
9324 child_at_origin[hex->face(1)->refinement_case() -
9325 1][f_fl[1]][f_ro[1]]),
9326
9327 hex->face(2)->isotropic_child_index(
9329 0, f_or[2], f_fl[2], f_ro[2])), // 8
9330 hex->face(2)->isotropic_child_index(
9332 1, f_or[2], f_fl[2], f_ro[2])),
9333 hex->face(2)->isotropic_child_index(
9335 2, f_or[2], f_fl[2], f_ro[2])),
9336 hex->face(2)->isotropic_child_index(
9338 3, f_or[2], f_fl[2], f_ro[2])),
9339
9340 hex->face(3)->isotropic_child_index(
9342 0, f_or[3], f_fl[3], f_ro[3])), // 12
9343 hex->face(3)->isotropic_child_index(
9345 1, f_or[3], f_fl[3], f_ro[3])),
9346 hex->face(3)->isotropic_child_index(
9348 2, f_or[3], f_fl[3], f_ro[3])),
9349 hex->face(3)->isotropic_child_index(
9351 3, f_or[3], f_fl[3], f_ro[3])),
9352
9353 hex->face(4)->child_index(
9354 child_at_origin[hex->face(4)->refinement_case() -
9355 1][f_fl[4]][f_ro[4]]), // 16
9356 hex->face(4)->child_index(
9357 1 -
9358 child_at_origin[hex->face(4)->refinement_case() -
9359 1][f_fl[4]][f_ro[4]]),
9360
9361 hex->face(5)->child_index(
9362 child_at_origin[hex->face(5)->refinement_case() -
9363 1][f_fl[5]][f_ro[5]]), // 18
9364 hex->face(5)->child_index(
9365 1 -
9366 child_at_origin[hex->face(5)->refinement_case() -
9367 1][f_fl[5]][f_ro[5]])};
9368
9369 // due to the exchange of x and y for the front
9370 // and back face, we order the children
9371 // according to
9372 //
9373 // *---*---*
9374 // | 1 | 3 |
9375 // *---*---*
9376 // | 0 | 2 |
9377 // *---*---*
9378 new_hexes[0]->set_bounding_object_indices(
9379 {quad_indices[4],
9380 quad_indices[2],
9381 quad_indices[8],
9382 quad_indices[12],
9383 quad_indices[16],
9384 quad_indices[0]});
9385 new_hexes[1]->set_bounding_object_indices(
9386 {quad_indices[5],
9387 quad_indices[3],
9388 quad_indices[9],
9389 quad_indices[13],
9390 quad_indices[0],
9391 quad_indices[18]});
9392 new_hexes[2]->set_bounding_object_indices(
9393 {quad_indices[2],
9394 quad_indices[6],
9395 quad_indices[10],
9396 quad_indices[14],
9397 quad_indices[17],
9398 quad_indices[1]});
9399 new_hexes[3]->set_bounding_object_indices(
9400 {quad_indices[3],
9401 quad_indices[7],
9402 quad_indices[11],
9403 quad_indices[15],
9404 quad_indices[1],
9405 quad_indices[19]});
9406 break;
9407 }
9408
9410 {
9411 //----------------------------
9412 //
9413 // RefinementCase<dim>::cut_yz
9414 //
9415 // the refined cube will look like this:
9416 //
9417 // *---------*
9418 // / /|
9419 // *---------* |
9420 // / /| |
9421 // *---------* |/|
9422 // | | * |
9423 // | |/| *
9424 // *---------* |/
9425 // | | *
9426 // | |/
9427 // *---------*
9428 //
9429
9430 // first, create the new
9431 // internal line
9432 new_lines[0]->set_bounding_object_indices(
9433
9434 {middle_vertex_index<dim, spacedim>(hex->face(0)),
9435 middle_vertex_index<dim, spacedim>(hex->face(1))});
9436
9437 // again, first collect some data about the
9438 // indices of the lines, with the following
9439 // numbering: (note that face 0 and 1 each are
9440 // shown twice for better readability)
9441
9442 // face 0: left plane
9443 // * *
9444 // /| /|
9445 // * | * |
9446 // /| * /| *
9447 // * 5/| * |7|
9448 // | * | | * |
9449 // |/| * |6| *
9450 // * 4/ * |/
9451 // | * | *
9452 // |/ |/
9453 // * *
9454 // face 1: right plane
9455 // * *
9456 // /| /|
9457 // * | * |
9458 // /| * /| *
9459 // * 9/| * |11
9460 // | * | | * |
9461 // |/| * |10 *
9462 // * 8/ * |/
9463 // | * | *
9464 // |/ |/
9465 // * *
9466 // face 2: front plane
9467 // (note: x,y exchanged)
9468 // *-------*
9469 // | |
9470 // *---0---*
9471 // | |
9472 // *-------*
9473 // face 3: back plane
9474 // (note: x,y exchanged)
9475 // *-------*
9476 // | |
9477 // *---1---*
9478 // | |
9479 // *-------*
9480 // face 4: bottom plane
9481 // *-------*
9482 // / /
9483 // *---2---*
9484 // / /
9485 // *-------*
9486 // face 5: top plane
9487 // *-------*
9488 // / /
9489 // *---3---*
9490 // / /
9491 // *-------*
9492 // middle planes
9493 // *-------* *-------*
9494 // / / | |
9495 // *---12--* | |
9496 // / / | |
9497 // *-------* *-------*
9498
9499 // set up a list of line iterators first. from
9500 // this, construct lists of line_indices and
9501 // line orientations later on
9502 const typename Triangulation<
9503 dim,
9504 spacedim>::raw_line_iterator lines[13] = {
9505 hex->face(2)->child(0)->line(
9506 (hex->face(2)->refinement_case() ==
9508 1 :
9509 3), // 0
9510 hex->face(3)->child(0)->line(
9511 (hex->face(3)->refinement_case() ==
9513 1 :
9514 3), // 1
9515 hex->face(4)->child(0)->line(
9516 (hex->face(4)->refinement_case() ==
9518 1 :
9519 3), // 2
9520 hex->face(5)->child(0)->line(
9521 (hex->face(5)->refinement_case() ==
9523 1 :
9524 3), // 3
9525
9526 hex->face(0)
9527 ->isotropic_child(
9529 0, f_or[0], f_fl[0], f_ro[0]))
9530 ->line(
9532 1, f_or[0], f_fl[0], f_ro[0])), // 4
9533 hex->face(0)
9534 ->isotropic_child(
9536 3, f_or[0], f_fl[0], f_ro[0]))
9537 ->line(
9539 0, f_or[0], f_fl[0], f_ro[0])), // 5
9540 hex->face(0)
9541 ->isotropic_child(
9543 0, f_or[0], f_fl[0], f_ro[0]))
9544 ->line(
9546 3, f_or[0], f_fl[0], f_ro[0])), // 6
9547 hex->face(0)
9548 ->isotropic_child(
9550 3, f_or[0], f_fl[0], f_ro[0]))
9551 ->line(
9553 2, f_or[0], f_fl[0], f_ro[0])), // 7
9554
9555 hex->face(1)
9556 ->isotropic_child(
9558 0, f_or[1], f_fl[1], f_ro[1]))
9559 ->line(
9561 1, f_or[1], f_fl[1], f_ro[1])), // 8
9562 hex->face(1)
9563 ->isotropic_child(
9565 3, f_or[1], f_fl[1], f_ro[1]))
9566 ->line(
9568 0, f_or[1], f_fl[1], f_ro[1])), // 9
9569 hex->face(1)
9570 ->isotropic_child(
9572 0, f_or[1], f_fl[1], f_ro[1]))
9573 ->line(
9575 3, f_or[1], f_fl[1], f_ro[1])), // 10
9576 hex->face(1)
9577 ->isotropic_child(
9579 3, f_or[1], f_fl[1], f_ro[1]))
9580 ->line(
9582 2, f_or[1], f_fl[1], f_ro[1])), // 11
9583
9584 new_lines[0] // 12
9585 };
9586
9587 unsigned int line_indices[13];
9588
9589 for (unsigned int i = 0; i < 13; ++i)
9590 line_indices[i] = lines[i]->index();
9591
9592 // the orientation of lines for the inner quads
9593 // is quite tricky. as these lines are newly
9594 // created ones and thus have no parents, they
9595 // cannot inherit this property. set up an array
9596 // and fill it with the respective values
9597 bool line_orientation[13];
9598
9599 // the middle vertices of the lines of our front
9600 // face
9601 const unsigned int middle_vertices[4] = {
9602 hex->line(8)->child(0)->vertex_index(1),
9603 hex->line(10)->child(0)->vertex_index(1),
9604 hex->line(0)->child(0)->vertex_index(1),
9605 hex->line(4)->child(0)->vertex_index(1),
9606 };
9607
9608 // note: for lines 0 to 3 the orientation of the
9609 // line is 'true', if vertex 0 is on the front
9610 for (unsigned int i = 0; i < 4; ++i)
9611 if (lines[i]->vertex_index(0) == middle_vertices[i])
9612 line_orientation[i] = true;
9613 else
9614 {
9615 // it must be the other way round then
9616 Assert(lines[i]->vertex_index(1) ==
9617 middle_vertices[i],
9619 line_orientation[i] = false;
9620 }
9621
9622 // note: for lines 4 to 11 (inner lines of the
9623 // outer quads) the following holds: the second
9624 // vertex of the even lines in standard
9625 // orientation is the vertex in the middle of
9626 // the quad, whereas for odd lines the first
9627 // vertex is the same middle vertex.
9628 for (unsigned int i = 4; i < 12; ++i)
9629 if (lines[i]->vertex_index((i + 1) % 2) ==
9630 middle_vertex_index<dim, spacedim>(
9631 hex->face(i / 4 - 1)))
9632 line_orientation[i] = true;
9633 else
9634 {
9635 // it must be the other way
9636 // round then
9637 Assert(lines[i]->vertex_index(i % 2) ==
9638 (middle_vertex_index<dim, spacedim>(
9639 hex->face(i / 4 - 1))),
9641 line_orientation[i] = false;
9642 }
9643 // for the last line the line orientation is
9644 // always true, since it was just constructed
9645 // that way
9646 line_orientation[12] = true;
9647
9648 // set up the 4 quads, numbered as follows (left
9649 // quad numbering, right line numbering
9650 // extracted from above)
9651 //
9652 // x
9653 // *-------* *---3---*
9654 // | 3 | 5 9
9655 // *-------* *---12--*
9656 // | 2 | 4 8
9657 // *-------*y *---2---*
9658 //
9659 // y
9660 // *---------* *----1----*
9661 // / 1 / 7 11
9662 // *---------* *----12---*
9663 // / 0 / 6 10
9664 // *---------*x *----0----*
9665
9666 new_quads[0]->set_bounding_object_indices(
9667 {line_indices[6],
9668 line_indices[10],
9669 line_indices[0],
9670 line_indices[12]});
9671 new_quads[1]->set_bounding_object_indices(
9672 {line_indices[7],
9673 line_indices[11],
9674 line_indices[12],
9675 line_indices[1]});
9676 new_quads[2]->set_bounding_object_indices(
9677 {line_indices[2],
9678 line_indices[12],
9679 line_indices[4],
9680 line_indices[8]});
9681 new_quads[3]->set_bounding_object_indices(
9682 {line_indices[12],
9683 line_indices[3],
9684 line_indices[5],
9685 line_indices[9]});
9686
9687 new_quads[0]->set_line_orientation(
9688 0, line_orientation[6]);
9689 new_quads[0]->set_line_orientation(
9690 1, line_orientation[10]);
9691 new_quads[0]->set_line_orientation(
9692 2, line_orientation[0]);
9693
9694 new_quads[1]->set_line_orientation(
9695 0, line_orientation[7]);
9696 new_quads[1]->set_line_orientation(
9697 1, line_orientation[11]);
9698 new_quads[1]->set_line_orientation(
9699 3, line_orientation[1]);
9700
9701 new_quads[2]->set_line_orientation(
9702 0, line_orientation[2]);
9703 new_quads[2]->set_line_orientation(
9704 2, line_orientation[4]);
9705 new_quads[2]->set_line_orientation(
9706 3, line_orientation[8]);
9707
9708 new_quads[3]->set_line_orientation(
9709 1, line_orientation[3]);
9710 new_quads[3]->set_line_orientation(
9711 2, line_orientation[5]);
9712 new_quads[3]->set_line_orientation(
9713 3, line_orientation[9]);
9714
9715 // the quads are numbered as follows:
9716 //
9717 // planes in the interior of the old hex:
9718 //
9719 // *
9720 // /|
9721 // / | x
9722 // / | *-------* *---------*
9723 // * | | 3 | / 1 /
9724 // | | *-------* *---------*
9725 // | * | 2 | / 0 /
9726 // | / *-------*y *---------*x
9727 // | /
9728 // |/
9729 // *
9730 //
9731 // children of the faces
9732 // of the old hex
9733 // *-------* *-------*
9734 // /| | / 19 /|
9735 // * | 15 | *-------* |
9736 // /|7*-------* / 18 /|11
9737 // * |/| | *-------* |/|
9738 // |6* | 14 | | 10* |
9739 // |/|5*-------* | 13 |/|9*
9740 // * |/ 17 / *-------* |/
9741 // |4*-------* | |8*
9742 // |/ 16 / | 12 |/
9743 // *-------* *-------*
9744 //
9745 // note that we have to take care of the
9746 // orientation of faces.
9747 const int quad_indices[20] = {
9748 new_quads[0]->index(), // 0
9749 new_quads[1]->index(),
9750 new_quads[2]->index(),
9751 new_quads[3]->index(),
9752
9753 hex->face(0)->isotropic_child_index(
9755 0, f_or[0], f_fl[0], f_ro[0])), // 4
9756 hex->face(0)->isotropic_child_index(
9758 1, f_or[0], f_fl[0], f_ro[0])),
9759 hex->face(0)->isotropic_child_index(
9761 2, f_or[0], f_fl[0], f_ro[0])),
9762 hex->face(0)->isotropic_child_index(
9764 3, f_or[0], f_fl[0], f_ro[0])),
9765
9766 hex->face(1)->isotropic_child_index(
9768 0, f_or[1], f_fl[1], f_ro[1])), // 8
9769 hex->face(1)->isotropic_child_index(
9771 1, f_or[1], f_fl[1], f_ro[1])),
9772 hex->face(1)->isotropic_child_index(
9774 2, f_or[1], f_fl[1], f_ro[1])),
9775 hex->face(1)->isotropic_child_index(
9777 3, f_or[1], f_fl[1], f_ro[1])),
9778
9779 hex->face(2)->child_index(
9780 child_at_origin[hex->face(2)->refinement_case() -
9781 1][f_fl[2]][f_ro[2]]), // 12
9782 hex->face(2)->child_index(
9783 1 -
9784 child_at_origin[hex->face(2)->refinement_case() -
9785 1][f_fl[2]][f_ro[2]]),
9786
9787 hex->face(3)->child_index(
9788 child_at_origin[hex->face(3)->refinement_case() -
9789 1][f_fl[3]][f_ro[3]]), // 14
9790 hex->face(3)->child_index(
9791 1 -
9792 child_at_origin[hex->face(3)->refinement_case() -
9793 1][f_fl[3]][f_ro[3]]),
9794
9795 hex->face(4)->child_index(
9796 child_at_origin[hex->face(4)->refinement_case() -
9797 1][f_fl[4]][f_ro[4]]), // 16
9798 hex->face(4)->child_index(
9799 1 -
9800 child_at_origin[hex->face(4)->refinement_case() -
9801 1][f_fl[4]][f_ro[4]]),
9802
9803 hex->face(5)->child_index(
9804 child_at_origin[hex->face(5)->refinement_case() -
9805 1][f_fl[5]][f_ro[5]]), // 18
9806 hex->face(5)->child_index(
9807 1 -
9808 child_at_origin[hex->face(5)->refinement_case() -
9809 1][f_fl[5]][f_ro[5]])};
9810
9811 new_hexes[0]->set_bounding_object_indices(
9812 {quad_indices[4],
9813 quad_indices[8],
9814 quad_indices[12],
9815 quad_indices[2],
9816 quad_indices[16],
9817 quad_indices[0]});
9818 new_hexes[1]->set_bounding_object_indices(
9819 {quad_indices[5],
9820 quad_indices[9],
9821 quad_indices[2],
9822 quad_indices[14],
9823 quad_indices[17],
9824 quad_indices[1]});
9825 new_hexes[2]->set_bounding_object_indices(
9826 {quad_indices[6],
9827 quad_indices[10],
9828 quad_indices[13],
9829 quad_indices[3],
9830 quad_indices[0],
9831 quad_indices[18]});
9832 new_hexes[3]->set_bounding_object_indices(
9833 {quad_indices[7],
9834 quad_indices[11],
9835 quad_indices[3],
9836 quad_indices[15],
9837 quad_indices[1],
9838 quad_indices[19]});
9839 break;
9840 }
9841
9843 {
9844 //----------------------------
9845 //
9846 // RefinementCase<dim>::cut_xyz
9847 // isotropic refinement
9848 //
9849 // the refined cube will look
9850 // like this:
9851 //
9852 // *----*----*
9853 // / / /|
9854 // *----*----* |
9855 // / / /| *
9856 // *----*----* |/|
9857 // | | | * |
9858 // | | |/| *
9859 // *----*----* |/
9860 // | | | *
9861 // | | |/
9862 // *----*----*
9863 //
9864
9865 // find the next unused vertex and set it
9866 // appropriately
9867 while (
9868 triangulation.vertices_used[next_unused_vertex] ==
9869 true)
9870 ++next_unused_vertex;
9871 Assert(
9872 next_unused_vertex < triangulation.vertices.size(),
9873 ExcMessage(
9874 "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."));
9875 triangulation.vertices_used[next_unused_vertex] =
9876 true;
9877
9878 // the new vertex is definitely in the interior,
9879 // so we need not worry about the
9880 // boundary. However we need to worry about
9881 // Manifolds. Let the cell compute its own
9882 // center, by querying the underlying manifold
9883 // object.
9884 triangulation.vertices[next_unused_vertex] =
9885 hex->center(true, true);
9886
9887 // set the data of the six lines. first collect
9888 // the indices of the seven vertices (consider
9889 // the two planes to be crossed to form the
9890 // planes cutting the hex in two vertically and
9891 // horizontally)
9892 //
9893 // *--3--* *--5--*
9894 // / / / | | |
9895 // 0--6--1 0--6--1
9896 // / / / | | |
9897 // *--2--* *--4--*
9898 // the lines are numbered
9899 // as follows:
9900 // *--*--* *--*--*
9901 // / 1 / | 5 |
9902 // *2-*-3* *2-*-3*
9903 // / 0 / | 4 |
9904 // *--*--* *--*--*
9905 //
9906 const unsigned int vertex_indices[7] = {
9907 middle_vertex_index<dim, spacedim>(hex->face(0)),
9908 middle_vertex_index<dim, spacedim>(hex->face(1)),
9909 middle_vertex_index<dim, spacedim>(hex->face(2)),
9910 middle_vertex_index<dim, spacedim>(hex->face(3)),
9911 middle_vertex_index<dim, spacedim>(hex->face(4)),
9912 middle_vertex_index<dim, spacedim>(hex->face(5)),
9913 next_unused_vertex};
9914
9915 new_lines[0]->set_bounding_object_indices(
9917 new_lines[1]->set_bounding_object_indices(
9919 new_lines[2]->set_bounding_object_indices(
9921 new_lines[3]->set_bounding_object_indices(
9923 new_lines[4]->set_bounding_object_indices(
9925 new_lines[5]->set_bounding_object_indices(
9927
9928 // again, first collect some data about the
9929 // indices of the lines, with the following
9930 // numbering: (note that face 0 and 1 each are
9931 // shown twice for better readability)
9932
9933 // face 0: left plane
9934 // * *
9935 // /| /|
9936 // * | * |
9937 // /| * /| *
9938 // * 1/| * |3|
9939 // | * | | * |
9940 // |/| * |2| *
9941 // * 0/ * |/
9942 // | * | *
9943 // |/ |/
9944 // * *
9945 // face 1: right plane
9946 // * *
9947 // /| /|
9948 // * | * |
9949 // /| * /| *
9950 // * 5/| * |7|
9951 // | * | | * |
9952 // |/| * |6| *
9953 // * 4/ * |/
9954 // | * | *
9955 // |/ |/
9956 // * *
9957 // face 2: front plane
9958 // (note: x,y exchanged)
9959 // *---*---*
9960 // | 11 |
9961 // *-8-*-9-*
9962 // | 10 |
9963 // *---*---*
9964 // face 3: back plane
9965 // (note: x,y exchanged)
9966 // *---*---*
9967 // | 15 |
9968 // *12-*-13*
9969 // | 14 |
9970 // *---*---*
9971 // face 4: bottom plane
9972 // *---*---*
9973 // / 17 /
9974 // *18-*-19*
9975 // / 16 /
9976 // *---*---*
9977 // face 5: top plane
9978 // *---*---*
9979 // / 21 /
9980 // *22-*-23*
9981 // / 20 /
9982 // *---*---*
9983 // middle planes
9984 // *---*---* *---*---*
9985 // / 25 / | 29 |
9986 // *26-*-27* *26-*-27*
9987 // / 24 / | 28 |
9988 // *---*---* *---*---*
9989
9990 // set up a list of line iterators first. from
9991 // this, construct lists of line_indices and
9992 // line orientations later on
9993 const typename Triangulation<
9994 dim,
9995 spacedim>::raw_line_iterator lines[30] = {
9996 hex->face(0)
9997 ->isotropic_child(
9999 0, f_or[0], f_fl[0], f_ro[0]))
10000 ->line(
10002 1, f_or[0], f_fl[0], f_ro[0])), // 0
10003 hex->face(0)
10004 ->isotropic_child(
10006 3, f_or[0], f_fl[0], f_ro[0]))
10007 ->line(
10009 0, f_or[0], f_fl[0], f_ro[0])), // 1
10010 hex->face(0)
10011 ->isotropic_child(
10013 0, f_or[0], f_fl[0], f_ro[0]))
10014 ->line(
10016 3, f_or[0], f_fl[0], f_ro[0])), // 2
10017 hex->face(0)
10018 ->isotropic_child(
10020 3, f_or[0], f_fl[0], f_ro[0]))
10021 ->line(
10023 2, f_or[0], f_fl[0], f_ro[0])), // 3
10024
10025 hex->face(1)
10026 ->isotropic_child(
10028 0, f_or[1], f_fl[1], f_ro[1]))
10029 ->line(
10031 1, f_or[1], f_fl[1], f_ro[1])), // 4
10032 hex->face(1)
10033 ->isotropic_child(
10035 3, f_or[1], f_fl[1], f_ro[1]))
10036 ->line(
10038 0, f_or[1], f_fl[1], f_ro[1])), // 5
10039 hex->face(1)
10040 ->isotropic_child(
10042 0, f_or[1], f_fl[1], f_ro[1]))
10043 ->line(
10045 3, f_or[1], f_fl[1], f_ro[1])), // 6
10046 hex->face(1)
10047 ->isotropic_child(
10049 3, f_or[1], f_fl[1], f_ro[1]))
10050 ->line(
10052 2, f_or[1], f_fl[1], f_ro[1])), // 7
10053
10054 hex->face(2)
10055 ->isotropic_child(
10057 0, f_or[2], f_fl[2], f_ro[2]))
10058 ->line(
10060 1, f_or[2], f_fl[2], f_ro[2])), // 8
10061 hex->face(2)
10062 ->isotropic_child(
10064 3, f_or[2], f_fl[2], f_ro[2]))
10065 ->line(
10067 0, f_or[2], f_fl[2], f_ro[2])), // 9
10068 hex->face(2)
10069 ->isotropic_child(
10071 0, f_or[2], f_fl[2], f_ro[2]))
10072 ->line(
10074 3, f_or[2], f_fl[2], f_ro[2])), // 10
10075 hex->face(2)
10076 ->isotropic_child(
10078 3, f_or[2], f_fl[2], f_ro[2]))
10079 ->line(
10081 2, f_or[2], f_fl[2], f_ro[2])), // 11
10082
10083 hex->face(3)
10084 ->isotropic_child(
10086 0, f_or[3], f_fl[3], f_ro[3]))
10087 ->line(
10089 1, f_or[3], f_fl[3], f_ro[3])), // 12
10090 hex->face(3)
10091 ->isotropic_child(
10093 3, f_or[3], f_fl[3], f_ro[3]))
10094 ->line(
10096 0, f_or[3], f_fl[3], f_ro[3])), // 13
10097 hex->face(3)
10098 ->isotropic_child(
10100 0, f_or[3], f_fl[3], f_ro[3]))
10101 ->line(
10103 3, f_or[3], f_fl[3], f_ro[3])), // 14
10104 hex->face(3)
10105 ->isotropic_child(
10107 3, f_or[3], f_fl[3], f_ro[3]))
10108 ->line(
10110 2, f_or[3], f_fl[3], f_ro[3])), // 15
10111
10112 hex->face(4)
10113 ->isotropic_child(
10115 0, f_or[4], f_fl[4], f_ro[4]))
10116 ->line(
10118 1, f_or[4], f_fl[4], f_ro[4])), // 16
10119 hex->face(4)
10120 ->isotropic_child(
10122 3, f_or[4], f_fl[4], f_ro[4]))
10123 ->line(
10125 0, f_or[4], f_fl[4], f_ro[4])), // 17
10126 hex->face(4)
10127 ->isotropic_child(
10129 0, f_or[4], f_fl[4], f_ro[4]))
10130 ->line(
10132 3, f_or[4], f_fl[4], f_ro[4])), // 18
10133 hex->face(4)
10134 ->isotropic_child(
10136 3, f_or[4], f_fl[4], f_ro[4]))
10137 ->line(
10139 2, f_or[4], f_fl[4], f_ro[4])), // 19
10140
10141 hex->face(5)
10142 ->isotropic_child(
10144 0, f_or[5], f_fl[5], f_ro[5]))
10145 ->line(
10147 1, f_or[5], f_fl[5], f_ro[5])), // 20
10148 hex->face(5)
10149 ->isotropic_child(
10151 3, f_or[5], f_fl[5], f_ro[5]))
10152 ->line(
10154 0, f_or[5], f_fl[5], f_ro[5])), // 21
10155 hex->face(5)
10156 ->isotropic_child(
10158 0, f_or[5], f_fl[5], f_ro[5]))
10159 ->line(
10161 3, f_or[5], f_fl[5], f_ro[5])), // 22
10162 hex->face(5)
10163 ->isotropic_child(
10165 3, f_or[5], f_fl[5], f_ro[5]))
10166 ->line(
10168 2, f_or[5], f_fl[5], f_ro[5])), // 23
10169
10170 new_lines[0], // 24
10171 new_lines[1], // 25
10172 new_lines[2], // 26
10173 new_lines[3], // 27
10174 new_lines[4], // 28
10175 new_lines[5] // 29
10176 };
10177
10178 unsigned int line_indices[30];
10179 for (unsigned int i = 0; i < 30; ++i)
10180 line_indices[i] = lines[i]->index();
10181
10182 // the orientation of lines for the inner quads
10183 // is quite tricky. as these lines are newly
10184 // created ones and thus have no parents, they
10185 // cannot inherit this property. set up an array
10186 // and fill it with the respective values
10187 bool line_orientation[30];
10188
10189 // note: for the first 24 lines (inner lines of
10190 // the outer quads) the following holds: the
10191 // second vertex of the even lines in standard
10192 // orientation is the vertex in the middle of
10193 // the quad, whereas for odd lines the first
10194 // vertex is the same middle vertex.
10195 for (unsigned int i = 0; i < 24; ++i)
10196 if (lines[i]->vertex_index((i + 1) % 2) ==
10197 vertex_indices[i / 4])
10198 line_orientation[i] = true;
10199 else
10200 {
10201 // it must be the other way
10202 // round then
10203 Assert(lines[i]->vertex_index(i % 2) ==
10204 vertex_indices[i / 4],
10206 line_orientation[i] = false;
10207 }
10208 // for the last 6 lines the line orientation is
10209 // always true, since they were just constructed
10210 // that way
10211 for (unsigned int i = 24; i < 30; ++i)
10212 line_orientation[i] = true;
10213
10214 // set up the 12 quads, numbered as follows
10215 // (left quad numbering, right line numbering
10216 // extracted from above)
10217 //
10218 // * *
10219 // /| 21|
10220 // * | * 15
10221 // y/|3* 20| *
10222 // * |/| * |/|
10223 // |2* |x 11 * 14
10224 // |/|1* |/| *
10225 // * |/ * |17
10226 // |0* 10 *
10227 // |/ |16
10228 // * *
10229 //
10230 // x
10231 // *---*---* *22-*-23*
10232 // | 5 | 7 | 1 29 5
10233 // *---*---* *26-*-27*
10234 // | 4 | 6 | 0 28 4
10235 // *---*---*y *18-*-19*
10236 //
10237 // y
10238 // *----*----* *-12-*-13-*
10239 // / 10 / 11 / 3 25 7
10240 // *----*----* *-26-*-27-*
10241 // / 8 / 9 / 2 24 6
10242 // *----*----*x *--8-*--9-*
10243
10244 new_quads[0]->set_bounding_object_indices(
10245 {line_indices[10],
10246 line_indices[28],
10247 line_indices[16],
10248 line_indices[24]});
10249 new_quads[1]->set_bounding_object_indices(
10250 {line_indices[28],
10251 line_indices[14],
10252 line_indices[17],
10253 line_indices[25]});
10254 new_quads[2]->set_bounding_object_indices(
10255 {line_indices[11],
10256 line_indices[29],
10257 line_indices[24],
10258 line_indices[20]});
10259 new_quads[3]->set_bounding_object_indices(
10260 {line_indices[29],
10261 line_indices[15],
10262 line_indices[25],
10263 line_indices[21]});
10264 new_quads[4]->set_bounding_object_indices(
10265 {line_indices[18],
10266 line_indices[26],
10267 line_indices[0],
10268 line_indices[28]});
10269 new_quads[5]->set_bounding_object_indices(
10270 {line_indices[26],
10271 line_indices[22],
10272 line_indices[1],
10273 line_indices[29]});
10274 new_quads[6]->set_bounding_object_indices(
10275 {line_indices[19],
10276 line_indices[27],
10277 line_indices[28],
10278 line_indices[4]});
10279 new_quads[7]->set_bounding_object_indices(
10280 {line_indices[27],
10281 line_indices[23],
10282 line_indices[29],
10283 line_indices[5]});
10284 new_quads[8]->set_bounding_object_indices(
10285 {line_indices[2],
10286 line_indices[24],
10287 line_indices[8],
10288 line_indices[26]});
10289 new_quads[9]->set_bounding_object_indices(
10290 {line_indices[24],
10291 line_indices[6],
10292 line_indices[9],
10293 line_indices[27]});
10294 new_quads[10]->set_bounding_object_indices(
10295 {line_indices[3],
10296 line_indices[25],
10297 line_indices[26],
10298 line_indices[12]});
10299 new_quads[11]->set_bounding_object_indices(
10300 {line_indices[25],
10301 line_indices[7],
10302 line_indices[27],
10303 line_indices[13]});
10304
10305 // now reset the line_orientation flags of outer
10306 // lines as they cannot be set in a loop (at
10307 // least not easily)
10308 new_quads[0]->set_line_orientation(
10309 0, line_orientation[10]);
10310 new_quads[0]->set_line_orientation(
10311 2, line_orientation[16]);
10312
10313 new_quads[1]->set_line_orientation(
10314 1, line_orientation[14]);
10315 new_quads[1]->set_line_orientation(
10316 2, line_orientation[17]);
10317
10318 new_quads[2]->set_line_orientation(
10319 0, line_orientation[11]);
10320 new_quads[2]->set_line_orientation(
10321 3, line_orientation[20]);
10322
10323 new_quads[3]->set_line_orientation(
10324 1, line_orientation[15]);
10325 new_quads[3]->set_line_orientation(
10326 3, line_orientation[21]);
10327
10328 new_quads[4]->set_line_orientation(
10329 0, line_orientation[18]);
10330 new_quads[4]->set_line_orientation(
10331 2, line_orientation[0]);
10332
10333 new_quads[5]->set_line_orientation(
10334 1, line_orientation[22]);
10335 new_quads[5]->set_line_orientation(
10336 2, line_orientation[1]);
10337
10338 new_quads[6]->set_line_orientation(
10339 0, line_orientation[19]);
10340 new_quads[6]->set_line_orientation(
10341 3, line_orientation[4]);
10342
10343 new_quads[7]->set_line_orientation(
10344 1, line_orientation[23]);
10345 new_quads[7]->set_line_orientation(
10346 3, line_orientation[5]);
10347
10348 new_quads[8]->set_line_orientation(
10349 0, line_orientation[2]);
10350 new_quads[8]->set_line_orientation(
10351 2, line_orientation[8]);
10352
10353 new_quads[9]->set_line_orientation(
10354 1, line_orientation[6]);
10355 new_quads[9]->set_line_orientation(
10356 2, line_orientation[9]);
10357
10358 new_quads[10]->set_line_orientation(
10359 0, line_orientation[3]);
10360 new_quads[10]->set_line_orientation(
10361 3, line_orientation[12]);
10362
10363 new_quads[11]->set_line_orientation(
10364 1, line_orientation[7]);
10365 new_quads[11]->set_line_orientation(
10366 3, line_orientation[13]);
10367
10368 //-------------------------------
10369 // create the eight new hexes
10370 //
10371 // again first collect some data. here, we need
10372 // the indices of a whole lotta quads.
10373
10374 // the quads are numbered as follows:
10375 //
10376 // planes in the interior of the old hex:
10377 //
10378 // *
10379 // /|
10380 // * |
10381 // /|3* *---*---* *----*----*
10382 // * |/| | 5 | 7 | / 10 / 11 /
10383 // |2* | *---*---* *----*----*
10384 // |/|1* | 4 | 6 | / 8 / 9 /
10385 // * |/ *---*---*y *----*----*x
10386 // |0*
10387 // |/
10388 // *
10389 //
10390 // children of the faces
10391 // of the old hex
10392 // *-------* *-------*
10393 // /|25 27| /34 35/|
10394 // 15| | / /19
10395 // / | | /32 33/ |
10396 // * |24 26| *-------*18 |
10397 // 1413*-------* |21 23| 17*
10398 // | /30 31/ | | /
10399 // 12/ / | |16
10400 // |/28 29/ |20 22|/
10401 // *-------* *-------*
10402 //
10403 // note that we have to
10404 // take care of the
10405 // orientation of
10406 // faces.
10407 const int quad_indices[36] = {
10408 new_quads[0]->index(), // 0
10409 new_quads[1]->index(),
10410 new_quads[2]->index(),
10411 new_quads[3]->index(),
10412 new_quads[4]->index(),
10413 new_quads[5]->index(),
10414 new_quads[6]->index(),
10415 new_quads[7]->index(),
10416 new_quads[8]->index(),
10417 new_quads[9]->index(),
10418 new_quads[10]->index(),
10419 new_quads[11]->index(), // 11
10420
10421 hex->face(0)->isotropic_child_index(
10423 0, f_or[0], f_fl[0], f_ro[0])), // 12
10424 hex->face(0)->isotropic_child_index(
10426 1, f_or[0], f_fl[0], f_ro[0])),
10427 hex->face(0)->isotropic_child_index(
10429 2, f_or[0], f_fl[0], f_ro[0])),
10430 hex->face(0)->isotropic_child_index(
10432 3, f_or[0], f_fl[0], f_ro[0])),
10433
10434 hex->face(1)->isotropic_child_index(
10436 0, f_or[1], f_fl[1], f_ro[1])), // 16
10437 hex->face(1)->isotropic_child_index(
10439 1, f_or[1], f_fl[1], f_ro[1])),
10440 hex->face(1)->isotropic_child_index(
10442 2, f_or[1], f_fl[1], f_ro[1])),
10443 hex->face(1)->isotropic_child_index(
10445 3, f_or[1], f_fl[1], f_ro[1])),
10446
10447 hex->face(2)->isotropic_child_index(
10449 0, f_or[2], f_fl[2], f_ro[2])), // 20
10450 hex->face(2)->isotropic_child_index(
10452 1, f_or[2], f_fl[2], f_ro[2])),
10453 hex->face(2)->isotropic_child_index(
10455 2, f_or[2], f_fl[2], f_ro[2])),
10456 hex->face(2)->isotropic_child_index(
10458 3, f_or[2], f_fl[2], f_ro[2])),
10459
10460 hex->face(3)->isotropic_child_index(
10462 0, f_or[3], f_fl[3], f_ro[3])), // 24
10463 hex->face(3)->isotropic_child_index(
10465 1, f_or[3], f_fl[3], f_ro[3])),
10466 hex->face(3)->isotropic_child_index(
10468 2, f_or[3], f_fl[3], f_ro[3])),
10469 hex->face(3)->isotropic_child_index(
10471 3, f_or[3], f_fl[3], f_ro[3])),
10472
10473 hex->face(4)->isotropic_child_index(
10475 0, f_or[4], f_fl[4], f_ro[4])), // 28
10476 hex->face(4)->isotropic_child_index(
10478 1, f_or[4], f_fl[4], f_ro[4])),
10479 hex->face(4)->isotropic_child_index(
10481 2, f_or[4], f_fl[4], f_ro[4])),
10482 hex->face(4)->isotropic_child_index(
10484 3, f_or[4], f_fl[4], f_ro[4])),
10485
10486 hex->face(5)->isotropic_child_index(
10488 0, f_or[5], f_fl[5], f_ro[5])), // 32
10489 hex->face(5)->isotropic_child_index(
10491 1, f_or[5], f_fl[5], f_ro[5])),
10492 hex->face(5)->isotropic_child_index(
10494 2, f_or[5], f_fl[5], f_ro[5])),
10495 hex->face(5)->isotropic_child_index(
10497 3, f_or[5], f_fl[5], f_ro[5]))};
10498
10499 // bottom children
10500 new_hexes[0]->set_bounding_object_indices(
10501 {quad_indices[12],
10502 quad_indices[0],
10503 quad_indices[20],
10504 quad_indices[4],
10505 quad_indices[28],
10506 quad_indices[8]});
10507 new_hexes[1]->set_bounding_object_indices(
10508 {quad_indices[0],
10509 quad_indices[16],
10510 quad_indices[22],
10511 quad_indices[6],
10512 quad_indices[29],
10513 quad_indices[9]});
10514 new_hexes[2]->set_bounding_object_indices(
10515 {quad_indices[13],
10516 quad_indices[1],
10517 quad_indices[4],
10518 quad_indices[24],
10519 quad_indices[30],
10520 quad_indices[10]});
10521 new_hexes[3]->set_bounding_object_indices(
10522 {quad_indices[1],
10523 quad_indices[17],
10524 quad_indices[6],
10525 quad_indices[26],
10526 quad_indices[31],
10527 quad_indices[11]});
10528
10529 // top children
10530 new_hexes[4]->set_bounding_object_indices(
10531 {quad_indices[14],
10532 quad_indices[2],
10533 quad_indices[21],
10534 quad_indices[5],
10535 quad_indices[8],
10536 quad_indices[32]});
10537 new_hexes[5]->set_bounding_object_indices(
10538 {quad_indices[2],
10539 quad_indices[18],
10540 quad_indices[23],
10541 quad_indices[7],
10542 quad_indices[9],
10543 quad_indices[33]});
10544 new_hexes[6]->set_bounding_object_indices(
10545 {quad_indices[15],
10546 quad_indices[3],
10547 quad_indices[5],
10548 quad_indices[25],
10549 quad_indices[10],
10550 quad_indices[34]});
10551 new_hexes[7]->set_bounding_object_indices(
10552 {quad_indices[3],
10553 quad_indices[19],
10554 quad_indices[7],
10555 quad_indices[27],
10556 quad_indices[11],
10557 quad_indices[35]});
10558 break;
10559 }
10560 default:
10561 // all refinement cases have been treated, there
10562 // only remains
10563 // RefinementCase<dim>::no_refinement as
10564 // untreated enumeration value. However, in that
10565 // case we should have aborted much
10566 // earlier. thus we should never get here
10567 Assert(false, ExcInternalError());
10568 break;
10569 } // switch (ref_case)
10570
10571 // and set face orientation flags. note that new
10572 // faces in the interior of the mother cell always
10573 // have a correctly oriented face, but the ones on
10574 // the outer faces will inherit this flag
10575 //
10576 // the flag have been set to true for all faces
10577 // initially, now go the other way round and reset
10578 // faces that are at the boundary of the mother cube
10579 //
10580 // the same is true for the face_flip and
10581 // face_rotation flags. however, the latter two are
10582 // set to false by default as this is the standard
10583 // value
10584
10585 // loop over all faces and all (relevant) subfaces
10586 // of that in order to set the correct values for
10587 // face_orientation, face_flip and face_rotation,
10588 // which are inherited from the corresponding face
10589 // of the mother cube
10590 for (const unsigned int f : GeometryInfo<dim>::face_indices())
10591 for (unsigned int s = 0;
10594 ref_case, f)),
10595 1U);
10596 ++s)
10597 {
10598 const unsigned int current_child =
10600 ref_case,
10601 f,
10602 s,
10603 f_or[f],
10604 f_fl[f],
10605 f_ro[f],
10607 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
10608 new_hexes[current_child]->set_face_orientation(f,
10609 f_or[f]);
10610 new_hexes[current_child]->set_face_flip(f, f_fl[f]);
10611 new_hexes[current_child]->set_face_rotation(f, f_ro[f]);
10612 }
10613
10614 // now see if we have created cells that are
10615 // distorted and if so add them to our list
10616 if (check_for_distorted_cells &&
10617 has_distorted_children<dim, spacedim>(hex))
10618 cells_with_distorted_children.distorted_cells.push_back(
10619 hex);
10620
10621 // note that the refinement flag was already cleared
10622 // at the beginning of this loop
10623
10624 // inform all listeners that cell refinement is done
10625 triangulation.signals.post_refinement_on_cell(hex);
10626 }
10627 }
10628
10629 // clear user data on quads. we used some of this data to
10630 // indicate anisotropic refinemnt cases on faces. all data
10631 // should be cleared by now, but the information whether we
10632 // used indices or pointers is still present. reset it now to
10633 // enable the user to use whichever they like later on.
10634 triangulation.faces->quads.clear_user_data();
10635
10636 // return the list with distorted children
10637 return cells_with_distorted_children;
10638 }
10639
10640
10653 template <int spacedim>
10654 static void
10656 {}
10657
10658
10659
10660 template <int dim, int spacedim>
10661 static void
10664 {
10665 // If the codimension is one, we cannot perform this check
10666 // yet.
10667 if (spacedim > dim)
10668 return;
10669
10670 for (const auto &cell : triangulation.cell_iterators())
10671 if (cell->at_boundary() && cell->refine_flag_set() &&
10672 cell->refine_flag_set() !=
10674 {
10675 // The cell is at the boundary and it is flagged for
10676 // anisotropic refinement. Therefore, we have a closer
10677 // look
10678 const RefinementCase<dim> ref_case = cell->refine_flag_set();
10679 for (const unsigned int face_no :
10681 if (cell->face(face_no)->at_boundary())
10682 {
10683 // this is the critical face at the boundary.
10685 face_no) !=
10687 {
10688 // up to now, we do not want to refine this
10689 // cell along the face under consideration
10690 // here.
10691 const typename Triangulation<dim,
10692 spacedim>::face_iterator
10693 face = cell->face(face_no);
10694 // the new point on the boundary would be this
10695 // one.
10696 const Point<spacedim> new_bound = face->center(true);
10697 // to check it, transform to the unit cell
10698 // with a linear mapping
10699 const Point<dim> new_unit =
10700 cell->reference_cell()
10701 .template get_default_linear_mapping<dim,
10702 spacedim>()
10703 .transform_real_to_unit_cell(cell, new_bound);
10704
10705 // Now, we have to calculate the distance from
10706 // the face in the unit cell.
10707
10708 // take the correct coordinate direction (0
10709 // for faces 0 and 1, 1 for faces 2 and 3, 2
10710 // for faces 4 and 5) and subtract the correct
10711 // boundary value of the face (0 for faces 0,
10712 // 2, and 4; 1 for faces 1, 3 and 5)
10713 const double dist =
10714 std::fabs(new_unit[face_no / 2] - face_no % 2);
10715
10716 // compare this with the empirical value
10717 // allowed. if it is too big, flag the face
10718 // for isotropic refinement
10719 const double allowed = 0.25;
10720
10721 if (dist > allowed)
10722 cell->flag_for_face_refinement(face_no);
10723 } // if flagged for anistropic refinement
10724 } // if (cell->face(face)->at_boundary())
10725 } // for all cells
10726 }
10727
10728
10741 template <int dim, int spacedim>
10742 static void
10744 {
10745 Assert(dim < 3,
10746 ExcMessage("Wrong function called -- there should "
10747 "be a specialization."));
10748 }
10749
10750
10751 template <int spacedim>
10752 static void
10755 {
10756 const unsigned int dim = 3;
10757
10758 // first clear flags on lines, since we need them to determine
10759 // which lines will be refined
10760 triangulation.clear_user_flags_line();
10761
10762 // also clear flags on hexes, since we need them to mark those
10763 // cells which are to be coarsened
10764 triangulation.clear_user_flags_hex();
10765
10766 // variable to store whether the mesh was changed in the
10767 // present loop and in the whole process
10768 bool mesh_changed = false;
10769
10770 do
10771 {
10772 mesh_changed = false;
10773
10774 // for this following, we need to know which cells are
10775 // going to be coarsened, if we had to make a
10776 // decision. the following function sets these flags:
10777 triangulation.fix_coarsen_flags();
10778
10779
10780 // flag those lines that are refined and will not be
10781 // coarsened and those that will be refined
10782 for (const auto &cell : triangulation.cell_iterators())
10783 if (cell->refine_flag_set())
10784 {
10785 for (unsigned int line = 0; line < cell->n_lines(); ++line)
10787 cell->refine_flag_set(), line) ==
10789 // flag a line, that will be
10790 // refined
10791 cell->line(line)->set_user_flag();
10792 }
10793 else if (cell->has_children() &&
10794 !cell->child(0)->coarsen_flag_set())
10795 {
10796 for (unsigned int line = 0; line < cell->n_lines(); ++line)
10798 cell->refinement_case(), line) ==
10800 // flag a line, that is refined
10801 // and will stay so
10802 cell->line(line)->set_user_flag();
10803 }
10804 else if (cell->has_children() &&
10805 cell->child(0)->coarsen_flag_set())
10806 cell->set_user_flag();
10807
10808
10809 // now check whether there are cells with lines that are
10810 // more than once refined or that will be more than once
10811 // refined. The first thing should never be the case, in
10812 // the second case we flag the cell for refinement
10814 cell = triangulation.last_active();
10815 cell != triangulation.end();
10816 --cell)
10817 for (unsigned int line = 0; line < cell->n_lines(); ++line)
10818 {
10819 if (cell->line(line)->has_children())
10820 {
10821 // if this line is refined, its children should
10822 // not have further children
10823 //
10824 // however, if any of the children is flagged
10825 // for further refinement, we need to refine
10826 // this cell also (at least, if the cell is not
10827 // already flagged)
10828 bool offending_line_found = false;
10829
10830 for (unsigned int c = 0; c < 2; ++c)
10831 {
10832 Assert(cell->line(line)->child(c)->has_children() ==
10833 false,
10835
10836 if (cell->line(line)->child(c)->user_flag_set() &&
10838 cell->refine_flag_set(), line) ==
10840 {
10841 // tag this cell for refinement
10842 cell->clear_coarsen_flag();
10843 // if anisotropic coarsening is allowed:
10844 // extend the refine_flag in the needed
10845 // direction, else set refine_flag
10846 // (isotropic)
10847 if (triangulation.smooth_grid &
10849 allow_anisotropic_smoothing)
10850 cell->flag_for_line_refinement(line);
10851 else
10852 cell->set_refine_flag();
10853
10854 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10856 cell->refine_flag_set(), line) ==
10858 // flag a line, that will be refined
10859 cell->line(l)->set_user_flag();
10860
10861 // note that we have changed the grid
10862 offending_line_found = true;
10863
10864 // it may save us several loop
10865 // iterations if we flag all lines of
10866 // this cell now (and not at the outset
10867 // of the next iteration) for refinement
10868 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10869 if (!cell->line(l)->has_children() &&
10871 cell->refine_flag_set(), l) !=
10873 cell->line(l)->set_user_flag();
10874
10875 break;
10876 }
10877 }
10878
10879 if (offending_line_found)
10880 {
10881 mesh_changed = true;
10882 break;
10883 }
10884 }
10885 }
10886
10887
10888 // there is another thing here: if any of the lines will
10889 // be refined, then we may not coarsen the present cell
10890 // similarly, if any of the lines *is* already refined, we
10891 // may not coarsen the current cell. however, there's a
10892 // catch: if the line is refined, but the cell behind it
10893 // is going to be coarsened, then the situation
10894 // changes. if we forget this second condition, the
10895 // refine_and_coarsen_3d test will start to fail. note
10896 // that to know which cells are going to be coarsened, the
10897 // call for fix_coarsen_flags above is necessary
10899 triangulation.last();
10900 cell != triangulation.end();
10901 --cell)
10902 {
10903 if (cell->user_flag_set())
10904 for (unsigned int line = 0; line < cell->n_lines(); ++line)
10905 if (cell->line(line)->has_children() &&
10906 (cell->line(line)->child(0)->user_flag_set() ||
10907 cell->line(line)->child(1)->user_flag_set()))
10908 {
10909 for (unsigned int c = 0; c < cell->n_children(); ++c)
10910 cell->child(c)->clear_coarsen_flag();
10911 cell->clear_user_flag();
10912 for (unsigned int l = 0; l < cell->n_lines(); ++l)
10914 cell->refinement_case(), l) ==
10916 // flag a line, that is refined
10917 // and will stay so
10918 cell->line(l)->set_user_flag();
10919 mesh_changed = true;
10920 break;
10921 }
10922 }
10923 }
10924 while (mesh_changed == true);
10925 }
10926
10927
10928
10935 template <int dim, int spacedim>
10936 static bool
10939 {
10940 // in 1d, coarsening is always allowed since we don't enforce
10941 // the 2:1 constraint there
10942 if (dim == 1)
10943 return true;
10944
10945 const RefinementCase<dim> ref_case = cell->refinement_case();
10946 for (unsigned int n : GeometryInfo<dim>::face_indices())
10947 {
10948 // if the cell is not refined along that face, coarsening
10949 // will not change anything, so do nothing. the same
10950 // applies, if the face is at the boandary
10951 const RefinementCase<dim - 1> face_ref_case =
10952 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
10953 n);
10954
10955 const unsigned int n_subfaces =
10956 GeometryInfo<dim - 1>::n_children(face_ref_case);
10957
10958 if (n_subfaces == 0 || cell->at_boundary(n))
10959 continue;
10960 for (unsigned int c = 0; c < n_subfaces; ++c)
10961 {
10963 child = cell->child(
10965
10967 child_neighbor = child->neighbor(n);
10968 if (!child->neighbor_is_coarser(n))
10969 // in 2d, if the child's neighbor is coarser, then
10970 // it has no children. however, in 3d it might be
10971 // otherwise. consider for example, that our face
10972 // might be refined with cut_x, but the neighbor is
10973 // refined with cut_xy at that face. then the
10974 // neighbor pointers of the children of our cell
10975 // will point to the common neighbor cell, not to
10976 // its children. what we really want to know in the
10977 // following is, whether the neighbor cell is
10978 // refined twice with reference to our cell. that
10979 // only has to be asked, if the child's neighbor is
10980 // not a coarser one.
10981 if ((child_neighbor->has_children() &&
10982 !child_neighbor->user_flag_set()) ||
10983 // neighbor has children, which are further
10984 // refined along the face, otherwise something
10985 // went wrong in the construction of neighbor
10986 // pointers. then only allow coarsening if this
10987 // neighbor will be coarsened as well
10988 // (user_pointer is set). the same applies, if
10989 // the neighbors children are not refined but
10990 // will be after refinement
10991 child_neighbor->refine_flag_set())
10992 return false;
10993 }
10994 }
10995 return true;
10996 }
10997 };
10998
10999
11004 {
11005 template <int spacedim>
11006 static void
11008 {}
11009
11010 template <int dim, int spacedim>
11012 {
11013 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11014 2 * triangulation.n_raw_faces(),
11015 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11016
11017 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11018 const std::pair<unsigned int, unsigned int> cell_pair = {
11019 cell->level(), cell->index()};
11020 unsigned int index;
11021
11022 if (adjacent_cells[2 * face_index].first ==
11024 adjacent_cells[2 * face_index].second ==
11026 {
11027 index = 2 * face_index + 0;
11028 }
11029 else
11030 {
11031 Assert(((adjacent_cells[2 * face_index + 1].first ==
11033 (adjacent_cells[2 * face_index + 1].second ==
11036 index = 2 * face_index + 1;
11037 }
11038
11039 adjacent_cells[index] = cell_pair;
11040 };
11041
11042 const auto get_entry =
11043 [&](const auto &face_index,
11044 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11045 auto test = adjacent_cells[2 * face_index];
11046
11047 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11048 cell->index()))
11049 test = adjacent_cells[2 * face_index + 1];
11050
11051 if ((test.first != numbers::invalid_unsigned_int) &&
11052 (test.second != numbers::invalid_unsigned_int))
11054 test.first,
11055 test.second);
11056 else
11058 };
11059
11060 for (const auto &cell : triangulation.cell_iterators())
11061 for (const auto &face : cell->face_iterators())
11062 {
11063 set_entry(face->index(), cell);
11064
11065 if (cell->is_active() && face->has_children())
11066 for (unsigned int c = 0; c < face->n_children(); ++c)
11067 set_entry(face->child(c)->index(), cell);
11068 }
11069
11070 for (const auto &cell : triangulation.cell_iterators())
11071 for (auto f : cell->face_indices())
11072 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11073 }
11074
11075 template <int dim, int spacedim>
11076 static void
11080 std::vector<unsigned int> & line_cell_count,
11081 std::vector<unsigned int> & quad_cell_count)
11082 {
11084 (void)triangulation;
11085 (void)cell;
11086 (void)line_cell_count;
11087 (void)quad_cell_count;
11088 }
11089
11090 template <int dim, int spacedim>
11093 const bool check_for_distorted_cells)
11094 {
11095 return Implementation::execute_refinement_isotropic(
11096 triangulation, check_for_distorted_cells);
11097 }
11098
11099 template <int dim, int spacedim>
11100 static void
11103 {
11104 // nothing to do since anisotropy is not supported
11105 (void)triangulation;
11106 }
11107
11108 template <int dim, int spacedim>
11109 static void
11112 {
11113 Implementation::prepare_refinement_dim_dependent(triangulation);
11114 }
11115
11116 template <int dim, int spacedim>
11117 static bool
11120 {
11122 (void)cell;
11123
11124 return false;
11125 }
11126 };
11127
11128
11129 template <int dim, int spacedim>
11132 {
11133 static const FlatManifold<dim, spacedim> flat_manifold;
11134 return flat_manifold;
11135 }
11136 } // namespace TriangulationImplementation
11137} // namespace internal
11138
11139
11140
11141template <int dim, int spacedim>
11143
11144
11145
11146template <int dim, int spacedim>
11148 const MeshSmoothing smooth_grid,
11149 const bool check_for_distorted_cells)
11150 : smooth_grid(smooth_grid)
11151 , anisotropic_refinement(false)
11152 , check_for_distorted_cells(check_for_distorted_cells)
11153{
11154 if (dim == 1)
11155 {
11156 vertex_to_boundary_id_map_1d =
11157 std::make_unique<std::map<unsigned int, types::boundary_id>>();
11158 vertex_to_manifold_id_map_1d =
11159 std::make_unique<std::map<unsigned int, types::manifold_id>>();
11160 }
11161
11162 // connect the any_change signal to the other top level signals
11163 signals.create.connect(signals.any_change);
11164 signals.post_refinement.connect(signals.any_change);
11165 signals.clear.connect(signals.any_change);
11166 signals.mesh_movement.connect(signals.any_change);
11167}
11168
11169
11170
11171template <int dim, int spacedim>
11174 : Subscriptor(std::move(tria))
11175 , smooth_grid(tria.smooth_grid)
11176 , reference_cells(std::move(tria.reference_cells))
11177 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
11178 , periodic_face_map(std::move(tria.periodic_face_map))
11179 , levels(std::move(tria.levels))
11180 , faces(std::move(tria.faces))
11181 , vertices(std::move(tria.vertices))
11182 , vertices_used(std::move(tria.vertices_used))
11183 , manifolds(std::move(tria.manifolds))
11184 , anisotropic_refinement(tria.anisotropic_refinement)
11185 , check_for_distorted_cells(tria.check_for_distorted_cells)
11186 , number_cache(std::move(tria.number_cache))
11187 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
11188 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
11189{
11191
11192 if (tria.policy)
11193 this->policy = tria.policy->clone();
11194}
11195
11196
11197template <int dim, int spacedim>
11201{
11202 Subscriptor::operator=(std::move(tria));
11203
11204 smooth_grid = tria.smooth_grid;
11205 reference_cells = std::move(tria.reference_cells);
11206 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
11207 periodic_face_map = std::move(tria.periodic_face_map);
11208 levels = std::move(tria.levels);
11209 faces = std::move(tria.faces);
11210 vertices = std::move(tria.vertices);
11211 vertices_used = std::move(tria.vertices_used);
11212 manifolds = std::move(tria.manifolds);
11213 anisotropic_refinement = tria.anisotropic_refinement;
11214 number_cache = tria.number_cache;
11215 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
11216 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
11217
11219
11220 if (tria.policy)
11221 this->policy = tria.policy->clone();
11222
11223 return *this;
11224}
11225
11226
11227
11228template <int dim, int spacedim>
11230{
11231 // notify listeners that the triangulation is going down...
11232 try
11233 {
11234 signals.clear();
11235 }
11236 catch (...)
11237 {}
11238
11239 levels.clear();
11240
11241 // the vertex_to_boundary_id_map_1d field should be unused except in
11242 // 1d. double check this here, as destruction is a good place to
11243 // ensure that what we've done over the course of the lifetime of
11244 // this object makes sense
11245 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
11247
11248 // the vertex_to_manifold_id_map_1d field should be also unused
11249 // except in 1d. check this as well
11250 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
11252}
11253
11254
11255
11256template <int dim, int spacedim>
11257void
11259{
11260 // notify listeners that the triangulation is going down...
11261 signals.clear();
11262
11263 // ...and then actually clear all content of it
11264 clear_despite_subscriptions();
11265 periodic_face_pairs_level_0.clear();
11266 periodic_face_map.clear();
11267 reference_cells.clear();
11268}
11269
11270
11271template <int dim, int spacedim>
11274{
11275 return MPI_COMM_SELF;
11276}
11277
11278
11279
11280template <int dim, int spacedim>
11281void
11283 const MeshSmoothing mesh_smoothing)
11284{
11285 Assert(n_levels() == 0,
11286 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11287 smooth_grid = mesh_smoothing;
11288}
11289
11290
11291
11292template <int dim, int spacedim>
11295{
11296 return smooth_grid;
11297}
11298
11299
11300
11301template <int dim, int spacedim>
11302void
11304 const types::manifold_id m_number,
11305 const Manifold<dim, spacedim> &manifold_object)
11306{
11308
11309 manifolds[m_number] = manifold_object.clone();
11310}
11311
11312
11313
11314template <int dim, int spacedim>
11315void
11317{
11319
11320 // delete the entry located at number.
11321 manifolds.erase(m_number);
11322}
11323
11324
11325template <int dim, int spacedim>
11326void
11328{
11329 manifolds.clear();
11330}
11331
11332
11333template <int dim, int spacedim>
11334void
11336 const types::manifold_id m_number)
11337{
11338 Assert(
11339 n_cells() > 0,
11340 ExcMessage(
11341 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
11342
11343 for (const auto &cell : this->active_cell_iterators())
11344 cell->set_all_manifold_ids(m_number);
11345}
11346
11347
11348template <int dim, int spacedim>
11349void
11351 const types::manifold_id m_number)
11352{
11353 Assert(
11354 n_cells() > 0,
11355 ExcMessage(
11356 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
11357
11358 for (const auto &cell : this->active_cell_iterators())
11359 for (auto f : GeometryInfo<dim>::face_indices())
11360 if (cell->face(f)->at_boundary())
11361 cell->face(f)->set_all_manifold_ids(m_number);
11362}
11363
11364
11365template <int dim, int spacedim>
11366void
11368 const types::boundary_id b_id,
11369 const types::manifold_id m_number)
11370{
11371 Assert(
11372 n_cells() > 0,
11373 ExcMessage(
11374 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
11375
11376 bool boundary_found = false;
11377
11378 for (const auto &cell : this->active_cell_iterators())
11379 {
11380 // loop on faces
11381 for (auto f : GeometryInfo<dim>::face_indices())
11382 if (cell->face(f)->at_boundary() &&
11383 cell->face(f)->boundary_id() == b_id)
11384 {
11385 boundary_found = true;
11386 cell->face(f)->set_manifold_id(m_number);
11387 }
11388
11389 // loop on edges if dim >= 3
11390 if (dim >= 3)
11391 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
11392 if (cell->line(e)->at_boundary() &&
11393 cell->line(e)->boundary_id() == b_id)
11394 {
11395 boundary_found = true;
11396 cell->line(e)->set_manifold_id(m_number);
11397 }
11398 }
11399
11400 (void)boundary_found;
11401 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
11402}
11403
11404
11405
11406template <int dim, int spacedim>
11409 const types::manifold_id m_number) const
11410{
11411 // look, if there is a manifold stored at
11412 // manifold_id number.
11413 const auto it = manifolds.find(m_number);
11414
11415 if (it != manifolds.end())
11416 {
11417 // if we have found an entry, return it
11418 return *(it->second);
11419 }
11420
11421 // if we have not found an entry connected with number, we return
11422 // the default (flat) manifold
11423 return internal::TriangulationImplementation::
11424 get_default_flat_manifold<dim, spacedim>();
11425}
11426
11427
11428
11429template <int dim, int spacedim>
11430std::vector<types::boundary_id>
11432{
11433 // in 1d, we store a map of all used boundary indicators. use it for
11434 // our purposes
11435 if (dim == 1)
11436 {
11437 std::vector<types::boundary_id> boundary_ids;
11438 for (std::map<unsigned int, types::boundary_id>::const_iterator p =
11439 vertex_to_boundary_id_map_1d->begin();
11440 p != vertex_to_boundary_id_map_1d->end();
11441 ++p)
11442 boundary_ids.push_back(p->second);
11443
11444 return boundary_ids;
11445 }
11446 else
11447 {
11448 std::set<types::boundary_id> b_ids;
11449 for (auto cell : active_cell_iterators())
11450 if (cell->is_locally_owned())
11451 for (const unsigned int face : cell->face_indices())
11452 if (cell->at_boundary(face))
11453 b_ids.insert(cell->face(face)->boundary_id());
11454 std::vector<types::boundary_id> boundary_ids(b_ids.begin(), b_ids.end());
11455 return boundary_ids;
11456 }
11457}
11458
11459
11460
11461template <int dim, int spacedim>
11462std::vector<types::manifold_id>
11464{
11465 std::set<types::manifold_id> m_ids;
11466 for (auto cell : active_cell_iterators())
11467 if (cell->is_locally_owned())
11468 {
11469 m_ids.insert(cell->manifold_id());
11470 for (const auto &face : cell->face_iterators())
11471 m_ids.insert(face->manifold_id());
11472 if (dim == 3)
11473 for (const unsigned int l : cell->line_indices())
11474 m_ids.insert(cell->line(l)->manifold_id());
11475 }
11476 return {m_ids.begin(), m_ids.end()};
11477}
11478
11479/*-----------------------------------------------------------------*/
11480
11481
11482template <int dim, int spacedim>
11483void
11485 const Triangulation<dim, spacedim> &other_tria)
11486{
11487 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
11488 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11489 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
11490 (dim == 1 || other_tria.faces != nullptr),
11491 ExcMessage(
11492 "When calling Triangulation::copy_triangulation(), "
11493 "the target triangulation must be empty but the source "
11494 "triangulation (the argument to this function) must contain "
11495 "something. Here, it seems like the source does not "
11496 "contain anything at all."));
11497
11498
11499 // copy normal elements
11500 vertices = other_tria.vertices;
11501 vertices_used = other_tria.vertices_used;
11502 anisotropic_refinement = other_tria.anisotropic_refinement;
11503 smooth_grid = other_tria.smooth_grid;
11504 reference_cells = other_tria.reference_cells;
11505
11506 if (dim > 1)
11507 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
11508 *other_tria.faces);
11509
11510 for (const auto &p : other_tria.manifolds)
11511 set_manifold(p.first, *p.second);
11512
11513
11514 levels.reserve(other_tria.levels.size());
11515 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
11516 levels.push_back(
11517 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
11518 *other_tria.levels[level]));
11519
11520 number_cache = other_tria.number_cache;
11521
11522 if (dim == 1)
11523 {
11524 vertex_to_boundary_id_map_1d =
11525 std::make_unique<std::map<unsigned int, types::boundary_id>>(
11526 *other_tria.vertex_to_boundary_id_map_1d);
11527
11528 vertex_to_manifold_id_map_1d =
11529 std::make_unique<std::map<unsigned int, types::manifold_id>>(
11530 *other_tria.vertex_to_manifold_id_map_1d);
11531 }
11532
11533 if (other_tria.policy)
11534 this->policy = other_tria.policy->clone();
11535
11536 // inform those who are listening on other_tria of the copy operation
11537 other_tria.signals.copy(*this);
11538 // also inform all listeners of the current triangulation that the
11539 // triangulation has been created
11540 signals.create();
11541
11542 // note that we need not copy the
11543 // subscriptor!
11544}
11545
11546
11547
11548template <int dim, int spacedim>
11549void
11551 const std::vector<Point<spacedim>> &v,
11552 const std::vector<CellData<dim>> & cells,
11553 const SubCellData & subcelldata)
11554{
11555 std::vector<CellData<dim>> reordered_cells(cells); // NOLINT
11556 SubCellData reordered_subcelldata(subcelldata); // NOLINT
11557
11558 // in-place reordering of data
11559 reorder_compatibility(reordered_cells, reordered_subcelldata);
11560
11561 // now create triangulation from
11562 // reordered data
11563 create_triangulation(v, reordered_cells, reordered_subcelldata);
11564}
11565
11566
11567template <int dim, int spacedim>
11568void
11570{
11571 this->update_reference_cells();
11572
11573 if (this->all_reference_cells_are_hyper_cube())
11574 {
11575 this->policy =
11577 dim,
11578 spacedim,
11580 }
11581 else
11582 {
11583 this->policy =
11585 dim,
11586 spacedim,
11588 }
11589}
11590
11591
11592
11593template <int dim, int spacedim>
11594void
11596 const std::vector<Point<spacedim>> &v,
11597 const std::vector<CellData<dim>> & cells,
11598 const SubCellData & subcelldata)
11599{
11600 Assert((vertices.size() == 0) && (levels.size() == 0) && (faces == nullptr),
11601 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
11602 // check that no forbidden arrays
11603 // are used
11604 Assert(subcelldata.check_consistency(dim), ExcInternalError());
11605
11606 // try to create a triangulation; if this fails, we still want to
11607 // throw an exception but if we just do so we'll get into trouble
11608 // because sometimes other objects are already attached to it:
11609 try
11610 {
11612 create_triangulation(v, cells, subcelldata, *this);
11613 }
11614 catch (...)
11615 {
11616 clear_despite_subscriptions();
11617 throw;
11618 }
11619
11620 reset_policy();
11621
11622 // update our counts of the various elements of a triangulation, and set
11623 // active_cell_indices of all cells
11624 reset_cell_vertex_indices_cache();
11626 *this, levels.size(), number_cache);
11627 reset_active_cell_indices();
11628 reset_global_cell_indices();
11629
11630 // now verify that there are indeed no distorted cells. as per the
11631 // documentation of this class, we first collect all distorted cells
11632 // and then throw an exception if there are any
11633 if (check_for_distorted_cells)
11634 {
11635 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
11636 // throw the array (and fill the various location fields) if
11637 // there are distorted cells. otherwise, just fall off the end
11638 // of the function
11639 AssertThrow(distorted_cells.distorted_cells.size() == 0, distorted_cells);
11640 }
11641
11642
11643 /*
11644 When the triangulation is a manifold (dim < spacedim) and made of
11645 quadrilaterals, the normal field provided from the map class depends on
11646 the order of the vertices. It may happen that this normal field is
11647 discontinuous. The following code takes care that this is not the case by
11648 setting the cell direction flag on those cell that produce the wrong
11649 orientation.
11650
11651 To determine if 2 neighbours have the same or opposite orientation we use
11652 a table of truth. Its entries are indexes by the local indices of the
11653 common face. For example if two elements share a face, and this face is
11654 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
11655 whether the orientation are the same (true) or opposite (false).
11656
11657 Even though there may be a combinatorial/graph theory argument to get this
11658 table in any dimension, I tested by hand all the different possible cases
11659 in 1D and 2D to generate the table.
11660
11661 Assuming that a surface respects the standard orientation for 2d meshes,
11662 the tables of truth are symmetric and their true values are the following
11663
11664 - 1D curves: (0,1)
11665 - 2D surface: (0,1),(0,2),(1,3),(2,3)
11666
11667 We store this data using an n_faces x n_faces full matrix, which is
11668 actually much bigger than the minimal data required, but it makes the code
11669 more readable.
11670
11671 */
11672 if (dim < spacedim && all_reference_cells_are_hyper_cube())
11673 {
11676 switch (dim)
11677 {
11678 case 1:
11679 {
11680 bool values[][2] = {{false, true}, {true, false}};
11681 for (const unsigned int i : GeometryInfo<dim>::face_indices())
11682 for (const unsigned int j : GeometryInfo<dim>::face_indices())
11683 correct(i, j) = (values[i][j]);
11684 break;
11685 }
11686 case 2:
11687 {
11688 bool values[][4] = {{false, true, true, false},
11689 {true, false, false, true},
11690 {true, false, false, true},
11691 {false, true, true, false}};
11692 for (const unsigned int i : GeometryInfo<dim>::face_indices())
11693 for (const unsigned int j : GeometryInfo<dim>::face_indices())
11694 correct(i, j) = (values[i][j]);
11695 break;
11696 }
11697 default:
11698 Assert(false, ExcNotImplemented());
11699 }
11700
11701
11702 std::list<active_cell_iterator> this_round, next_round;
11703 active_cell_iterator neighbor;
11704
11705 this_round.push_back(begin_active());
11706 begin_active()->set_direction_flag(true);
11707 begin_active()->set_user_flag();
11708
11709 while (this_round.size() > 0)
11710 {
11711 for (typename std::list<active_cell_iterator>::iterator cell =
11712 this_round.begin();
11713 cell != this_round.end();
11714 ++cell)
11715 {
11716 for (const unsigned int i : (*cell)->face_indices())
11717 {
11718 if (!((*cell)->face(i)->at_boundary()))
11719 {
11720 neighbor = (*cell)->neighbor(i);
11721
11722 unsigned int cf = (*cell)->face_index(i);
11723 unsigned int j = 0;
11724 while (neighbor->face_index(j) != cf)
11725 {
11726 ++j;
11727 }
11728
11729
11730 // If we already saw this guy, check that everything is
11731 // fine
11732 if (neighbor->user_flag_set())
11733 {
11734 // If we have visited this guy, then the ordering and
11735 // the orientation should agree
11736 Assert(!(correct(i, j) ^
11737 (neighbor->direction_flag() ==
11738 (*cell)->direction_flag())),
11739 ExcNonOrientableTriangulation());
11740 }
11741 else
11742 {
11743 next_round.push_back(neighbor);
11744 neighbor->set_user_flag();
11745 if ((correct(i, j) ^ (neighbor->direction_flag() ==
11746 (*cell)->direction_flag())))
11747 neighbor->set_direction_flag(
11748 !neighbor->direction_flag());
11749 }
11750 }
11751 }
11752 }
11753
11754 // Before we quit let's check
11755 // that if the triangulation
11756 // is disconnected that we
11757 // still get all cells
11758 if (next_round.size() == 0)
11759 for (const auto &cell : this->active_cell_iterators())
11760 if (cell->user_flag_set() == false)
11761 {
11762 next_round.push_back(cell);
11763 cell->set_direction_flag(true);
11764 cell->set_user_flag();
11765 break;
11766 }
11767
11768 this_round = next_round;
11769 next_round.clear();
11770 }
11771 }
11772
11773 // inform all listeners that the triangulation has been created
11774 signals.create();
11775}
11776
11777
11778
11779template <int dim, int spacedim>
11780void
11783{
11784 // 1) create coarse grid
11786 construction_data.coarse_cells,
11787 SubCellData());
11788
11789 // create a copy of cell_infos such that we can sort them
11790 auto cell_infos = construction_data.cell_infos;
11791
11792 // sort cell_infos on each level separately
11793 for (auto &cell_info : cell_infos)
11794 std::sort(
11795 cell_info.begin(),
11796 cell_info.end(),
11799 const CellId a_id(a.id);
11800 const CellId b_id(b.id);
11801
11802 const auto a_coarse_cell_index =
11803 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
11804 const auto b_coarse_cell_index =
11805 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
11806
11807 // according to their coarse-cell index and if that is
11808 // same according to their cell id (the result is that
11809 // cells on each level are sorted according to their
11810 // index on that level - what we need in the following
11811 // operations)
11812 if (a_coarse_cell_index != b_coarse_cell_index)
11813 return a_coarse_cell_index < b_coarse_cell_index;
11814 else
11815 return a_id < b_id;
11816 });
11817
11818 // 2) create all levels via a sequence of refinements. note that
11819 // we must make sure that we actually have cells on this level,
11820 // which is not clear in a parallel context for some processes
11821 for (unsigned int level = 0;
11822 level < cell_infos.size() && !cell_infos[level].empty();
11823 ++level)
11824 {
11825 // a) set manifold ids here (because new vertices have to be
11826 // positioned correctly during each refinement step)
11827 {
11828 auto cell = this->begin(level);
11829 auto cell_info = cell_infos[level].begin();
11830 for (; cell_info != cell_infos[level].end(); ++cell_info)
11831 {
11832 while (cell_info->id != cell->id().template to_binary<dim>())
11833 ++cell;
11834 if (dim == 3)
11835 for (const auto quad : cell->face_indices())
11836 cell->quad(quad)->set_manifold_id(
11837 cell_info->manifold_quad_ids[quad]);
11838
11839 if (dim >= 2)
11840 for (const auto line : cell->line_indices())
11841 cell->line(line)->set_manifold_id(
11842 cell_info->manifold_line_ids[line]);
11843
11844 cell->set_manifold_id(cell_info->manifold_id);
11845 }
11846 }
11847
11848 // b) perform refinement on all levels but on the finest
11849 if (level + 1 != cell_infos.size())
11850 {
11851 // find cells that should have children and mark them for
11852 // refinement
11853 auto coarse_cell = this->begin(level);
11854 auto fine_cell_info = cell_infos[level + 1].begin();
11855
11856 // loop over all cells on the next level
11857 for (; fine_cell_info != cell_infos[level + 1].end();
11858 ++fine_cell_info)
11859 {
11860 // find the parent of that cell
11861 while (
11862 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
11863 ++coarse_cell;
11864
11865 // set parent for refinement
11866 coarse_cell->set_refine_flag();
11867 }
11868
11869 // execute refinement
11870 ::Triangulation<dim,
11871 spacedim>::execute_coarsening_and_refinement();
11872 }
11873 }
11874
11875 // 3) set boundary ids
11876 for (unsigned int level = 0;
11877 level < cell_infos.size() && !cell_infos[level].empty();
11878 ++level)
11879 {
11880 auto cell = this->begin(level);
11881 auto cell_info = cell_infos[level].begin();
11882 for (; cell_info != cell_infos[level].end(); ++cell_info)
11883 {
11884 // find cell that has the correct cell
11885 while (cell_info->id != cell->id().template to_binary<dim>())
11886 ++cell;
11887
11888 // boundary ids
11889 for (auto pair : cell_info->boundary_ids)
11890 if (cell->face(pair.first)->at_boundary())
11891 cell->face(pair.first)->set_boundary_id(pair.second);
11892 }
11893 }
11894}
11895
11896
11897template <int dim, int spacedim>
11898void
11900{
11901 AssertThrow(dim + 1 == spacedim,
11902 ExcMessage("Only works for dim == spacedim-1"));
11903 for (const auto &cell : this->active_cell_iterators())
11904 cell->set_direction_flag(!cell->direction_flag());
11905}
11906
11907
11908
11909template <int dim, int spacedim>
11910void
11912{
11913 Assert(n_cells() > 0,
11914 ExcMessage("Error: An empty Triangulation can not be refined."));
11915
11916 for (const auto &cell : this->active_cell_iterators())
11917 {
11918 cell->clear_coarsen_flag();
11919 cell->set_refine_flag();
11920 }
11921}
11922
11923
11924
11925template <int dim, int spacedim>
11926void
11927Triangulation<dim, spacedim>::refine_global(const unsigned int times)
11928{
11929 for (unsigned int i = 0; i < times; ++i)
11930 {
11931 set_all_refine_flags();
11932 execute_coarsening_and_refinement();
11933 }
11934}
11935
11936
11937
11938template <int dim, int spacedim>
11939void
11940Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
11941{
11942 for (unsigned int i = 0; i < times; ++i)
11943 {
11944 for (const auto &cell : this->active_cell_iterators())
11945 {
11946 cell->clear_refine_flag();
11947 cell->set_coarsen_flag();
11948 }
11949 execute_coarsening_and_refinement();
11950 }
11951}
11952
11953
11954/*-------------------- refine/coarsen flags -------------------------*/
11955
11956
11957
11958template <int dim, int spacedim>
11959void
11960Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
11961{
11962 v.resize(dim * n_active_cells(), false);
11963 std::vector<bool>::iterator i = v.begin();
11964
11965 for (const auto &cell : this->active_cell_iterators())
11966 for (unsigned int j = 0; j < dim; ++j, ++i)
11967 if (cell->refine_flag_set() & (1 << j))
11968 *i = true;
11969
11970 Assert(i == v.end(), ExcInternalError());
11971}
11972
11973
11974
11975template <int dim, int spacedim>
11976void
11978{
11979 std::vector<bool> v;
11980 save_refine_flags(v);
11981 write_bool_vector(mn_tria_refine_flags_begin,
11982 v,
11984 out);
11985}
11986
11987
11988
11989template <int dim, int spacedim>
11990void
11992{
11993 std::vector<bool> v;
11994 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
11995 load_refine_flags(v);
11996}
11997
11998
11999
12000template <int dim, int spacedim>
12001void
12002Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12003{
12004 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12005
12006 std::vector<bool>::const_iterator i = v.begin();
12007 for (const auto &cell : this->active_cell_iterators())
12008 {
12009 unsigned int ref_case = 0;
12010
12011 for (unsigned int j = 0; j < dim; ++j, ++i)
12012 if (*i == true)
12013 ref_case += 1 << j;
12015 ExcGridReadError());
12016 if (ref_case > 0)
12017 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12018 else
12019 cell->clear_refine_flag();
12020 }
12021
12022 Assert(i == v.end(), ExcInternalError());
12023}
12024
12025
12026
12027template <int dim, int spacedim>
12028void
12029Triangulation<dim, spacedim>::save_coarsen_flags(std::vector<bool> &v) const
12030{
12031 v.resize(n_active_cells(), false);
12032 std::vector<bool>::iterator i = v.begin();
12033 for (const auto &cell : this->active_cell_iterators())
12034 {
12035 *i = cell->coarsen_flag_set();
12036 ++i;
12037 }
12038
12039 Assert(i == v.end(), ExcInternalError());
12040}
12041
12042
12043
12044template <int dim, int spacedim>
12045void
12047{
12048 std::vector<bool> v;
12049 save_coarsen_flags(v);
12050 write_bool_vector(mn_tria_coarsen_flags_begin,
12051 v,
12053 out);
12054}
12055
12056
12057
12058template <int dim, int spacedim>
12059void
12061{
12062 std::vector<bool> v;
12063 read_bool_vector(mn_tria_coarsen_flags_begin,
12064 v,
12066 in);
12067 load_coarsen_flags(v);
12068}
12069
12070
12071
12072template <int dim, int spacedim>
12073void
12074Triangulation<dim, spacedim>::load_coarsen_flags(const std::vector<bool> &v)
12075{
12076 Assert(v.size() == n_active_cells(), ExcGridReadError());
12077
12078 std::vector<bool>::const_iterator i = v.begin();
12079 for (const auto &cell : this->active_cell_iterators())
12080 {
12081 if (*i == true)
12082 cell->set_coarsen_flag();
12083 else
12084 cell->clear_coarsen_flag();
12085 ++i;
12086 }
12087
12088 Assert(i == v.end(), ExcInternalError());
12089}
12090
12091
12092template <int dim, int spacedim>
12093bool
12095{
12096 return anisotropic_refinement;
12097}
12098
12099
12100
12101/*-------------------- user data/flags -------------------------*/
12102
12103
12104namespace
12105{
12106 // clear user data of cells
12107 void
12108 clear_user_data(std::vector<std::unique_ptr<
12110 {
12111 for (auto &level : levels)
12112 level->cells.clear_user_data();
12113 }
12114
12115
12116 // clear user data of faces
12117 void
12119 {
12120 if (faces->dim == 2)
12121 {
12122 faces->lines.clear_user_data();
12123 }
12124
12125
12126 if (faces->dim == 3)
12127 {
12128 faces->lines.clear_user_data();
12129 faces->quads.clear_user_data();
12130 }
12131 }
12132} // namespace
12133
12134
12135template <int dim, int spacedim>
12136void
12138{
12139 // let functions in anonymous namespace do their work
12140 ::clear_user_data(levels);
12141 if (dim > 1)
12142 ::clear_user_data(faces.get());
12143}
12144
12145
12146
12147namespace
12148{
12149 void
12150 clear_user_flags_line(
12151 unsigned int dim,
12152 std::vector<
12153 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12154 & levels,
12156 {
12157 if (dim == 1)
12158 {
12159 for (const auto &level : levels)
12160 level->cells.clear_user_flags();
12161 }
12162 else if (dim == 2 || dim == 3)
12163 {
12164 faces->lines.clear_user_flags();
12165 }
12166 else
12167 {
12168 Assert(false, ExcNotImplemented())
12169 }
12170 }
12171} // namespace
12172
12173
12174template <int dim, int spacedim>
12175void
12177{
12178 ::clear_user_flags_line(dim, levels, faces.get());
12179}
12180
12181
12182
12183namespace
12184{
12185 void
12186 clear_user_flags_quad(
12187 unsigned int dim,
12188 std::vector<
12189 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12190 & levels,
12192 {
12193 if (dim == 1)
12194 {
12195 // nothing to do in 1d
12196 }
12197 else if (dim == 2)
12198 {
12199 for (const auto &level : levels)
12200 level->cells.clear_user_flags();
12201 }
12202 else if (dim == 3)
12203 {
12204 faces->quads.clear_user_flags();
12205 }
12206 else
12207 {
12208 Assert(false, ExcNotImplemented())
12209 }
12210 }
12211} // namespace
12212
12213
12214template <int dim, int spacedim>
12215void
12217{
12218 ::clear_user_flags_quad(dim, levels, faces.get());
12219}
12220
12221
12222
12223namespace
12224{
12225 void
12226 clear_user_flags_hex(
12227 unsigned int dim,
12228 std::vector<
12229 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
12230 &levels,
12232 {
12233 if (dim == 1)
12234 {
12235 // nothing to do in 1d
12236 }
12237 else if (dim == 2)
12238 {
12239 // nothing to do in 2d
12240 }
12241 else if (dim == 3)
12242 {
12243 for (const auto &level : levels)
12244 level->cells.clear_user_flags();
12245 }
12246 else
12247 {
12248 Assert(false, ExcNotImplemented())
12249 }
12250 }
12251} // namespace
12252
12253
12254template <int dim, int spacedim>
12255void
12257{
12258 ::clear_user_flags_hex(dim, levels, faces.get());
12259}
12260
12261
12262
12263template <int dim, int spacedim>
12264void
12266{
12267 clear_user_flags_line();
12268 clear_user_flags_quad();
12269 clear_user_flags_hex();
12270}
12271
12272
12273
12274template <int dim, int spacedim>
12275void
12276Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
12277{
12278 save_user_flags_line(out);
12279
12280 if (dim >= 2)
12281 save_user_flags_quad(out);
12282
12283 if (dim >= 3)
12284 save_user_flags_hex(out);
12285
12286 if (dim >= 4)
12287 Assert(false, ExcNotImplemented());
12288}
12289
12290
12291
12292template <int dim, int spacedim>
12293void
12294Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
12295{
12296 // clear vector and append
12297 // all the stuff later on
12298 v.clear();
12299
12300 std::vector<bool> tmp;
12301
12302 save_user_flags_line(tmp);
12303 v.insert(v.end(), tmp.begin(), tmp.end());
12304
12305 if (dim >= 2)
12306 {
12307 save_user_flags_quad(tmp);
12308 v.insert(v.end(), tmp.begin(), tmp.end());
12309 }
12310
12311 if (dim >= 3)
12312 {
12313 save_user_flags_hex(tmp);
12314 v.insert(v.end(), tmp.begin(), tmp.end());
12315 }
12316
12317 if (dim >= 4)
12318 Assert(false, ExcNotImplemented());
12319}
12320
12321
12322
12323template <int dim, int spacedim>
12324void
12326{
12327 load_user_flags_line(in);
12328
12329 if (dim >= 2)
12330 load_user_flags_quad(in);
12331
12332 if (dim >= 3)
12333 load_user_flags_hex(in);
12334
12335 if (dim >= 4)
12336 Assert(false, ExcNotImplemented());
12337}
12338
12339
12340
12341template <int dim, int spacedim>
12342void
12343Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
12344{
12345 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12346 std::vector<bool> tmp;
12347
12348 // first extract the flags
12349 // belonging to lines
12350 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12351 // and set the lines
12352 load_user_flags_line(tmp);
12353
12354 if (dim >= 2)
12355 {
12356 tmp.clear();
12357 tmp.insert(tmp.end(),
12358 v.begin() + n_lines(),
12359 v.begin() + n_lines() + n_quads());
12360 load_user_flags_quad(tmp);
12361 }
12362
12363 if (dim >= 3)
12364 {
12365 tmp.clear();
12366 tmp.insert(tmp.end(),
12367 v.begin() + n_lines() + n_quads(),
12368 v.begin() + n_lines() + n_quads() + n_hexs());
12369 load_user_flags_hex(tmp);
12370 }
12371
12372 if (dim >= 4)
12373 Assert(false, ExcNotImplemented());
12374}
12375
12376
12377
12378template <int dim, int spacedim>
12379void
12381{
12382 v.resize(n_lines(), false);
12383 std::vector<bool>::iterator i = v.begin();
12384 line_iterator line = begin_line(), endl = end_line();
12385 for (; line != endl; ++line, ++i)
12386 *i = line->user_flag_set();
12387
12388 Assert(i == v.end(), ExcInternalError());
12389}
12390
12391
12392
12393template <int dim, int spacedim>
12394void
12396{
12397 std::vector<bool> v;
12398 save_user_flags_line(v);
12399 write_bool_vector(mn_tria_line_user_flags_begin,
12400 v,
12402 out);
12403}
12404
12405
12406
12407template <int dim, int spacedim>
12408void
12410{
12411 std::vector<bool> v;
12412 read_bool_vector(mn_tria_line_user_flags_begin,
12413 v,
12415 in);
12416 load_user_flags_line(v);
12417}
12418
12419
12420
12421template <int dim, int spacedim>
12422void
12424{
12425 Assert(v.size() == n_lines(), ExcGridReadError());
12426
12427 line_iterator line = begin_line(), endl = end_line();
12428 std::vector<bool>::const_iterator i = v.begin();
12429 for (; line != endl; ++line, ++i)
12430 if (*i == true)
12431 line->set_user_flag();
12432 else
12433 line->clear_user_flag();
12434
12435 Assert(i == v.end(), ExcInternalError());
12436}
12437
12438
12439namespace
12440{
12441 template <typename Iterator>
12442 bool
12443 get_user_flag(const Iterator &i)
12444 {
12445 return i->user_flag_set();
12446 }
12447
12448
12449
12450 template <int structdim, int dim, int spacedim>
12451 bool
12453 {
12454 Assert(false, ExcInternalError());
12455 return false;
12456 }
12457
12458
12459
12460 template <typename Iterator>
12461 void
12462 set_user_flag(const Iterator &i)
12463 {
12464 i->set_user_flag();
12465 }
12466
12467
12468
12469 template <int structdim, int dim, int spacedim>
12470 void
12472 {
12473 Assert(false, ExcInternalError());
12474 }
12475
12476
12477
12478 template <typename Iterator>
12479 void
12480 clear_user_flag(const Iterator &i)
12481 {
12482 i->clear_user_flag();
12483 }
12484
12485
12486
12487 template <int structdim, int dim, int spacedim>
12488 void
12489 clear_user_flag(
12491 {
12492 Assert(false, ExcInternalError());
12493 }
12494} // namespace
12495
12496
12497template <int dim, int spacedim>
12498void
12500{
12501 v.resize(n_quads(), false);
12502
12503 if (dim >= 2)
12504 {
12505 std::vector<bool>::iterator i = v.begin();
12506 quad_iterator quad = begin_quad(), endq = end_quad();
12507 for (; quad != endq; ++quad, ++i)
12508 *i = get_user_flag(quad);
12509
12510 Assert(i == v.end(), ExcInternalError());
12511 }
12512}
12513
12514
12515
12516template <int dim, int spacedim>
12517void
12519{
12520 std::vector<bool> v;
12521 save_user_flags_quad(v);
12522 write_bool_vector(mn_tria_quad_user_flags_begin,
12523 v,
12525 out);
12526}
12527
12528
12529
12530template <int dim, int spacedim>
12531void
12533{
12534 std::vector<bool> v;
12535 read_bool_vector(mn_tria_quad_user_flags_begin,
12536 v,
12538 in);
12539 load_user_flags_quad(v);
12540}
12541
12542
12543
12544template <int dim, int spacedim>
12545void
12547{
12548 Assert(v.size() == n_quads(), ExcGridReadError());
12549
12550 if (dim >= 2)
12551 {
12552 quad_iterator quad = begin_quad(), endq = end_quad();
12553 std::vector<bool>::const_iterator i = v.begin();
12554 for (; quad != endq; ++quad, ++i)
12555 if (*i == true)
12556 set_user_flag(quad);
12557 else
12558 clear_user_flag(quad);
12559
12560 Assert(i == v.end(), ExcInternalError());
12561 }
12562}
12563
12564
12565
12566template <int dim, int spacedim>
12567void
12568Triangulation<dim, spacedim>::save_user_flags_hex(std::vector<bool> &v) const
12569{
12570 v.resize(n_hexs(), false);
12571
12572 if (dim >= 3)
12573 {
12574 std::vector<bool>::iterator i = v.begin();
12575 hex_iterator hex = begin_hex(), endh = end_hex();
12576 for (; hex != endh; ++hex, ++i)
12577 *i = get_user_flag(hex);
12578
12579 Assert(i == v.end(), ExcInternalError());
12580 }
12581}
12582
12583
12584
12585template <int dim, int spacedim>
12586void
12588{
12589 std::vector<bool> v;
12590 save_user_flags_hex(v);
12591 write_bool_vector(mn_tria_hex_user_flags_begin,
12592 v,
12594 out);
12595}
12596
12597
12598
12599template <int dim, int spacedim>
12600void
12602{
12603 std::vector<bool> v;
12604 read_bool_vector(mn_tria_hex_user_flags_begin,
12605 v,
12607 in);
12608 load_user_flags_hex(v);
12609}
12610
12611
12612
12613template <int dim, int spacedim>
12614void
12615Triangulation<dim, spacedim>::load_user_flags_hex(const std::vector<bool> &v)
12616{
12617 Assert(v.size() == n_hexs(), ExcGridReadError());
12618
12619 if (dim >= 3)
12620 {
12621 hex_iterator hex = begin_hex(), endh = end_hex();
12622 std::vector<bool>::const_iterator i = v.begin();
12623 for (; hex != endh; ++hex, ++i)
12624 if (*i == true)
12625 set_user_flag(hex);
12626 else
12627 clear_user_flag(hex);
12628
12629 Assert(i == v.end(), ExcInternalError());
12630 }
12631}
12632
12633
12634
12635template <int dim, int spacedim>
12636void
12638 std::vector<unsigned int> &v) const
12639{
12640 // clear vector and append all the
12641 // stuff later on
12642 v.clear();
12643
12644 std::vector<unsigned int> tmp;
12645
12646 save_user_indices_line(tmp);
12647 v.insert(v.end(), tmp.begin(), tmp.end());
12648
12649 if (dim >= 2)
12650 {
12651 save_user_indices_quad(tmp);
12652 v.insert(v.end(), tmp.begin(), tmp.end());
12653 }
12654
12655 if (dim >= 3)
12656 {
12657 save_user_indices_hex(tmp);
12658 v.insert(v.end(), tmp.begin(), tmp.end());
12659 }
12660
12661 if (dim >= 4)
12662 Assert(false, ExcNotImplemented());
12663}
12664
12665
12666
12667template <int dim, int spacedim>
12668void
12670 const std::vector<unsigned int> &v)
12671{
12672 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12673 std::vector<unsigned int> tmp;
12674
12675 // first extract the indices
12676 // belonging to lines
12677 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12678 // and set the lines
12679 load_user_indices_line(tmp);
12680
12681 if (dim >= 2)
12682 {
12683 tmp.clear();
12684 tmp.insert(tmp.end(),
12685 v.begin() + n_lines(),
12686 v.begin() + n_lines() + n_quads());
12687 load_user_indices_quad(tmp);
12688 }
12689
12690 if (dim >= 3)
12691 {
12692 tmp.clear();
12693 tmp.insert(tmp.end(),
12694 v.begin() + n_lines() + n_quads(),
12695 v.begin() + n_lines() + n_quads() + n_hexs());
12696 load_user_indices_hex(tmp);
12697 }
12698
12699 if (dim >= 4)
12700 Assert(false, ExcNotImplemented());
12701}
12702
12703
12704
12705namespace
12706{
12707 template <typename Iterator>
12708 unsigned int
12709 get_user_index(const Iterator &i)
12710 {
12711 return i->user_index();
12712 }
12713
12714
12715
12716 template <int structdim, int dim, int spacedim>
12717 unsigned int
12718 get_user_index(
12720 {
12721 Assert(false, ExcInternalError());
12723 }
12724
12725
12726
12727 template <typename Iterator>
12728 void
12729 set_user_index(const Iterator &i, const unsigned int x)
12730 {
12731 i->set_user_index(x);
12732 }
12733
12734
12735
12736 template <int structdim, int dim, int spacedim>
12737 void
12738 set_user_index(
12740 const unsigned int)
12741 {
12742 Assert(false, ExcInternalError());
12743 }
12744} // namespace
12745
12746
12747template <int dim, int spacedim>
12748void
12750 std::vector<unsigned int> &v) const
12751{
12752 v.resize(n_lines(), 0);
12753 std::vector<unsigned int>::iterator i = v.begin();
12754 line_iterator line = begin_line(), endl = end_line();
12755 for (; line != endl; ++line, ++i)
12756 *i = line->user_index();
12757}
12758
12759
12760
12761template <int dim, int spacedim>
12762void
12764 const std::vector<unsigned int> &v)
12765{
12766 Assert(v.size() == n_lines(), ExcGridReadError());
12767
12768 line_iterator line = begin_line(), endl = end_line();
12769 std::vector<unsigned int>::const_iterator i = v.begin();
12770 for (; line != endl; ++line, ++i)
12771 line->set_user_index(*i);
12772}
12773
12774
12775template <int dim, int spacedim>
12776void
12778 std::vector<unsigned int> &v) const
12779{
12780 v.resize(n_quads(), 0);
12781
12782 if (dim >= 2)
12783 {
12784 std::vector<unsigned int>::iterator i = v.begin();
12785 quad_iterator quad = begin_quad(), endq = end_quad();
12786 for (; quad != endq; ++quad, ++i)
12787 *i = get_user_index(quad);
12788 }
12789}
12790
12791
12792
12793template <int dim, int spacedim>
12794void
12796 const std::vector<unsigned int> &v)
12797{
12798 Assert(v.size() == n_quads(), ExcGridReadError());
12799
12800 if (dim >= 2)
12801 {
12802 quad_iterator quad = begin_quad(), endq = end_quad();
12803 std::vector<unsigned int>::const_iterator i = v.begin();
12804 for (; quad != endq; ++quad, ++i)
12805 set_user_index(quad, *i);
12806 }
12807}
12808
12809
12810template <int dim, int spacedim>
12811void
12813 std::vector<unsigned int> &v) const
12814{
12815 v.resize(n_hexs(), 0);
12816
12817 if (dim >= 3)
12818 {
12819 std::vector<unsigned int>::iterator i = v.begin();
12820 hex_iterator hex = begin_hex(), endh = end_hex();
12821 for (; hex != endh; ++hex, ++i)
12822 *i = get_user_index(hex);
12823 }
12824}
12825
12826
12827
12828template <int dim, int spacedim>
12829void
12831 const std::vector<unsigned int> &v)
12832{
12833 Assert(v.size() == n_hexs(), ExcGridReadError());
12834
12835 if (dim >= 3)
12836 {
12837 hex_iterator hex = begin_hex(), endh = end_hex();
12838 std::vector<unsigned int>::const_iterator i = v.begin();
12839 for (; hex != endh; ++hex, ++i)
12840 set_user_index(hex, *i);
12841 }
12842}
12843
12844
12845
12846//---------------- user pointers ----------------------------------------//
12847
12848
12849namespace
12850{
12851 template <typename Iterator>
12852 void *
12853 get_user_pointer(const Iterator &i)
12854 {
12855 return i->user_pointer();
12856 }
12857
12858
12859
12860 template <int structdim, int dim, int spacedim>
12861 void *
12862 get_user_pointer(
12864 {
12865 Assert(false, ExcInternalError());
12866 return nullptr;
12867 }
12868
12869
12870
12871 template <typename Iterator>
12872 void
12873 set_user_pointer(const Iterator &i, void *x)
12874 {
12875 i->set_user_pointer(x);
12876 }
12877
12878
12879
12880 template <int structdim, int dim, int spacedim>
12881 void
12882 set_user_pointer(
12884 void *)
12885 {
12886 Assert(false, ExcInternalError());
12887 }
12888} // namespace
12889
12890
12891template <int dim, int spacedim>
12892void
12893Triangulation<dim, spacedim>::save_user_pointers(std::vector<void *> &v) const
12894{
12895 // clear vector and append all the
12896 // stuff later on
12897 v.clear();
12898
12899 std::vector<void *> tmp;
12900
12901 save_user_pointers_line(tmp);
12902 v.insert(v.end(), tmp.begin(), tmp.end());
12903
12904 if (dim >= 2)
12905 {
12906 save_user_pointers_quad(tmp);
12907 v.insert(v.end(), tmp.begin(), tmp.end());
12908 }
12909
12910 if (dim >= 3)
12911 {
12912 save_user_pointers_hex(tmp);
12913 v.insert(v.end(), tmp.begin(), tmp.end());
12914 }
12915
12916 if (dim >= 4)
12917 Assert(false, ExcNotImplemented());
12918}
12919
12920
12921
12922template <int dim, int spacedim>
12923void
12924Triangulation<dim, spacedim>::load_user_pointers(const std::vector<void *> &v)
12925{
12926 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
12927 std::vector<void *> tmp;
12928
12929 // first extract the pointers
12930 // belonging to lines
12931 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
12932 // and set the lines
12933 load_user_pointers_line(tmp);
12934
12935 if (dim >= 2)
12936 {
12937 tmp.clear();
12938 tmp.insert(tmp.end(),
12939 v.begin() + n_lines(),
12940 v.begin() + n_lines() + n_quads());
12941 load_user_pointers_quad(tmp);
12942 }
12943
12944 if (dim >= 3)
12945 {
12946 tmp.clear();
12947 tmp.insert(tmp.end(),
12948 v.begin() + n_lines() + n_quads(),
12949 v.begin() + n_lines() + n_quads() + n_hexs());
12950 load_user_pointers_hex(tmp);
12951 }
12952
12953 if (dim >= 4)
12954 Assert(false, ExcNotImplemented());
12955}
12956
12957
12958
12959template <int dim, int spacedim>
12960void
12962 std::vector<void *> &v) const
12963{
12964 v.resize(n_lines(), nullptr);
12965 std::vector<void *>::iterator i = v.begin();
12966 line_iterator line = begin_line(), endl = end_line();
12967 for (; line != endl; ++line, ++i)
12968 *i = line->user_pointer();
12969}
12970
12971
12972
12973template <int dim, int spacedim>
12974void
12976 const std::vector<void *> &v)
12977{
12978 Assert(v.size() == n_lines(), ExcGridReadError());
12979
12980 line_iterator line = begin_line(), endl = end_line();
12981 std::vector<void *>::const_iterator i = v.begin();
12982 for (; line != endl; ++line, ++i)
12983 line->set_user_pointer(*i);
12984}
12985
12986
12987
12988template <int dim, int spacedim>
12989void
12991 std::vector<void *> &v) const
12992{
12993 v.resize(n_quads(), nullptr);
12994
12995 if (dim >= 2)
12996 {
12997 std::vector<void *>::iterator i = v.begin();
12998 quad_iterator quad = begin_quad(), endq = end_quad();
12999 for (; quad != endq; ++quad, ++i)
13000 *i = get_user_pointer(quad);
13001 }
13002}
13003
13004
13005
13006template <int dim, int spacedim>
13007void
13009 const std::vector<void *> &v)
13010{
13011 Assert(v.size() == n_quads(), ExcGridReadError());
13012
13013 if (dim >= 2)
13014 {
13015 quad_iterator quad = begin_quad(), endq = end_quad();
13016 std::vector<void *>::const_iterator i = v.begin();
13017 for (; quad != endq; ++quad, ++i)
13018 set_user_pointer(quad, *i);
13019 }
13020}
13021
13022
13023template <int dim, int spacedim>
13024void
13026 std::vector<void *> &v) const
13027{
13028 v.resize(n_hexs(), nullptr);
13029
13030 if (dim >= 3)
13031 {
13032 std::vector<void *>::iterator i = v.begin();
13033 hex_iterator hex = begin_hex(), endh = end_hex();
13034 for (; hex != endh; ++hex, ++i)
13035 *i = get_user_pointer(hex);
13036 }
13037}
13038
13039
13040
13041template <int dim, int spacedim>
13042void
13044 const std::vector<void *> &v)
13045{
13046 Assert(v.size() == n_hexs(), ExcGridReadError());
13047
13048 if (dim >= 3)
13049 {
13050 hex_iterator hex = begin_hex(), endh = end_hex();
13051 std::vector<void *>::const_iterator i = v.begin();
13052 for (; hex != endh; ++hex, ++i)
13053 set_user_pointer(hex, *i);
13054 }
13055}
13056
13057
13058
13059/*------------------------ Cell iterator functions ------------------------*/
13060
13061
13062template <int dim, int spacedim>
13064Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
13065{
13066 switch (dim)
13067 {
13068 case 1:
13069 return begin_raw_line(level);
13070 case 2:
13071 return begin_raw_quad(level);
13072 case 3:
13073 return begin_raw_hex(level);
13074 default:
13075 Assert(false, ExcNotImplemented());
13076 return raw_cell_iterator();
13077 }
13078}
13079
13080
13081
13082template <int dim, int spacedim>
13084Triangulation<dim, spacedim>::begin(const unsigned int level) const
13085{
13086 switch (dim)
13087 {
13088 case 1:
13089 return begin_line(level);
13090 case 2:
13091 return begin_quad(level);
13092 case 3:
13093 return begin_hex(level);
13094 default:
13095 Assert(false, ExcImpossibleInDim(dim));
13096 return cell_iterator();
13097 }
13098}
13099
13100
13101
13102template <int dim, int spacedim>
13104Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
13105{
13106 switch (dim)
13107 {
13108 case 1:
13109 return begin_active_line(level);
13110 case 2:
13111 return begin_active_quad(level);
13112 case 3:
13113 return begin_active_hex(level);
13114 default:
13115 Assert(false, ExcNotImplemented());
13116 return active_cell_iterator();
13117 }
13118}
13119
13120
13121
13122template <int dim, int spacedim>
13125{
13126 const unsigned int level = levels.size() - 1;
13127 if (levels[level]->cells.n_objects() == 0)
13128 return end(level);
13129
13130 // find the last raw iterator on
13131 // this level
13132 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
13133 level,
13134 levels[level]->cells.n_objects() - 1);
13135
13136 // then move to the last used one
13137 if (ri->used() == true)
13138 return ri;
13139 while ((--ri).state() == IteratorState::valid)
13140 if (ri->used() == true)
13141 return ri;
13142 return ri;
13143}
13144
13145
13146
13147template <int dim, int spacedim>
13150{
13151 // get the last used cell
13152 cell_iterator cell = last();
13153
13154 if (cell != end())
13155 {
13156 // then move to the last active one
13157 if (cell->is_active() == true)
13158 return cell;
13159 while ((--cell).state() == IteratorState::valid)
13160 if (cell->is_active() == true)
13161 return cell;
13162 }
13163 return cell;
13164}
13165
13166
13167
13168template <int dim, int spacedim>
13171{
13172 cell_iterator cell(
13173 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
13174
13175 for (const auto &child_index : cell_id.get_child_indices())
13176 {
13177 Assert(
13178 cell->has_children(),
13179 ExcMessage(
13180 "CellId is invalid for this triangulation.\n"
13181 "Either the provided CellId does not correspond to a cell in this "
13182 "triangulation object, or, in case you are using a parallel "
13183 "triangulation, may correspond to an artificial cell that is less "
13184 "refined on this processor."));
13185 cell = cell->child(static_cast<unsigned int>(child_index));
13186 }
13187
13188 return cell;
13189}
13190
13191
13192
13193template <int dim, int spacedim>
13196{
13197 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13198 -1,
13199 -1);
13200}
13201
13202
13203
13204template <int dim, int spacedim>
13206Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
13207{
13208 // This function may be called on parallel triangulations on levels
13209 // that exist globally, but not on the local portion of the
13210 // triangulation. In that case, just return the end iterator.
13211 //
13212 // We need to use levels.size() instead of n_levels() because the
13213 // latter function uses the cache, but we need to be able to call
13214 // this function at a time when the cache is not currently up to
13215 // date.
13216 if (level >= levels.size())
13217 {
13218 Assert(level < n_global_levels(),
13219 ExcInvalidLevel(level, n_global_levels()));
13220 return end();
13221 }
13222
13223 // Query whether the given level is valid for the local portion of the
13224 // triangulation.
13225 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13226 if (level < levels.size() - 1)
13227 return begin_raw(level + 1);
13228 else
13229 return end();
13230}
13231
13232
13233template <int dim, int spacedim>
13235Triangulation<dim, spacedim>::end(const unsigned int level) const
13236{
13237 // This function may be called on parallel triangulations on levels
13238 // that exist globally, but not on the local portion of the
13239 // triangulation. In that case, just retrn the end iterator.
13240 //
13241 // We need to use levels.size() instead of n_levels() because the
13242 // latter function uses the cache, but we need to be able to call
13243 // this function at a time when the cache is not currently up to
13244 // date.
13245 if (level >= levels.size())
13246 {
13247 Assert(level < n_global_levels(),
13248 ExcInvalidLevel(level, n_global_levels()));
13249 return end();
13250 }
13251
13252 // Query whether the given level is valid for the local portion of the
13253 // triangulation.
13254 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13255 if (level < levels.size() - 1)
13256 return begin(level + 1);
13257 else
13258 return end();
13259}
13260
13261
13262template <int dim, int spacedim>
13264Triangulation<dim, spacedim>::end_active(const unsigned int level) const
13265{
13266 // This function may be called on parallel triangulations on levels
13267 // that exist globally, but not on the local portion of the
13268 // triangulation. In that case, just return the end iterator.
13269 //
13270 // We need to use levels.size() instead of n_levels() because the
13271 // latter function uses the cache, but we need to be able to call
13272 // this function at a time when the cache is not currently up to
13273 // date.
13274 if (level >= levels.size())
13275 {
13276 Assert(level < n_global_levels(),
13277 ExcInvalidLevel(level, n_global_levels()));
13278 return end();
13279 }
13280
13281 // Query whether the given level is valid for the local portion of the
13282 // triangulation.
13283 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13284 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
13285 begin_active(level + 1));
13286}
13287
13288
13289
13290template <int dim, int spacedim>
13293{
13295 begin(), end());
13296}
13297
13298
13299template <int dim, int spacedim>
13302{
13303 return IteratorRange<
13305 end());
13306}
13307
13308
13309
13310template <int dim, int spacedim>
13313 const unsigned int level) const
13314{
13316 begin(level), end(level));
13317}
13318
13319
13320
13321template <int dim, int spacedim>
13324 const unsigned int level) const
13325{
13326 return IteratorRange<
13328 begin_active(level), end_active(level));
13329}
13330
13331
13332/*------------------------ Face iterator functions ------------------------*/
13333
13334
13335template <int dim, int spacedim>
13338{
13339 switch (dim)
13340 {
13341 case 1:
13342 Assert(false, ExcImpossibleInDim(1));
13343 return raw_face_iterator();
13344 case 2:
13345 return begin_line();
13346 case 3:
13347 return begin_quad();
13348 default:
13349 Assert(false, ExcNotImplemented());
13350 return face_iterator();
13351 }
13352}
13353
13354
13355
13356template <int dim, int spacedim>
13359{
13360 switch (dim)
13361 {
13362 case 1:
13363 Assert(false, ExcImpossibleInDim(1));
13364 return raw_face_iterator();
13365 case 2:
13366 return begin_active_line();
13367 case 3:
13368 return begin_active_quad();
13369 default:
13370 Assert(false, ExcNotImplemented());
13371 return active_face_iterator();
13372 }
13373}
13374
13375
13376
13377template <int dim, int spacedim>
13380{
13381 switch (dim)
13382 {
13383 case 1:
13384 Assert(false, ExcImpossibleInDim(1));
13385 return raw_face_iterator();
13386 case 2:
13387 return end_line();
13388 case 3:
13389 return end_quad();
13390 default:
13391 Assert(false, ExcNotImplemented());
13392 return raw_face_iterator();
13393 }
13394}
13395
13396
13397
13398template <int dim, int spacedim>
13401{
13402 return IteratorRange<
13404 begin_active_face(), end_face());
13405}
13406
13407/*------------------------ Vertex iterator functions ------------------------*/
13408
13409
13410template <int dim, int spacedim>
13413{
13414 vertex_iterator i =
13415 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13416 if (i.state() != IteratorState::valid)
13417 return i;
13418 // This loop will end because every triangulation has used vertices.
13419 while (i->used() == false)
13420 if ((++i).state() != IteratorState::valid)
13421 return i;
13422 return i;
13423}
13424
13425
13426
13427template <int dim, int spacedim>
13430{
13431 // every vertex is active
13432 return begin_vertex();
13433}
13434
13435
13436
13437template <int dim, int spacedim>
13440{
13441 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13442 -1,
13444}
13445
13446
13447
13448/*------------------------ Line iterator functions ------------------------*/
13449
13450
13451
13452template <int dim, int spacedim>
13455{
13456 // This function may be called on parallel triangulations on levels
13457 // that exist globally, but not on the local portion of the
13458 // triangulation. In that case, just return the end iterator.
13459 //
13460 // We need to use levels.size() instead of n_levels() because the
13461 // latter function uses the cache, but we need to be able to call
13462 // this function at a time when the cache is not currently up to
13463 // date.
13464 if (level >= levels.size())
13465 {
13466 Assert(level < n_global_levels(),
13467 ExcInvalidLevel(level, n_global_levels()));
13468 return end_line();
13469 }
13470
13471 switch (dim)
13472 {
13473 case 1:
13474 // Query whether the given level is valid for the local portion of the
13475 // triangulation.
13476 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13477
13478 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13479 return end_line();
13480
13481 return raw_line_iterator(
13482 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13483
13484 default:
13485 Assert(level == 0, ExcFacesHaveNoLevel());
13486 return raw_line_iterator(
13487 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13488 }
13489}
13490
13491
13492template <int dim, int spacedim>
13494Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
13495{
13496 // level is checked in begin_raw
13497 raw_line_iterator ri = begin_raw_line(level);
13498 if (ri.state() != IteratorState::valid)
13499 return ri;
13500 while (ri->used() == false)
13501 if ((++ri).state() != IteratorState::valid)
13502 return ri;
13503 return ri;
13504}
13505
13506
13507
13508template <int dim, int spacedim>
13511{
13512 // level is checked in begin_raw
13513 line_iterator i = begin_line(level);
13514 if (i.state() != IteratorState::valid)
13515 return i;
13516 while (i->has_children())
13517 if ((++i).state() != IteratorState::valid)
13518 return i;
13519 return i;
13520}
13521
13522
13523
13524template <int dim, int spacedim>
13527{
13528 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13529 -1,
13530 -1);
13531}
13532
13533
13534
13535/*------------------------ Quad iterator functions ------------------------*/
13536
13537
13538template <int dim, int spacedim>
13541{
13542 // This function may be called on parallel triangulations on levels
13543 // that exist globally, but not on the local portion of the
13544 // triangulation. In that case, just return the end iterator.
13545 //
13546 // We need to use levels.size() instead of n_levels() because the
13547 // latter function uses the cache, but we need to be able to call
13548 // this function at a time when the cache is not currently up to
13549 // date.
13550 if (level >= levels.size())
13551 {
13552 Assert(level < n_global_levels(),
13553 ExcInvalidLevel(level, n_global_levels()));
13554 return end_quad();
13555 }
13556
13557 switch (dim)
13558 {
13559 case 1:
13560 Assert(false, ExcImpossibleInDim(1));
13561 return raw_hex_iterator();
13562 case 2:
13563 {
13564 // Query whether the given level is valid for the local portion of the
13565 // triangulation.
13566 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13567
13568 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13569 return end_quad();
13570
13571 return raw_quad_iterator(
13572 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13573 }
13574
13575 case 3:
13576 {
13577 Assert(level == 0, ExcFacesHaveNoLevel());
13578
13579 return raw_quad_iterator(
13580 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
13581 }
13582
13583
13584 default:
13585 Assert(false, ExcNotImplemented());
13586 return raw_hex_iterator();
13587 }
13588}
13589
13590
13591
13592template <int dim, int spacedim>
13594Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
13595{
13596 // level is checked in begin_raw
13597 raw_quad_iterator ri = begin_raw_quad(level);
13598 if (ri.state() != IteratorState::valid)
13599 return ri;
13600 while (ri->used() == false)
13601 if ((++ri).state() != IteratorState::valid)
13602 return ri;
13603 return ri;
13604}
13605
13606
13607
13608template <int dim, int spacedim>
13611{
13612 // level is checked in begin_raw
13613 quad_iterator i = begin_quad(level);
13614 if (i.state() != IteratorState::valid)
13615 return i;
13616 while (i->has_children())
13617 if ((++i).state() != IteratorState::valid)
13618 return i;
13619 return i;
13620}
13621
13622
13623
13624template <int dim, int spacedim>
13627{
13628 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13629 -1,
13630 -1);
13631}
13632
13633
13634/*------------------------ Hex iterator functions ------------------------*/
13635
13636
13637template <int dim, int spacedim>
13639Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
13640{
13641 // This function may be called on parallel triangulations on levels
13642 // that exist globally, but not on the local portion of the
13643 // triangulation. In that case, just return the end iterator.
13644 //
13645 // We need to use levels.size() instead of n_levels() because the
13646 // latter function uses the cache, but we need to be able to call
13647 // this function at a time when the cache is not currently up to
13648 // date.
13649 if (level >= levels.size())
13650 {
13651 Assert(level < n_global_levels(),
13652 ExcInvalidLevel(level, n_global_levels()));
13653 return end_hex();
13654 }
13655
13656 switch (dim)
13657 {
13658 case 1:
13659 case 2:
13660 Assert(false, ExcImpossibleInDim(1));
13661 return raw_hex_iterator();
13662 case 3:
13663 {
13664 // Query whether the given level is valid for the local portion of the
13665 // triangulation.
13666 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
13667
13668 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
13669 return end_hex();
13670
13671 return raw_hex_iterator(
13672 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
13673 }
13674
13675 default:
13676 Assert(false, ExcNotImplemented());
13677 return raw_hex_iterator();
13678 }
13679}
13680
13681
13682
13683template <int dim, int spacedim>
13685Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
13686{
13687 // level is checked in begin_raw
13688 raw_hex_iterator ri = begin_raw_hex(level);
13689 if (ri.state() != IteratorState::valid)
13690 return ri;
13691 while (ri->used() == false)
13692 if ((++ri).state() != IteratorState::valid)
13693 return ri;
13694 return ri;
13695}
13696
13697
13698
13699template <int dim, int spacedim>
13702{
13703 // level is checked in begin_raw
13704 hex_iterator i = begin_hex(level);
13705 if (i.state() != IteratorState::valid)
13706 return i;
13707 while (i->has_children())
13708 if ((++i).state() != IteratorState::valid)
13709 return i;
13710 return i;
13711}
13712
13713
13714
13715template <int dim, int spacedim>
13718{
13719 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
13720 -1,
13721 -1);
13722}
13723
13724
13725
13726// -------------------------------- number of cells etc ---------------
13727
13728
13729namespace internal
13730{
13731 namespace TriangulationImplementation
13732 {
13733 inline unsigned int
13735 {
13736 return c.n_lines;
13737 }
13738
13739
13740 inline unsigned int
13743 {
13744 return c.n_active_lines;
13745 }
13746
13747
13748 inline unsigned int
13750 {
13751 return c.n_quads;
13752 }
13753
13754
13755 inline unsigned int
13758 {
13759 return c.n_active_quads;
13760 }
13761
13762
13763 inline unsigned int
13765 {
13766 return c.n_hexes;
13767 }
13768
13769
13770 inline unsigned int
13773 {
13774 return c.n_active_hexes;
13775 }
13776 } // namespace TriangulationImplementation
13777} // namespace internal
13778
13779
13780
13781template <int dim, int spacedim>
13782unsigned int
13784{
13786}
13787
13788
13789template <int dim, int spacedim>
13790unsigned int
13792{
13794}
13795
13796template <int dim, int spacedim>
13799{
13800 return n_active_cells();
13801}
13802
13803template <int dim, int spacedim>
13806{
13807 return n_cells(0);
13808}
13809
13810template <int dim, int spacedim>
13811unsigned int
13813{
13814 switch (dim)
13815 {
13816 case 1:
13817 return n_used_vertices();
13818 case 2:
13819 return n_lines();
13820 case 3:
13821 return n_quads();
13822 default:
13823 Assert(false, ExcNotImplemented());
13824 }
13825 return 0;
13826}
13827
13828
13829template <int dim, int spacedim>
13830unsigned int
13832{
13833 switch (dim)
13834 {
13835 case 1:
13836 return n_vertices();
13837 case 2:
13838 return n_raw_lines();
13839 case 3:
13840 return n_raw_quads();
13841 default:
13842 Assert(false, ExcNotImplemented());
13843 }
13844 return 0;
13845}
13846
13847
13848template <int dim, int spacedim>
13849unsigned int
13851{
13852 switch (dim)
13853 {
13854 case 1:
13855 return n_used_vertices();
13856 case 2:
13857 return n_active_lines();
13858 case 3:
13859 return n_active_quads();
13860 default:
13861 Assert(false, ExcNotImplemented());
13862 }
13863 return 0;
13864}
13865
13866
13867template <int dim, int spacedim>
13868unsigned int
13869Triangulation<dim, spacedim>::n_raw_cells(const unsigned int level) const
13870{
13871 switch (dim)
13872 {
13873 case 1:
13874 return n_raw_lines(level);
13875 case 2:
13876 return n_raw_quads(level);
13877 case 3:
13878 return n_raw_hexs(level);
13879 default:
13880 Assert(false, ExcNotImplemented());
13881 }
13882 return 0;
13883}
13884
13885
13886
13887template <int dim, int spacedim>
13888unsigned int
13889Triangulation<dim, spacedim>::n_cells(const unsigned int level) const
13890{
13891 switch (dim)
13892 {
13893 case 1:
13894 return n_lines(level);
13895 case 2:
13896 return n_quads(level);
13897 case 3:
13898 return n_hexs(level);
13899 default:
13900 Assert(false, ExcNotImplemented());
13901 }
13902 return 0;
13903}
13904
13905
13906
13907template <int dim, int spacedim>
13908unsigned int
13910{
13911 switch (dim)
13912 {
13913 case 1:
13914 return n_active_lines(level);
13915 case 2:
13916 return n_active_quads(level);
13917 case 3:
13918 return n_active_hexs(level);
13919 default:
13920 Assert(false, ExcNotImplemented());
13921 }
13922 return 0;
13923}
13924
13925
13926template <int dim, int spacedim>
13927bool
13929{
13930 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
13931 if (n_active_cells(lvl) != 0)
13932 return true;
13933
13934 return false;
13935}
13936
13937
13938template <int dim, int spacedim>
13939unsigned int
13941{
13942 return number_cache.n_lines;
13943}
13944
13945
13946
13947template <int dim, int spacedim>
13948unsigned int
13949Triangulation<dim, spacedim>::n_raw_lines(const unsigned int level) const
13950{
13951 if (dim == 1)
13952 {
13953 AssertIndexRange(level, n_levels());
13954 return levels[level]->cells.n_objects();
13955 }
13956
13957 Assert(false, ExcFacesHaveNoLevel());
13958 return 0;
13959}
13960
13961
13962template <int dim, int spacedim>
13963unsigned int
13965{
13966 if (dim == 1)
13967 {
13968 Assert(false, ExcNotImplemented());
13969 return 0;
13970 }
13971
13972 return faces->lines.n_objects();
13973}
13974
13975
13976template <int dim, int spacedim>
13977unsigned int
13978Triangulation<dim, spacedim>::n_lines(const unsigned int level) const
13979{
13980 AssertIndexRange(level, number_cache.n_lines_level.size());
13981 Assert(dim == 1, ExcFacesHaveNoLevel());
13982 return number_cache.n_lines_level[level];
13983}
13984
13985
13986template <int dim, int spacedim>
13987unsigned int
13989{
13990 return number_cache.n_active_lines;
13991}
13992
13993
13994template <int dim, int spacedim>
13995unsigned int
13997{
13998 AssertIndexRange(level, number_cache.n_lines_level.size());
13999 Assert(dim == 1, ExcFacesHaveNoLevel());
14000
14001 return number_cache.n_active_lines_level[level];
14002}
14003
14004
14005template <>
14006unsigned int
14008{
14009 return 0;
14010}
14011
14012
14013template <>
14014unsigned int
14015Triangulation<1, 1>::n_quads(const unsigned int) const
14016{
14017 return 0;
14018}
14019
14020
14021template <>
14022unsigned int
14023Triangulation<1, 1>::n_raw_quads(const unsigned int) const
14024{
14025 return 0;
14026}
14027
14028
14029template <>
14030unsigned int
14031Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
14032{
14033 return 0;
14034}
14035
14036
14037template <>
14038unsigned int
14040{
14041 return 0;
14042}
14043
14044
14045template <>
14046unsigned int
14048{
14049 return 0;
14050}
14051
14052
14053
14054template <>
14055unsigned int
14057{
14058 return 0;
14059}
14060
14061
14062template <>
14063unsigned int
14064Triangulation<1, 2>::n_quads(const unsigned int) const
14065{
14066 return 0;
14067}
14068
14069
14070template <>
14071unsigned int
14072Triangulation<1, 2>::n_raw_quads(const unsigned int) const
14073{
14074 return 0;
14075}
14076
14077
14078template <>
14079unsigned int
14080Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
14081{
14082 return 0;
14083}
14084
14085
14086template <>
14087unsigned int
14089{
14090 return 0;
14091}
14092
14093
14094template <>
14095unsigned int
14097{
14098 return 0;
14099}
14100
14101
14102template <>
14103unsigned int
14105{
14106 return 0;
14107}
14108
14109
14110template <>
14111unsigned int
14112Triangulation<1, 3>::n_quads(const unsigned int) const
14113{
14114 return 0;
14115}
14116
14117
14118template <>
14119unsigned int
14120Triangulation<1, 3>::n_raw_quads(const unsigned int) const
14121{
14122 return 0;
14123}
14124
14125
14126template <>
14127unsigned int
14128Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
14129{
14130 return 0;
14131}
14132
14133
14134template <>
14135unsigned int
14137{
14138 return 0;
14139}
14140
14141
14142template <>
14143unsigned int
14145{
14146 return 0;
14147}
14148
14149
14150
14151template <int dim, int spacedim>
14152unsigned int
14154{
14155 return number_cache.n_quads;
14156}
14157
14158
14159template <int dim, int spacedim>
14160unsigned int
14161Triangulation<dim, spacedim>::n_quads(const unsigned int level) const
14162{
14163 Assert(dim == 2, ExcFacesHaveNoLevel());
14164 AssertIndexRange(level, number_cache.n_quads_level.size());
14165 return number_cache.n_quads_level[level];
14166}
14167
14168
14169
14170template <>
14171unsigned int
14173{
14174 AssertIndexRange(level, n_levels());
14175 return levels[level]->cells.n_objects();
14176}
14177
14178
14179
14180template <>
14181unsigned int
14183{
14184 AssertIndexRange(level, n_levels());
14185 return levels[level]->cells.n_objects();
14186}
14187
14188
14189template <>
14190unsigned int
14191Triangulation<3, 3>::n_raw_quads(const unsigned int) const
14192{
14193 Assert(false, ExcFacesHaveNoLevel());
14194 return 0;
14195}
14196
14197
14198
14199template <int dim, int spacedim>
14200unsigned int
14202{
14203 Assert(false, ExcNotImplemented());
14204 return 0;
14205}
14206
14207
14208
14209template <>
14210unsigned int
14212{
14213 return faces->quads.n_objects();
14214}
14215
14216
14217
14218template <int dim, int spacedim>
14219unsigned int
14221{
14222 return number_cache.n_active_quads;
14223}
14224
14225
14226template <int dim, int spacedim>
14227unsigned int
14229{
14230 AssertIndexRange(level, number_cache.n_quads_level.size());
14231 Assert(dim == 2, ExcFacesHaveNoLevel());
14232
14233 return number_cache.n_active_quads_level[level];
14234}
14235
14236
14237template <int dim, int spacedim>
14238unsigned int
14240{
14241 return 0;
14242}
14243
14244
14245
14246template <int dim, int spacedim>
14247unsigned int
14248Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
14249{
14250 return 0;
14251}
14252
14253
14254
14255template <int dim, int spacedim>
14256unsigned int
14257Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
14258{
14259 return 0;
14260}
14261
14262
14263template <int dim, int spacedim>
14264unsigned int
14266{
14267 return 0;
14268}
14269
14270
14271
14272template <int dim, int spacedim>
14273unsigned int
14274Triangulation<dim, spacedim>::n_active_hexs(const unsigned int) const
14275{
14276 return 0;
14277}
14278
14279
14280template <>
14281unsigned int
14283{
14284 return number_cache.n_hexes;
14285}
14286
14287
14288
14289template <>
14290unsigned int
14291Triangulation<3, 3>::n_hexs(const unsigned int level) const
14292{
14293 AssertIndexRange(level, number_cache.n_hexes_level.size());
14294
14295 return number_cache.n_hexes_level[level];
14296}
14297
14298
14299
14300template <>
14301unsigned int
14303{
14304 AssertIndexRange(level, n_levels());
14305 return levels[level]->cells.n_objects();
14306}
14307
14308
14309template <>
14310unsigned int
14312{
14313 return number_cache.n_active_hexes;
14314}
14315
14316
14317
14318template <>
14319unsigned int
14321{
14322 AssertIndexRange(level, number_cache.n_hexes_level.size());
14323
14324 return number_cache.n_active_hexes_level[level];
14325}
14326
14327
14328
14329template <int dim, int spacedim>
14330unsigned int
14332{
14333 return std::count(vertices_used.begin(), vertices_used.end(), true);
14334}
14335
14336
14337
14338template <int dim, int spacedim>
14339const std::vector<bool> &
14341{
14342 return vertices_used;
14343}
14344
14345
14346
14347template <>
14348unsigned int
14350{
14351 return 2;
14352}
14353
14354
14355
14356template <>
14357unsigned int
14359{
14360 return 2;
14361}
14362
14363
14364template <>
14365unsigned int
14367{
14368 return 2;
14369}
14370
14371
14372template <int dim, int spacedim>
14373unsigned int
14375{
14376 cell_iterator cell = begin(0),
14377 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
14378 // store the largest index of the
14379 // vertices used on level 0
14380 unsigned int max_vertex_index = 0;
14381 for (; cell != endc; ++cell)
14382 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
14383 if (cell->vertex_index(vertex) > max_vertex_index)
14384 max_vertex_index = cell->vertex_index(vertex);
14385
14386 // store the number of times a cell
14387 // touches a vertex. An unsigned
14388 // int should suffice, even for
14389 // larger dimensions
14390 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
14391 // touch a vertex's usage count
14392 // every time we find an adjacent
14393 // element
14394 for (cell = begin(); cell != endc; ++cell)
14395 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
14396 ++usage_count[cell->vertex_index(vertex)];
14397
14399 static_cast<unsigned int>(
14400 *std::max_element(usage_count.begin(), usage_count.end())));
14401}
14402
14403
14404
14405template <int dim, int spacedim>
14408{
14410}
14411
14412
14413
14414template <int dim, int spacedim>
14417{
14418 return *this;
14419}
14420
14421
14422
14423template <int dim, int spacedim>
14426{
14427 return *this;
14428}
14429
14430
14431
14432template <int dim, int spacedim>
14433void
14436 &periodicity_vector)
14437{
14438 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
14439 periodicity_vector.begin(),
14440 periodicity_vector.end());
14441
14442 // Now initialize periodic_face_map
14443 update_periodic_face_map();
14444}
14445
14446
14447
14448template <int dim, int spacedim>
14449const typename std::map<
14450 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
14451 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
14452 unsigned int>,
14453 std::bitset<3>>> &
14455{
14456 return periodic_face_map;
14457}
14458
14459
14460
14461template <int dim, int spacedim>
14462void
14464{
14465 // Call our version of prepare_coarsening_and_refinement() even if a derived
14466 // class like parallel::distributed::Triangulation overrides it. Their
14467 // function will be called in their execute_coarsening_and_refinement()
14468 // function. Even in a distributed computation our job here is to reconstruct
14469 // the local part of the mesh and as such checking our flags is enough.
14471
14472 // verify a case with which we have had
14473 // some difficulty in the past (see the
14474 // deal.II/coarsening_* tests)
14475 if (smooth_grid & limit_level_difference_at_vertices)
14476 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
14477
14478 // Inform all listeners about beginning of refinement.
14479 signals.pre_refinement();
14480
14481 execute_coarsening();
14482
14483 const DistortedCellList cells_with_distorted_children = execute_refinement();
14484
14485 reset_cell_vertex_indices_cache();
14486
14487 // verify a case with which we have had
14488 // some difficulty in the past (see the
14489 // deal.II/coarsening_* tests)
14490 if (smooth_grid & limit_level_difference_at_vertices)
14491 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
14492
14493 // finally build up neighbor connectivity information, and set
14494 // active cell indices
14495 this->policy->update_neighbors(*this);
14496 reset_active_cell_indices();
14497
14498 reset_global_cell_indices(); // TODO: better place?
14499
14500 // Inform all listeners about end of refinement.
14501 signals.post_refinement();
14502
14503 AssertThrow(cells_with_distorted_children.distorted_cells.size() == 0,
14504 cells_with_distorted_children);
14505
14506 update_periodic_face_map();
14507}
14508
14509
14510
14511template <int dim, int spacedim>
14512void
14514{
14515 unsigned int active_cell_index = 0;
14516 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
14517 if ((cell->used() == false) || cell->has_children())
14518 cell->set_active_cell_index(numbers::invalid_unsigned_int);
14519 else
14520 {
14521 cell->set_active_cell_index(active_cell_index);
14522 ++active_cell_index;
14523 }
14524
14525 Assert(active_cell_index == n_active_cells(), ExcInternalError());
14526}
14527
14528
14529
14530template <int dim, int spacedim>
14531void
14533{
14534 {
14536 for (const auto &cell : active_cell_iterators())
14537 cell->set_global_active_cell_index(cell_index++);
14538 }
14539
14540 for (unsigned int l = 0; l < levels.size(); ++l)
14541 {
14543 for (const auto &cell : cell_iterators_on_level(l))
14544 cell->set_global_level_cell_index(cell_index++);
14545 }
14546}
14547
14548
14549
14550template <int dim, int spacedim>
14551void
14553{
14554 for (unsigned int l = 0; l < levels.size(); ++l)
14555 {
14556 constexpr unsigned int max_vertices_per_cell = 1 << dim;
14557 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
14558 cache.clear();
14559 cache.resize(levels[l]->refine_flags.size() * max_vertices_per_cell,
14561 for (const auto &cell : cell_iterators_on_level(l))
14562 {
14563 const unsigned int my_index = cell->index() * max_vertices_per_cell;
14564 for (const unsigned int i : cell->vertex_indices())
14565 cache[my_index + i] = internal::TriaAccessorImplementation::
14566 Implementation::vertex_index(*cell, i);
14567 }
14568 }
14569}
14570
14571
14572
14573template <int dim, int spacedim>
14574void
14576{
14577 // first empty the currently stored objects
14578 periodic_face_map.clear();
14579
14580 typename std::vector<
14582 for (it = periodic_face_pairs_level_0.begin();
14583 it != periodic_face_pairs_level_0.end();
14584 ++it)
14585 {
14586 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
14587 it->cell[1],
14588 it->face_idx[0],
14589 it->face_idx[1],
14590 it->orientation,
14591 periodic_face_map);
14592
14593 // for the other way, we need to invert the orientation
14594 std::bitset<3> inverted_orientation;
14595 {
14596 bool orientation, flip, rotation;
14597 orientation = it->orientation[0];
14598 rotation = it->orientation[2];
14599 flip = orientation ? rotation ^ it->orientation[1] : it->orientation[1];
14600 inverted_orientation[0] = orientation;
14601 inverted_orientation[1] = flip;
14602 inverted_orientation[2] = rotation;
14603 }
14604 update_periodic_face_map_recursively<dim, spacedim>(it->cell[1],
14605 it->cell[0],
14606 it->face_idx[1],
14607 it->face_idx[0],
14608 inverted_orientation,
14609 periodic_face_map);
14610 }
14611
14612 // check consistency
14613 typename std::map<std::pair<cell_iterator, unsigned int>,
14614 std::pair<std::pair<cell_iterator, unsigned int>,
14615 std::bitset<3>>>::const_iterator it_test;
14616 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
14617 ++it_test)
14618 {
14620 it_test->first.first;
14622 it_test->second.first.first;
14623 if (cell_1->level() == cell_2->level())
14624 {
14625 // if both cells have the same neighbor, then the same pair
14626 // order swapped has to be in the map
14627 Assert(periodic_face_map[it_test->second.first].first ==
14628 it_test->first,
14630 }
14631 }
14632}
14633
14634
14635
14636template <int dim, int spacedim>
14637void
14639{
14640 std::set<ReferenceCell> reference_cells_set;
14641 for (auto cell : active_cell_iterators())
14642 if (cell->is_locally_owned())
14643 reference_cells_set.insert(cell->reference_cell());
14644
14645 this->reference_cells =
14646 std::vector<ReferenceCell>(reference_cells_set.begin(),
14647 reference_cells_set.end());
14648}
14649
14650
14651
14652template <int dim, int spacedim>
14653const std::vector<ReferenceCell> &
14655{
14656 return this->reference_cells;
14657}
14658
14659
14660
14661template <int dim, int spacedim>
14662bool
14664{
14665 Assert(this->reference_cells.size() > 0,
14666 ExcMessage("You can't ask about the kinds of reference "
14667 "cells used by this triangulation if the "
14668 "triangulation doesn't yet have any cells in it."));
14669 return (this->reference_cells.size() == 1 &&
14670 this->reference_cells[0].is_hyper_cube());
14671}
14672
14673
14674
14675template <int dim, int spacedim>
14676bool
14678{
14679 Assert(this->reference_cells.size() > 0,
14680 ExcMessage("You can't ask about the kinds of reference "
14681 "cells used by this triangulation if the "
14682 "triangulation doesn't yet have any cells in it."));
14683 return (this->reference_cells.size() == 1 &&
14684 this->reference_cells[0].is_simplex());
14685}
14686
14687
14688
14689template <int dim, int spacedim>
14690bool
14692{
14693 Assert(this->reference_cells.size() > 0,
14694 ExcMessage("You can't ask about the kinds of reference "
14695 "cells used by this triangulation if the "
14696 "triangulation doesn't yet have any cells in it."));
14697 return reference_cells.size() > 1 ||
14698 ((reference_cells[0].is_hyper_cube() == false) &&
14699 (reference_cells[0].is_simplex() == false));
14700}
14701
14702
14703
14704template <int dim, int spacedim>
14705void
14707{
14708 levels.clear();
14709 faces.reset();
14710
14711 vertices.clear();
14712 vertices_used.clear();
14713
14714 manifolds.clear();
14715
14717}
14718
14719
14720
14721template <int dim, int spacedim>
14724{
14725 const DistortedCellList cells_with_distorted_children =
14726 this->policy->execute_refinement(*this, check_for_distorted_cells);
14727
14728
14729
14730 // re-compute number of lines
14732 *this, levels.size(), number_cache);
14733
14734#ifdef DEBUG
14735 for (const auto &level : levels)
14736 monitor_memory(level->cells, dim);
14737
14738 // check whether really all refinement flags are reset (also of
14739 // previously non-active cells which we may not have touched. If the
14740 // refinement flag of a non-active cell is set, something went wrong
14741 // since the cell-accessors should have caught this)
14742 for (const auto &cell : this->cell_iterators())
14743 Assert(!cell->refine_flag_set(), ExcInternalError());
14744#endif
14745
14746 return cells_with_distorted_children;
14747}
14748
14749
14750
14751template <int dim, int spacedim>
14752void
14754{
14755 // create a vector counting for each line how many cells contain
14756 // this line. in 3D, this is used later on to decide which lines can
14757 // be deleted after coarsening a cell. in other dimensions it will
14758 // be ignored
14759 std::vector<unsigned int> line_cell_count =
14760 count_cells_bounded_by_line(*this);
14761 std::vector<unsigned int> quad_cell_count =
14762 count_cells_bounded_by_quad(*this);
14763
14764 // loop over all cells. Flag all cells of which all children are
14765 // flagged for coarsening and delete the childrens' flags. In
14766 // effect, only those cells are flagged of which originally all
14767 // children were flagged and for which all children are on the same
14768 // refinement level. For flagging, the user flags are used, to avoid
14769 // confusion and because non-active cells can't be flagged for
14770 // coarsening. Note that because of the effects of
14771 // @p{fix_coarsen_flags}, of a cell either all or no children must
14772 // be flagged for coarsening, so it is ok to only check the first
14773 // child
14774 clear_user_flags();
14775
14776 for (const auto &cell : this->cell_iterators())
14777 if (!cell->is_active())
14778 if (cell->child(0)->coarsen_flag_set())
14779 {
14780 cell->set_user_flag();
14781 for (unsigned int child = 0; child < cell->n_children(); ++child)
14782 {
14783 Assert(cell->child(child)->coarsen_flag_set(),
14785 cell->child(child)->clear_coarsen_flag();
14786 }
14787 }
14788
14789
14790 // now do the actual coarsening step. Since the loop goes over used
14791 // cells we only need not worry about deleting some cells since the
14792 // ++operator will then just hop over them if we should hit one. Do
14793 // the loop in the reverse way since we may only delete some cells
14794 // if their neighbors have already been deleted (if the latter are
14795 // on a higher level for example)
14796 //
14797 // since we delete the *children* of cells, we can ignore cells
14798 // on the highest level, i.e., level must be less than or equal
14799 // to n_levels()-2.
14800 cell_iterator cell = begin(), endc = end();
14801 if (levels.size() >= 2)
14802 for (cell = last(); cell != endc; --cell)
14803 if (cell->level() <= static_cast<int>(levels.size() - 2) &&
14804 cell->user_flag_set())
14805 {
14806 // inform all listeners that cell coarsening is going to happen
14807 signals.pre_coarsening_on_cell(cell);
14808 // use a separate function, since this is dimension specific
14809 this->policy->delete_children(*this,
14810 cell,
14811 line_cell_count,
14812 quad_cell_count);
14813 }
14814
14815 // re-compute number of lines and quads
14817 *this, levels.size(), number_cache);
14818
14819 // in principle no user flags should be set any more at this point
14820#if DEBUG
14821 for (cell = begin(); cell != endc; ++cell)
14822 Assert(cell->user_flag_set() == false, ExcInternalError());
14823#endif
14824}
14825
14826
14827
14828template <int dim, int spacedim>
14829void
14831{
14832 // copy a piece of code from prepare_coarsening_and_refinement that
14833 // ensures that the level difference at vertices is limited if so
14834 // desired. we need this code here since at least in 1d we don't
14835 // call the dimension-independent version of
14836 // prepare_coarsening_and_refinement function. in 2d and 3d, having
14837 // this hunk here makes our lives a bit easier as well as it takes
14838 // care of these cases earlier than it would otherwise happen.
14839 //
14840 // the main difference to the code in p_c_and_r is that here we
14841 // absolutely have to make sure that we get things right, i.e. that
14842 // in particular we set flags right if
14843 // limit_level_difference_at_vertices is set. to do so we iterate
14844 // until the flags don't change any more
14845 std::vector<bool> previous_coarsen_flags(n_active_cells());
14846 save_coarsen_flags(previous_coarsen_flags);
14847
14848 std::vector<int> vertex_level(vertices.size(), 0);
14849
14850 bool continue_iterating = true;
14851
14852 do
14853 {
14854 if (smooth_grid & limit_level_difference_at_vertices)
14855 {
14856 Assert(!anisotropic_refinement,
14857 ExcMessage("In case of anisotropic refinement the "
14858 "limit_level_difference_at_vertices flag for "
14859 "mesh smoothing must not be set!"));
14860
14861 // store highest level one of the cells adjacent to a vertex
14862 // belongs to
14863 std::fill(vertex_level.begin(), vertex_level.end(), 0);
14864 for (const auto &cell : this->active_cell_iterators())
14865 {
14866 if (cell->refine_flag_set())
14867 for (const unsigned int vertex :
14869 vertex_level[cell->vertex_index(vertex)] =
14870 std::max(vertex_level[cell->vertex_index(vertex)],
14871 cell->level() + 1);
14872 else if (!cell->coarsen_flag_set())
14873 for (const unsigned int vertex :
14875 vertex_level[cell->vertex_index(vertex)] =
14876 std::max(vertex_level[cell->vertex_index(vertex)],
14877 cell->level());
14878 else
14879 {
14880 // if coarsen flag is set then tentatively assume
14881 // that the cell will be coarsened. this isn't
14882 // always true (the coarsen flag could be removed
14883 // again) and so we may make an error here. we try
14884 // to correct this by iterating over the entire
14885 // process until we are converged
14886 Assert(cell->coarsen_flag_set(), ExcInternalError());
14887 for (const unsigned int vertex :
14889 vertex_level[cell->vertex_index(vertex)] =
14890 std::max(vertex_level[cell->vertex_index(vertex)],
14891 cell->level() - 1);
14892 }
14893 }
14894
14895
14896 // loop over all cells in reverse order. do so because we
14897 // can then update the vertex levels on the adjacent
14898 // vertices and maybe already flag additional cells in this
14899 // loop
14900 //
14901 // note that not only may we have to add additional
14902 // refinement flags, but we will also have to remove
14903 // coarsening flags on cells adjacent to vertices that will
14904 // see refinement
14905 active_cell_iterator cell = begin_active(), endc = end();
14906 for (cell = last_active(); cell != endc; --cell)
14907 if (cell->refine_flag_set() == false)
14908 {
14909 for (const unsigned int vertex :
14911 if (vertex_level[cell->vertex_index(vertex)] >=
14912 cell->level() + 1)
14913 {
14914 // remove coarsen flag...
14915 cell->clear_coarsen_flag();
14916
14917 // ...and if necessary also refine the current
14918 // cell, at the same time updating the level
14919 // information about vertices
14920 if (vertex_level[cell->vertex_index(vertex)] >
14921 cell->level() + 1)
14922 {
14923 cell->set_refine_flag();
14924
14925 for (const unsigned int v :
14927 vertex_level[cell->vertex_index(v)] =
14928 std::max(vertex_level[cell->vertex_index(v)],
14929 cell->level() + 1);
14930 }
14931
14932 // continue and see whether we may, for example,
14933 // go into the inner 'if' above based on a
14934 // different vertex
14935 }
14936 }
14937 }
14938
14939 // loop over all cells. Flag all cells of which all children are
14940 // flagged for coarsening and delete the childrens' flags. Also
14941 // delete all flags of cells for which not all children of a
14942 // cell are flagged. In effect, only those cells are flagged of
14943 // which originally all children were flagged and for which all
14944 // children are on the same refinement level. For flagging, the
14945 // user flags are used, to avoid confusion and because
14946 // non-active cells can't be flagged for coarsening
14947 //
14948 // In effect, all coarsen flags are turned into user flags of
14949 // the mother cell if coarsening is possible or deleted
14950 // otherwise.
14951 clear_user_flags();
14952 // Coarsen flags of cells with no mother cell, i.e. on the
14953 // coarsest level are deleted explicitly.
14954 for (const auto &acell : this->active_cell_iterators_on_level(0))
14955 acell->clear_coarsen_flag();
14956
14957 for (const auto &cell : this->cell_iterators())
14958 {
14959 // nothing to do if we are already on the finest level
14960 if (cell->is_active())
14961 continue;
14962
14963 const unsigned int n_children = cell->n_children();
14964 unsigned int flagged_children = 0;
14965 for (unsigned int child = 0; child < n_children; ++child)
14966 if (cell->child(child)->is_active() &&
14967 cell->child(child)->coarsen_flag_set())
14968 {
14969 ++flagged_children;
14970 // clear flag since we don't need it anymore
14971 cell->child(child)->clear_coarsen_flag();
14972 }
14973
14974 // flag this cell for coarsening if all children were
14975 // flagged
14976 if (flagged_children == n_children)
14977 cell->set_user_flag();
14978 }
14979
14980 // in principle no coarsen flags should be set any more at this
14981 // point
14982#if DEBUG
14983 for (auto &cell : this->cell_iterators())
14984 Assert(cell->coarsen_flag_set() == false, ExcInternalError());
14985#endif
14986
14987 // now loop over all cells which have the user flag set. their
14988 // children were flagged for coarsening. set the coarsen flag
14989 // again if we are sure that none of the neighbors of these
14990 // children are refined, or will be refined, since then we would
14991 // get a two-level jump in refinement. on the other hand, if one
14992 // of the children's neighbors has their user flag set, then we
14993 // know that its children will go away by coarsening, and we
14994 // will be ok.
14995 //
14996 // note on the other hand that we do allow level-2 jumps in
14997 // refinement between neighbors in 1d, so this whole procedure
14998 // is only necessary if we are not in 1d
14999 //
15000 // since we remove some coarsening/user flags in the process, we
15001 // have to work from the finest level to the coarsest one, since
15002 // we occasionally inspect user flags of cells on finer levels
15003 // and need to be sure that these flags are final
15004 cell_iterator cell = begin(), endc = end();
15005 for (cell = last(); cell != endc; --cell)
15006 if (cell->user_flag_set())
15007 // if allowed: flag the
15008 // children for coarsening
15009 if (this->policy->coarsening_allowed(cell))
15010 for (unsigned int c = 0; c < cell->n_children(); ++c)
15011 {
15012 Assert(cell->child(c)->refine_flag_set() == false,
15014
15015 cell->child(c)->set_coarsen_flag();
15016 }
15017
15018 // clear all user flags again, now that we don't need them any
15019 // more
15020 clear_user_flags();
15021
15022
15023 // now see if anything has changed in the last iteration of this
15024 // function
15025 std::vector<bool> current_coarsen_flags(n_active_cells());
15026 save_coarsen_flags(current_coarsen_flags);
15027
15028 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
15029 previous_coarsen_flags = current_coarsen_flags;
15030 }
15031 while (continue_iterating == true);
15032}
15033
15034
15035// TODO: merge the following 3 functions since they are the same
15036template <>
15037bool
15039{
15040 // save the flags to determine whether something was changed in the
15041 // course of this function
15042 std::vector<bool> flags_before;
15043 save_coarsen_flags(flags_before);
15044
15045 // do nothing in 1d, except setting the coarsening flags correctly
15046 fix_coarsen_flags();
15047
15048 std::vector<bool> flags_after;
15049 save_coarsen_flags(flags_after);
15050
15051 return (flags_before != flags_after);
15052}
15053
15054
15055template <>
15056bool
15058{
15059 // save the flags to determine whether something was changed in the
15060 // course of this function
15061 std::vector<bool> flags_before;
15062 save_coarsen_flags(flags_before);
15063
15064 // do nothing in 1d, except setting the coarsening flags correctly
15065 fix_coarsen_flags();
15066
15067 std::vector<bool> flags_after;
15068 save_coarsen_flags(flags_after);
15069
15070 return (flags_before != flags_after);
15071}
15072
15073
15074template <>
15075bool
15077{
15078 // save the flags to determine whether something was changed in the
15079 // course of this function
15080 std::vector<bool> flags_before;
15081 save_coarsen_flags(flags_before);
15082
15083 // do nothing in 1d, except setting the coarsening flags correctly
15084 fix_coarsen_flags();
15085
15086 std::vector<bool> flags_after;
15087 save_coarsen_flags(flags_after);
15088
15089 return (flags_before != flags_after);
15090}
15091
15092
15093
15094namespace
15095{
15096 // check if the given @param cell marked for coarsening would
15097 // produce an unrefined island. To break up long chains of these
15098 // cells we recursively check our neighbors in case we change this
15099 // cell. This reduces the number of outer iterations dramatically.
15100 template <int dim, int spacedim>
15101 void
15102 possibly_do_not_produce_unrefined_islands(
15104 {
15105 Assert(cell->has_children(), ExcInternalError());
15106
15107 unsigned int n_neighbors = 0;
15108 // count all neighbors that will be refined along the face of our
15109 // cell after the next step
15110 unsigned int count = 0;
15111 for (unsigned int n : GeometryInfo<dim>::face_indices())
15112 {
15113 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
15114 cell->neighbor(n);
15115 if (neighbor.state() == IteratorState::valid)
15116 {
15117 ++n_neighbors;
15118 if (face_will_be_refined_by_neighbor(cell, n))
15119 ++count;
15120 }
15121 }
15122 // clear coarsen flags if either all existing neighbors will be
15123 // refined or all but one will be and the cell is in the interior
15124 // of the domain
15125 if (count == n_neighbors ||
15126 (count >= n_neighbors - 1 &&
15127 n_neighbors == GeometryInfo<dim>::faces_per_cell))
15128 {
15129 for (unsigned int c = 0; c < cell->n_children(); ++c)
15130 cell->child(c)->clear_coarsen_flag();
15131
15132 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15133 if (!cell->at_boundary(face) &&
15134 (!cell->neighbor(face)->is_active()) &&
15135 (cell_will_be_coarsened(cell->neighbor(face))))
15136 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
15137 cell->neighbor(face));
15138 }
15139 }
15140
15141
15142 // see if the current cell needs to be refined to avoid unrefined
15143 // islands.
15144 //
15145 // there are sometimes chains of cells that induce refinement of
15146 // each other. to avoid running the loop in
15147 // prepare_coarsening_and_refinement over and over again for each
15148 // one of them, at least for the isotropic refinement case we seek
15149 // to flag neighboring elements as well as necessary. this takes
15150 // care of (slightly pathological) cases like
15151 // deal.II/mesh_smoothing_03
15152 template <int dim, int spacedim>
15153 void
15154 possibly_refine_unrefined_island(
15156 const bool allow_anisotropic_smoothing)
15157 {
15158 Assert(cell->is_active(), ExcInternalError());
15159 Assert(cell->refine_flag_set() == false, ExcInternalError());
15160
15161
15162 // now we provide two algorithms. the first one is the standard
15163 // one, coming from the time, where only isotropic refinement was
15164 // possible. it simply counts the neighbors that are or will be
15165 // refined and compares to the number of other ones. the second
15166 // one does this check independently for each direction: if all
15167 // neighbors in one direction (normally two, at the boundary only
15168 // one) are refined, the current cell is flagged to be refined in
15169 // an according direction.
15170
15171 if (allow_anisotropic_smoothing == false)
15172 {
15173 // use first algorithm
15174 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
15175 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15176 if (!cell->at_boundary(face))
15177 {
15178 if (face_will_be_refined_by_neighbor(cell, face))
15179 ++refined_neighbors;
15180 else
15181 ++unrefined_neighbors;
15182 }
15183
15184 if (unrefined_neighbors < refined_neighbors)
15185 {
15186 cell->clear_coarsen_flag();
15187 cell->set_refine_flag();
15188
15189 // ok, so now we have flagged this cell. if we know that
15190 // there were any unrefined neighbors at all, see if any
15191 // of those will have to be refined as well
15192 if (unrefined_neighbors > 0)
15193 for (const unsigned int face : GeometryInfo<dim>::face_indices())
15194 if (!cell->at_boundary(face) &&
15195 (face_will_be_refined_by_neighbor(cell, face) == false) &&
15196 (cell->neighbor(face)->has_children() == false) &&
15197 (cell->neighbor(face)->refine_flag_set() == false))
15198 possibly_refine_unrefined_island<dim, spacedim>(
15199 cell->neighbor(face), allow_anisotropic_smoothing);
15200 }
15201 }
15202 else
15203 {
15204 // variable to store the cell refine case needed to fulfill
15205 // all smoothing requirements
15206 RefinementCase<dim> smoothing_cell_refinement_case =
15208
15209 // use second algorithm, do the check individually for each
15210 // direction
15211 for (unsigned int face_pair = 0;
15212 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
15213 ++face_pair)
15214 {
15215 // variable to store the cell refine case needed to refine
15216 // at the current face pair in the same way as the
15217 // neighbors do...
15218 RefinementCase<dim> directional_cell_refinement_case =
15220
15221 for (unsigned int face_index = 0; face_index < 2; ++face_index)
15222 {
15223 unsigned int face = 2 * face_pair + face_index;
15224 // variable to store the refine case (to come) of the
15225 // face under consideration
15226 RefinementCase<dim - 1> expected_face_ref_case =
15227 RefinementCase<dim - 1>::no_refinement;
15228
15229 if (cell->neighbor(face).state() == IteratorState::valid)
15230 face_will_be_refined_by_neighbor<dim, spacedim>(
15231 cell, face, expected_face_ref_case);
15232 // now extract which refine case would be necessary to
15233 // achieve the same face refinement. set the
15234 // intersection with other requirements for the same
15235 // direction.
15236
15237 // note: using the intersection is not an obvious
15238 // decision, we could also argue that it is more
15239 // natural to use the union. however, intersection is
15240 // the less aggressive tactic and favours a smaller
15241 // number of refined cells over an intensive
15242 // smoothing. this way we try not to lose too much of
15243 // the effort we put in anisotropic refinement
15244 // indicators due to overly aggressive smoothing...
15245 directional_cell_refinement_case =
15246 (directional_cell_refinement_case &
15249 expected_face_ref_case,
15250 face,
15251 cell->face_orientation(face),
15252 cell->face_flip(face),
15253 cell->face_rotation(face)));
15254 } // for both face indices
15255 // if both requirements sum up to something useful, add
15256 // this to the refine case for smoothing. note: if
15257 // directional_cell_refinement_case is isotropic still,
15258 // then something went wrong...
15259 Assert(directional_cell_refinement_case <
15262 smoothing_cell_refinement_case =
15263 smoothing_cell_refinement_case | directional_cell_refinement_case;
15264 } // for all face_pairs
15265 // no we collected contributions from all directions. combine
15266 // the new flags with the existing refine case, but only if
15267 // smoothing is required
15268 if (smoothing_cell_refinement_case)
15269 {
15270 cell->clear_coarsen_flag();
15271 cell->set_refine_flag(cell->refine_flag_set() |
15272 smoothing_cell_refinement_case);
15273 }
15274 }
15275 }
15276} // namespace
15277
15278
15279template <int dim, int spacedim>
15280bool
15282{
15283 // save the flags to determine whether something was changed in the
15284 // course of this function
15285 std::vector<bool> flags_before[2];
15286 save_coarsen_flags(flags_before[0]);
15287 save_refine_flags(flags_before[1]);
15288
15289 // save the flags at the outset of each loop. we do so in order to
15290 // find out whether something was changed in the present loop, in
15291 // which case we would have to re-run the loop. the other
15292 // possibility to find this out would be to set a flag
15293 // @p{something_changed} to true each time we change something.
15294 // however, sometimes one change in one of the parts of the loop is
15295 // undone by another one, so we might end up in an endless loop. we
15296 // could be tempted to break this loop at an arbitrary number of
15297 // runs, but that would not be a clean solution, since we would
15298 // either have to 1/ break the loop too early, in which case the
15299 // promise that a second call to this function immediately after the
15300 // first one does not change anything, would be broken, or 2/ we do
15301 // as many loops as there are levels. we know that information is
15302 // transported over one level in each run of the loop, so this is
15303 // enough. Unfortunately, each loop is rather expensive, so we chose
15304 // the way presented here
15305 std::vector<bool> flags_before_loop[2] = {flags_before[0], flags_before[1]};
15306
15307 // now for what is done in each loop: we have to fulfill several
15308 // tasks at the same time, namely several mesh smoothing algorithms
15309 // and mesh regularization, by which we mean that the next mesh
15310 // fulfills several requirements such as no double refinement at
15311 // each face or line, etc.
15312 //
15313 // since doing these things at once seems almost impossible (in the
15314 // first year of this library, they were done in two functions, one
15315 // for refinement and one for coarsening, and most things within
15316 // these were done at once, so the code was rather impossible to
15317 // join into this, only, function), we do them one after each
15318 // other. the order in which we do them is such that the important
15319 // tasks, namely regularization, are done last and the least
15320 // important things are done the first. the following order is
15321 // chosen:
15322 //
15323 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
15324 // coarsen flags on level 1 to avoid level 0 cells being created
15325 // by coarsening. As coarsen flags will never be added, this can
15326 // be done once and for all before the actual loop starts.
15327 //
15328 // 1/ do not coarsen a cell if 'most of the neighbors' will be
15329 // refined after the step. This is to prevent occurrence of
15330 // unrefined islands.
15331 //
15332 // 2/ eliminate refined islands in the interior and at the
15333 // boundary. since they don't do much harm besides increasing the
15334 // number of degrees of freedom, doing this has a rather low
15335 // priority.
15336 //
15337 // 3/ limit the level difference of neighboring cells at each
15338 // vertex.
15339 //
15340 // 4/ eliminate unrefined islands. this has higher priority since
15341 // this diminishes the approximation properties not only of the
15342 // unrefined island, but also of the surrounding patch.
15343 //
15344 // 5/ ensure patch level 1. Then the triangulation consists of
15345 // patches, i.e. of cells that are refined once. It follows that
15346 // if at least one of the children of a cell is or will be
15347 // refined than all children need to be refined. This step only
15348 // sets refinement flags and does not set coarsening flags. If
15349 // the patch_level_1 flag is set, then
15350 // eliminate_unrefined_islands, eliminate_refined_inner_islands
15351 // and eliminate_refined_boundary_islands will be fulfilled
15352 // automatically and do not need to be enforced separately.
15353 //
15354 // 6/ take care of the requirement that no double refinement is done
15355 // at each face
15356 //
15357 // 7/ take care that no double refinement is done at each line in 3d
15358 // or higher dimensions.
15359 //
15360 // 8/ make sure that all children of each cell are either flagged
15361 // for coarsening or none of the children is
15362 //
15363 // For some of these steps, it is known that they interact. Namely,
15364 // it is not possible to guarantee that after step 6 another step 5
15365 // would have no effect; the same holds for the opposite order and
15366 // also when taking into account step 7. however, it is important to
15367 // guarantee that step five or six do not undo something that step 5
15368 // did, and step 7 not something of step 6, otherwise the
15369 // requirements will not be satisfied even if the loop
15370 // terminates. this is accomplished by the fact that steps 5 and 6
15371 // only *add* refinement flags and delete coarsening flags
15372 // (therefore, step 6 can't undo something that step 4 already did),
15373 // and step 7 only deletes coarsening flags, never adds some. step 7
15374 // needs also take care that it won't tag cells for refinement for
15375 // which some neighbors are more refined or will be refined.
15376
15377 //------------------------------------
15378 // STEP 0:
15379 // Only if coarsest_level_1 or patch_level_1 is set: clear all
15380 // coarsen flags on level 1 to avoid level 0 cells being created
15381 // by coarsening.
15382 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
15383 n_levels() >= 2)
15384 {
15385 for (const auto &cell : active_cell_iterators_on_level(1))
15386 cell->clear_coarsen_flag();
15387 }
15388
15389 bool mesh_changed_in_this_loop = false;
15390 do
15391 {
15392 //------------------------------------
15393 // STEP 1:
15394 // do not coarsen a cell if 'most of the neighbors' will be
15395 // refined after the step. This is to prevent the occurrence
15396 // of unrefined islands. If patch_level_1 is set, this will
15397 // be automatically fulfilled.
15398 if (smooth_grid & do_not_produce_unrefined_islands &&
15399 !(smooth_grid & patch_level_1))
15400 {
15401 for (const auto &cell : cell_iterators())
15402 {
15403 // only do something if this
15404 // cell will be coarsened
15405 if (!cell->is_active() && cell_will_be_coarsened(cell))
15406 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
15407 }
15408 }
15409
15410
15411 //------------------------------------
15412 // STEP 2:
15413 // eliminate refined islands in the interior and at the
15414 // boundary. since they don't do much harm besides increasing
15415 // the number of degrees of freedom, doing this has a rather
15416 // low priority. If patch_level_1 is set, this will be
15417 // automatically fulfilled.
15418 //
15419 // there is one corner case to consider: if this is a
15420 // distributed triangulation, there may be refined islands on
15421 // the boundary of which we own only part (e.g. a single cell
15422 // in the corner of a domain). the rest of the island is
15423 // ghost cells and it *looks* like the area around it
15424 // (artificial cells) are coarser but this is only because
15425 // they may actually be equally fine on other
15426 // processors. it's hard to detect this case but we can do
15427 // the following: only set coarsen flags to remove this
15428 // refined island if all cells we want to set flags on are
15429 // locally owned
15430 if (smooth_grid & (eliminate_refined_inner_islands |
15431 eliminate_refined_boundary_islands) &&
15432 !(smooth_grid & patch_level_1))
15433 {
15434 for (const auto &cell : cell_iterators())
15435 if (!cell->is_active() ||
15436 (cell->is_active() && cell->refine_flag_set() &&
15437 cell->is_locally_owned()))
15438 {
15439 // check whether all children are active, i.e. not
15440 // refined themselves. This is a precondition that the
15441 // children may be coarsened away. If the cell is only
15442 // flagged for refinement, then all future children
15443 // will be active
15444 bool all_children_active = true;
15445 if (!cell->is_active())
15446 for (unsigned int c = 0; c < cell->n_children(); ++c)
15447 if (!cell->child(c)->is_active() ||
15448 cell->child(c)->is_ghost() ||
15449 cell->child(c)->is_artificial())
15450 {
15451 all_children_active = false;
15452 break;
15453 }
15454
15455 if (all_children_active)
15456 {
15457 // count number of refined and unrefined neighbors
15458 // of cell. neighbors on lower levels are counted
15459 // as unrefined since they can only get to the
15460 // same level as this cell by the next refinement
15461 // cycle
15462 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
15463
15464 // Keep track if this cell is at a periodic
15465 // boundary or not. TODO: We do not currently run
15466 // the algorithm for inner islands at a periodic
15467 // boundary (remains to be implemented), but we
15468 // also don't want to consider them
15469 // boundary_island cells as this can interfere
15470 // with 2:1 refinement across periodic faces.
15471 // Instead: just ignore those cells for this
15472 // smoothing operation below.
15473 bool at_periodic_boundary = false;
15474
15475 for (const unsigned int n :
15477 {
15478 const cell_iterator neighbor = cell->neighbor(n);
15479 if (neighbor.state() == IteratorState::valid)
15480 {
15481 ++total_neighbors;
15482
15483 if (!face_will_be_refined_by_neighbor(cell, n))
15484 ++unrefined_neighbors;
15485 }
15486 else if (cell->has_periodic_neighbor(n))
15487 {
15488 ++total_neighbors;
15489 at_periodic_boundary = true;
15490 }
15491 }
15492
15493 // if all neighbors unrefined: mark this cell for
15494 // coarsening or don't refine if marked for that
15495 //
15496 // also do the distinction between the two
15497 // versions of the eliminate_refined_*_islands
15498 // flag
15499 //
15500 // the last check is whether there are any
15501 // neighbors at all. if not so, then we are (e.g.)
15502 // on the coarsest grid with one cell, for which,
15503 // of course, we do not remove the refine flag.
15504 if ((unrefined_neighbors == total_neighbors) &&
15505 ((!cell->at_boundary() &&
15506 (smooth_grid & eliminate_refined_inner_islands)) ||
15507 (cell->at_boundary() && !at_periodic_boundary &&
15508 (smooth_grid &
15509 eliminate_refined_boundary_islands))) &&
15510 (total_neighbors != 0))
15511 {
15512 if (!cell->is_active())
15513 for (unsigned int c = 0; c < cell->n_children(); ++c)
15514 {
15515 cell->child(c)->clear_refine_flag();
15516 cell->child(c)->set_coarsen_flag();
15517 }
15518 else
15519 cell->clear_refine_flag();
15520 }
15521 }
15522 }
15523 }
15524
15525 //------------------------------------
15526 // STEP 3:
15527 // limit the level difference of neighboring cells at each
15528 // vertex.
15529 //
15530 // in case of anisotropic refinement this does not make
15531 // sense. as soon as one cell is anisotropically refined, an
15532 // Assertion is thrown. therefore we can ignore this problem
15533 // later on
15534 if (smooth_grid & limit_level_difference_at_vertices)
15535 {
15536 Assert(!anisotropic_refinement,
15537 ExcMessage("In case of anisotropic refinement the "
15538 "limit_level_difference_at_vertices flag for "
15539 "mesh smoothing must not be set!"));
15540
15541 // store highest level one of the cells adjacent to a vertex
15542 // belongs to
15543 std::vector<int> vertex_level(vertices.size(), 0);
15544 for (const auto &cell : active_cell_iterators())
15545 {
15546 if (cell->refine_flag_set())
15547 for (const unsigned int vertex :
15549 vertex_level[cell->vertex_index(vertex)] =
15550 std::max(vertex_level[cell->vertex_index(vertex)],
15551 cell->level() + 1);
15552 else if (!cell->coarsen_flag_set())
15553 for (const unsigned int vertex :
15555 vertex_level[cell->vertex_index(vertex)] =
15556 std::max(vertex_level[cell->vertex_index(vertex)],
15557 cell->level());
15558 else
15559 {
15560 // if coarsen flag is set then tentatively assume
15561 // that the cell will be coarsened. this isn't
15562 // always true (the coarsen flag could be removed
15563 // again) and so we may make an error here
15564 Assert(cell->coarsen_flag_set(), ExcInternalError());
15565 for (const unsigned int vertex :
15567 vertex_level[cell->vertex_index(vertex)] =
15568 std::max(vertex_level[cell->vertex_index(vertex)],
15569 cell->level() - 1);
15570 }
15571 }
15572
15573
15574 // loop over all cells in reverse order. do so because we
15575 // can then update the vertex levels on the adjacent
15576 // vertices and maybe already flag additional cells in this
15577 // loop
15578 //
15579 // note that not only may we have to add additional
15580 // refinement flags, but we will also have to remove
15581 // coarsening flags on cells adjacent to vertices that will
15582 // see refinement
15583 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
15584 if (cell->refine_flag_set() == false)
15585 {
15586 for (const unsigned int vertex :
15588 if (vertex_level[cell->vertex_index(vertex)] >=
15589 cell->level() + 1)
15590 {
15591 // remove coarsen flag...
15592 cell->clear_coarsen_flag();
15593
15594 // ...and if necessary also refine the current
15595 // cell, at the same time updating the level
15596 // information about vertices
15597 if (vertex_level[cell->vertex_index(vertex)] >
15598 cell->level() + 1)
15599 {
15600 cell->set_refine_flag();
15601
15602 for (const unsigned int v :
15604 vertex_level[cell->vertex_index(v)] =
15605 std::max(vertex_level[cell->vertex_index(v)],
15606 cell->level() + 1);
15607 }
15608
15609 // continue and see whether we may, for example,
15610 // go into the inner'if'
15611 // above based on a
15612 // different vertex
15613 }
15614 }
15615 }
15616
15617 //-----------------------------------
15618 // STEP 4:
15619 // eliminate unrefined islands. this has higher priority
15620 // since this diminishes the approximation properties not
15621 // only of the unrefined island, but also of the surrounding
15622 // patch.
15623 //
15624 // do the loop from finest to coarsest cells since we may
15625 // trigger a cascade by marking cells for refinement which
15626 // may trigger more cells further down below
15627 if (smooth_grid & eliminate_unrefined_islands)
15628 {
15629 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
15630 // only do something if cell is not already flagged for
15631 // (isotropic) refinement
15632 if (cell->refine_flag_set() !=
15634 possibly_refine_unrefined_island<dim, spacedim>(
15635 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
15636 }
15637
15638 //-------------------------------
15639 // STEP 5:
15640 // ensure patch level 1.
15641 //
15642 // Introduce some terminology:
15643 // - a cell that is refined
15644 // once is a patch of
15645 // level 1 simply called patch.
15646 // - a cell that is globally
15647 // refined twice is called
15648 // a patch of level 2.
15649 // - patch level n says that
15650 // the triangulation consists
15651 // of patches of level n.
15652 // This makes sense only
15653 // if the grid is already at
15654 // least n times globally
15655 // refined.
15656 //
15657 // E.g. from patch level 1 follows: if at least one of the
15658 // children of a cell is or will be refined than enforce all
15659 // children to be refined.
15660
15661 // This step 4 only sets refinement flags and does not set
15662 // coarsening flags.
15663 if (smooth_grid & patch_level_1)
15664 {
15665 // An important assumption (A) is that before calling this
15666 // function the grid was already of patch level 1.
15667
15668 // loop over all cells whose children are all active. (By
15669 // assumption (A) either all or none of the children are
15670 // active). If the refine flag of at least one of the
15671 // children is set then set_refine_flag and
15672 // clear_coarsen_flag of all children.
15673 for (const auto &cell : cell_iterators())
15674 if (!cell->is_active())
15675 {
15676 // ensure the invariant. we can then check whether all
15677 // of its children are further refined or not by
15678 // simply looking at the first child
15679 Assert(cell_is_patch_level_1(cell), ExcInternalError());
15680 if (cell->child(0)->has_children() == true)
15681 continue;
15682
15683 // cell is found to be a patch. combine the refine
15684 // cases of all children
15685 RefinementCase<dim> combined_ref_case =
15687 for (unsigned int i = 0; i < cell->n_children(); ++i)
15688 combined_ref_case =
15689 combined_ref_case | cell->child(i)->refine_flag_set();
15690 if (combined_ref_case != RefinementCase<dim>::no_refinement)
15691 for (unsigned int i = 0; i < cell->n_children(); ++i)
15692 {
15693 cell_iterator child = cell->child(i);
15694
15695 child->clear_coarsen_flag();
15696 child->set_refine_flag(combined_ref_case);
15697 }
15698 }
15699
15700 // The code above dealt with the case where we may get a
15701 // non-patch_level_1 mesh from refinement. Now also deal
15702 // with the case where we could get such a mesh by
15703 // coarsening. Coarsen the children (and remove the
15704 // grandchildren) only if all cell->grandchild(i)
15705 // ->coarsen_flag_set() are set.
15706 //
15707 // for a case where this is a bit tricky, take a look at the
15708 // mesh_smoothing_0[12] testcases
15709 for (const auto &cell : cell_iterators())
15710 {
15711 // check if this cell has active grandchildren. note
15712 // that we know that it is patch_level_1, i.e. if one of
15713 // its children is active then so are all, and it isn't
15714 // going to have any grandchildren at all:
15715 if (cell->is_active() || cell->child(0)->is_active())
15716 continue;
15717
15718 // cell is not active, and so are none of its
15719 // children. check the grandchildren. note that the
15720 // children are also patch_level_1, and so we only ever
15721 // need to check their first child
15722 const unsigned int n_children = cell->n_children();
15723 bool has_active_grandchildren = false;
15724
15725 for (unsigned int i = 0; i < n_children; ++i)
15726 if (cell->child(i)->child(0)->is_active())
15727 {
15728 has_active_grandchildren = true;
15729 break;
15730 }
15731
15732 if (has_active_grandchildren == false)
15733 continue;
15734
15735
15736 // ok, there are active grandchildren. see if either all
15737 // or none of them are flagged for coarsening
15738 unsigned int n_grandchildren = 0;
15739
15740 // count all coarsen flags of the grandchildren.
15741 unsigned int n_coarsen_flags = 0;
15742
15743 // cell is not a patch (of level 1) as it has a
15744 // grandchild. Is cell a patch of level 2?? Therefore:
15745 // find out whether all cell->child(i) are patches
15746 for (unsigned int c = 0; c < n_children; ++c)
15747 {
15748 // get at the child. by assumption (A), and the
15749 // check by which we got here, the child is not
15750 // active
15751 cell_iterator child = cell->child(c);
15752
15753 const unsigned int nn_children = child->n_children();
15754 n_grandchildren += nn_children;
15755
15756 // if child is found to be a patch of active cells
15757 // itself, then add up how many of its children are
15758 // supposed to be coarsened
15759 if (child->child(0)->is_active())
15760 for (unsigned int cc = 0; cc < nn_children; ++cc)
15761 if (child->child(cc)->coarsen_flag_set())
15762 ++n_coarsen_flags;
15763 }
15764
15765 // if not all grandchildren are supposed to be coarsened
15766 // (e.g. because some simply don't have the flag set, or
15767 // because they are not active and therefore cannot
15768 // carry the flag), then remove the coarsen flag from
15769 // all of the active grandchildren. note that there may
15770 // be coarsen flags on the grandgrandchildren -- we
15771 // don't clear them here, but we'll get to them in later
15772 // iterations if necessary
15773 //
15774 // there is nothing we have to do if no coarsen flags
15775 // have been set at all
15776 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
15777 for (unsigned int c = 0; c < n_children; ++c)
15778 {
15779 const cell_iterator child = cell->child(c);
15780 if (child->child(0)->is_active())
15781 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
15782 child->child(cc)->clear_coarsen_flag();
15783 }
15784 }
15785 }
15786
15787 //--------------------------------
15788 //
15789 // at the boundary we could end up with cells with negative
15790 // volume or at least with a part, that is negative, if the
15791 // cell is refined anisotropically. we have to check, whether
15792 // that can happen
15793 this->policy->prevent_distorted_boundary_cells(*this);
15794
15795 //-------------------------------
15796 // STEP 6:
15797 // take care of the requirement that no
15798 // double refinement is done at each face
15799 //
15800 // in case of anisotropic refinement it is only likely, but
15801 // not sure, that the cells, which are more refined along a
15802 // certain face common to two cells are on a higher
15803 // level. therefore we cannot be sure, that the requirement
15804 // of no double refinement is fulfilled after a single pass
15805 // of the following actions. We could just wait for the next
15806 // global loop. when this function terminates, the
15807 // requirement will be fulfilled. However, it might be faster
15808 // to insert an inner loop here.
15809 bool changed = true;
15810 while (changed)
15811 {
15812 changed = false;
15813 active_cell_iterator cell = last_active(), endc = end();
15814
15815 for (; cell != endc; --cell)
15816 if (cell->refine_flag_set())
15817 {
15818 // loop over neighbors of cell
15819 for (const auto i : cell->face_indices())
15820 {
15821 // only do something if the face is not at the
15822 // boundary and if the face will be refined with
15823 // the RefineCase currently flagged for
15824 const bool has_periodic_neighbor =
15825 cell->has_periodic_neighbor(i);
15826 const bool has_neighbor_or_periodic_neighbor =
15827 !cell->at_boundary(i) || has_periodic_neighbor;
15828 if (has_neighbor_or_periodic_neighbor &&
15830 cell->refine_flag_set(), i) !=
15832 {
15833 // 1) if the neighbor has children: nothing to
15834 // worry about. 2) if the neighbor is active
15835 // and a coarser one, ensure, that its
15836 // refine_flag is set 3) if the neighbor is
15837 // active and as refined along the face as our
15838 // current cell, make sure, that no
15839 // coarsen_flag is set. if we remove the
15840 // coarsen flag of our neighbor,
15841 // fix_coarsen_flags() makes sure, that the
15842 // mother cell will not be coarsened
15843 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
15844 {
15845 if ((!has_periodic_neighbor &&
15846 cell->neighbor_is_coarser(i)) ||
15847 (has_periodic_neighbor &&
15848 cell->periodic_neighbor_is_coarser(i)))
15849 {
15850 if (cell->neighbor_or_periodic_neighbor(i)
15851 ->coarsen_flag_set())
15852 cell->neighbor_or_periodic_neighbor(i)
15853 ->clear_coarsen_flag();
15854 // we'll set the refine flag for this
15855 // neighbor below. we note, that we
15856 // have changed something by setting
15857 // the changed flag to true. We do not
15858 // need to do so, if we just removed
15859 // the coarsen flag, as the changed
15860 // flag only indicates the need to
15861 // re-run the inner loop. however, we
15862 // only loop over cells flagged for
15863 // refinement here, so nothing to
15864 // worry about if we remove coarsen
15865 // flags
15866
15867 if (dim == 2)
15868 {
15869 if (smooth_grid &
15870 allow_anisotropic_smoothing)
15871 changed =
15872 has_periodic_neighbor ?
15873 cell->periodic_neighbor(i)
15874 ->flag_for_face_refinement(
15875 cell
15876 ->periodic_neighbor_of_coarser_periodic_neighbor(
15877 i)
15878 .first,
15880 cell->neighbor(i)
15881 ->flag_for_face_refinement(
15882 cell
15883 ->neighbor_of_coarser_neighbor(
15884 i)
15885 .first,
15887 else
15888 {
15889 if (!cell
15890 ->neighbor_or_periodic_neighbor(
15891 i)
15892 ->refine_flag_set())
15893 changed = true;
15894 cell->neighbor_or_periodic_neighbor(i)
15895 ->set_refine_flag();
15896 }
15897 }
15898 else // i.e. if (dim==3)
15899 {
15900 // ugly situations might arise here,
15901 // consider the following situation, which
15902 // shows neighboring cells at the common
15903 // face, where the upper right element is
15904 // coarser at the given face. Now the upper
15905 // child element of the lower left wants to
15906 // refine according to cut_z, such that
15907 // there is a 'horizontal' refinement of the
15908 // face marked with #####
15909 //
15910 // / /
15911 // / /
15912 // *---------------*
15913 // | |
15914 // | |
15915 // | |
15916 // | |
15917 // | |
15918 // | | /
15919 // | |/
15920 // *---------------*
15921 //
15922 //
15923 // *---------------*
15924 // /| /|
15925 // / | ##### / |
15926 // | |
15927 // *---------------*
15928 // /| /|
15929 // / | / |
15930 // | |
15931 // *---------------*
15932 // / /
15933 // / /
15934 //
15935 // this introduces too many hanging nodes
15936 // and the neighboring (coarser) cell (upper
15937 // right) has to be refined. If it is only
15938 // refined according to cut_z, then
15939 // everything is ok:
15940 //
15941 // / /
15942 // / /
15943 // *---------------*
15944 // | |
15945 // | | /
15946 // | |/
15947 // *---------------*
15948 // | |
15949 // | | /
15950 // | |/
15951 // *---------------*
15952 //
15953 //
15954 // *---------------*
15955 // /| /|
15956 // / *---------------*
15957 // /| /|
15958 // *---------------*
15959 // /| /|
15960 // / | / |
15961 // | |
15962 // *---------------*
15963 // / /
15964 // / /
15965 //
15966 // if however the cell wants to refine
15967 // itself in an other way, or if we disallow
15968 // anisotropic smoothing, then simply
15969 // refining the neighbor isotropically is
15970 // not going to work, since this introduces
15971 // a refinement of face ##### with both
15972 // cut_x and cut_y, which is not possible:
15973 //
15974 // / / /
15975 // / / /
15976 // *-------*-------*
15977 // | | |
15978 // | | | /
15979 // | | |/
15980 // *-------*-------*
15981 // | | |
15982 // | | | /
15983 // | | |/
15984 // *-------*-------*
15985 //
15986 //
15987 // *---------------*
15988 // /| /|
15989 // / *---------------*
15990 // /| /|
15991 // *---------------*
15992 // /| /|
15993 // / | / |
15994 // | |
15995 // *---------------*
15996 // / /
15997 // / /
15998 //
15999 // thus, in this case we also need to refine
16000 // our current cell in the new direction:
16001 //
16002 // / / /
16003 // / / /
16004 // *-------*-------*
16005 // | | |
16006 // | | | /
16007 // | | |/
16008 // *-------*-------*
16009 // | | |
16010 // | | | /
16011 // | | |/
16012 // *-------*-------*
16013 //
16014 //
16015 // *-------*-------*
16016 // /| /| /|
16017 // / *-------*-------*
16018 // /| /| /|
16019 // *-------*-------*
16020 // /| / /|
16021 // / | / |
16022 // | |
16023 // *---------------*
16024 // / /
16025 // / /
16026
16027 std::pair<unsigned int, unsigned int>
16028 nb_indices =
16029 has_periodic_neighbor ?
16030 cell
16031 ->periodic_neighbor_of_coarser_periodic_neighbor(
16032 i) :
16033 cell->neighbor_of_coarser_neighbor(i);
16034 unsigned int refined_along_x = 0,
16035 refined_along_y = 0,
16036 to_be_refined_along_x = 0,
16037 to_be_refined_along_y = 0;
16038
16039 const int this_face_index =
16040 cell->face_index(i);
16041
16042 // step 1: detect, along which axis the face
16043 // is currently refined
16044
16045 // first, we need an iterator pointing to
16046 // the parent face. This requires a slight
16047 // detour in case the neighbor is behind a
16048 // periodic face.
16049 const auto parent_face = [&]() {
16050 if (has_periodic_neighbor)
16051 {
16052 const auto neighbor =
16053 cell->periodic_neighbor(i);
16054 const auto parent_face_no =
16055 neighbor
16056 ->periodic_neighbor_of_periodic_neighbor(
16057 nb_indices.first);
16058 auto parent =
16059 neighbor->periodic_neighbor(
16060 nb_indices.first);
16061 return parent->face(parent_face_no);
16062 }
16063 else
16064 return cell->neighbor(i)->face(
16065 nb_indices.first);
16066 }();
16067
16068 if ((this_face_index ==
16069 parent_face->child_index(0)) ||
16070 (this_face_index ==
16071 parent_face->child_index(1)))
16072 {
16073 // this might be an
16074 // anisotropic child. get the
16075 // face refine case of the
16076 // neighbors face and count
16077 // refinements in x and y
16078 // direction.
16079 RefinementCase<dim - 1> frc =
16080 parent_face->refinement_case();
16082 ++refined_along_x;
16084 ++refined_along_y;
16085 }
16086 else
16087 // this has to be an isotropic
16088 // child
16089 {
16090 ++refined_along_x;
16091 ++refined_along_y;
16092 }
16093 // step 2: detect, along which axis the face
16094 // has to be refined given the current
16095 // refine flag
16096 RefinementCase<dim - 1> flagged_frc =
16098 cell->refine_flag_set(),
16099 i,
16100 cell->face_orientation(i),
16101 cell->face_flip(i),
16102 cell->face_rotation(i));
16103 if (flagged_frc &
16105 ++to_be_refined_along_x;
16106 if (flagged_frc &
16108 ++to_be_refined_along_y;
16109
16110 // step 3: set the refine flag of the
16111 // (coarser and active) neighbor.
16112 if ((smooth_grid &
16113 allow_anisotropic_smoothing) ||
16114 cell->neighbor_or_periodic_neighbor(i)
16115 ->refine_flag_set())
16116 {
16117 if (refined_along_x +
16118 to_be_refined_along_x >
16119 1)
16120 changed |=
16121 cell
16122 ->neighbor_or_periodic_neighbor(i)
16123 ->flag_for_face_refinement(
16124 nb_indices.first,
16125 RefinementCase<dim -
16126 1>::cut_axis(0));
16127 if (refined_along_y +
16128 to_be_refined_along_y >
16129 1)
16130 changed |=
16131 cell
16132 ->neighbor_or_periodic_neighbor(i)
16133 ->flag_for_face_refinement(
16134 nb_indices.first,
16135 RefinementCase<dim -
16136 1>::cut_axis(1));
16137 }
16138 else
16139 {
16140 if (cell
16141 ->neighbor_or_periodic_neighbor(i)
16142 ->refine_flag_set() !=
16144 dim>::isotropic_refinement)
16145 changed = true;
16146 cell->neighbor_or_periodic_neighbor(i)
16147 ->set_refine_flag();
16148 }
16149
16150 // step 4: if necessary (see above) add to
16151 // the refine flag of the current cell
16152 cell_iterator nb =
16153 cell->neighbor_or_periodic_neighbor(i);
16154 RefinementCase<dim - 1> nb_frc =
16156 nb->refine_flag_set(),
16157 nb_indices.first,
16158 nb->face_orientation(nb_indices.first),
16159 nb->face_flip(nb_indices.first),
16160 nb->face_rotation(nb_indices.first));
16161 if ((nb_frc & RefinementCase<dim>::cut_x) &&
16162 !((refined_along_x != 0u) ||
16163 (to_be_refined_along_x != 0u)))
16164 changed |= cell->flag_for_face_refinement(
16165 i,
16167 if ((nb_frc & RefinementCase<dim>::cut_y) &&
16168 !((refined_along_y != 0u) ||
16169 (to_be_refined_along_y != 0u)))
16170 changed |= cell->flag_for_face_refinement(
16171 i,
16173 }
16174 } // if neighbor is coarser
16175 else // -> now the neighbor is not coarser
16176 {
16177 cell->neighbor_or_periodic_neighbor(i)
16178 ->clear_coarsen_flag();
16179 const unsigned int nb_nb =
16180 has_periodic_neighbor ?
16181 cell
16182 ->periodic_neighbor_of_periodic_neighbor(
16183 i) :
16184 cell->neighbor_of_neighbor(i);
16185 const cell_iterator neighbor =
16186 cell->neighbor_or_periodic_neighbor(i);
16187 RefinementCase<dim - 1> face_ref_case =
16189 neighbor->refine_flag_set(),
16190 nb_nb,
16191 neighbor->face_orientation(nb_nb),
16192 neighbor->face_flip(nb_nb),
16193 neighbor->face_rotation(nb_nb));
16194 RefinementCase<dim - 1> needed_face_ref_case =
16196 cell->refine_flag_set(),
16197 i,
16198 cell->face_orientation(i),
16199 cell->face_flip(i),
16200 cell->face_rotation(i));
16201 // if the neighbor wants to refine the
16202 // face with cut_x and we want cut_y
16203 // or vice versa, we have to refine
16204 // isotropically at the given face
16205 if ((face_ref_case ==
16207 needed_face_ref_case ==
16209 (face_ref_case ==
16211 needed_face_ref_case ==
16213 {
16214 changed = cell->flag_for_face_refinement(
16215 i, face_ref_case);
16216 neighbor->flag_for_face_refinement(
16217 nb_nb, needed_face_ref_case);
16218 }
16219 }
16220 }
16221 else //-> the neighbor is not active
16222 {
16223 RefinementCase<dim - 1>
16224 face_ref_case = cell->face(i)->refinement_case(),
16225 needed_face_ref_case =
16227 cell->refine_flag_set(),
16228 i,
16229 cell->face_orientation(i),
16230 cell->face_flip(i),
16231 cell->face_rotation(i));
16232 // if the face is refined with cut_x and
16233 // we want cut_y or vice versa, we have to
16234 // refine isotropically at the given face
16235 if ((face_ref_case == RefinementCase<dim>::cut_x &&
16236 needed_face_ref_case ==
16238 (face_ref_case == RefinementCase<dim>::cut_y &&
16239 needed_face_ref_case ==
16241 changed =
16242 cell->flag_for_face_refinement(i,
16243 face_ref_case);
16244 }
16245 }
16246 }
16247 }
16248 }
16249
16250 //------------------------------------
16251 // STEP 7:
16252 // take care that no double refinement
16253 // is done at each line in 3d or higher
16254 // dimensions.
16255 this->policy->prepare_refinement_dim_dependent(*this);
16256
16257 //------------------------------------
16258 // STEP 8:
16259 // make sure that all children of each
16260 // cell are either flagged for coarsening
16261 // or none of the children is
16262 fix_coarsen_flags();
16263 // get the refinement and coarsening
16264 // flags
16265 std::vector<bool> flags_after_loop[2];
16266 save_coarsen_flags(flags_after_loop[0]);
16267 save_refine_flags(flags_after_loop[1]);
16268
16269 // find out whether something was
16270 // changed in this loop
16271 mesh_changed_in_this_loop =
16272 ((flags_before_loop[0] != flags_after_loop[0]) ||
16273 (flags_before_loop[1] != flags_after_loop[1]));
16274
16275 // set the flags for the next loop
16276 // already
16277 flags_before_loop[0].swap(flags_after_loop[0]);
16278 flags_before_loop[1].swap(flags_after_loop[1]);
16279 }
16280 while (mesh_changed_in_this_loop);
16281
16282
16283 // find out whether something was really changed in this
16284 // function. Note that @p{flags_before_loop} represents the state
16285 // after the last loop, i.e. the present state
16286 return ((flags_before[0] != flags_before_loop[0]) ||
16287 (flags_before[1] != flags_before_loop[1]));
16288}
16289
16290
16291
16292template <int dim, int spacedim>
16293void
16295 const unsigned int magic_number1,
16296 const std::vector<bool> &v,
16297 const unsigned int magic_number2,
16298 std::ostream & out)
16299{
16300 const unsigned int N = v.size();
16301 unsigned char * flags = new unsigned char[N / 8 + 1];
16302 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16303 flags[i] = 0;
16304
16305 for (unsigned int position = 0; position < N; ++position)
16306 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
16307
16308 AssertThrow(out.fail() == false, ExcIO());
16309
16310 // format:
16311 // 0. magic number
16312 // 1. number of flags
16313 // 2. the flags
16314 // 3. magic number
16315 out << magic_number1 << ' ' << N << std::endl;
16316 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16317 out << static_cast<unsigned int>(flags[i]) << ' ';
16318
16319 out << std::endl << magic_number2 << std::endl;
16320
16321 delete[] flags;
16322
16323 AssertThrow(out.fail() == false, ExcIO());
16324}
16325
16326
16327template <int dim, int spacedim>
16328void
16329Triangulation<dim, spacedim>::read_bool_vector(const unsigned int magic_number1,
16330 std::vector<bool> &v,
16331 const unsigned int magic_number2,
16332 std::istream & in)
16333{
16334 AssertThrow(in.fail() == false, ExcIO());
16335
16336 unsigned int magic_number;
16337 in >> magic_number;
16338 AssertThrow(magic_number == magic_number1, ExcGridReadError());
16339
16340 unsigned int N;
16341 in >> N;
16342 v.resize(N);
16343
16344 unsigned char * flags = new unsigned char[N / 8 + 1];
16345 unsigned short int tmp;
16346 for (unsigned int i = 0; i < N / 8 + 1; ++i)
16347 {
16348 in >> tmp;
16349 flags[i] = tmp;
16350 }
16351
16352 for (unsigned int position = 0; position != N; ++position)
16353 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
16354
16355 in >> magic_number;
16356 AssertThrow(magic_number == magic_number2, ExcGridReadError());
16357
16358 delete[] flags;
16359
16360 AssertThrow(in.fail() == false, ExcIO());
16361}
16362
16363
16364
16365template <int dim, int spacedim>
16366std::size_t
16368{
16369 std::size_t mem = 0;
16371 for (const auto &level : levels)
16374 mem += MemoryConsumption::memory_consumption(vertices_used);
16375 mem += sizeof(manifolds);
16376 mem += sizeof(smooth_grid);
16377 mem += MemoryConsumption::memory_consumption(number_cache);
16378 mem += sizeof(faces);
16379 if (faces)
16381
16382 return mem;
16383}
16384
16385
16386
16387template <int dim, int spacedim>
16389 default;
16390
16391
16392// explicit instantiations
16393#include "tria.inst"
16394
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
unsigned char compute_orientation(const std::array< T, N > &vertices_0, const std::array< T, N > &vertices_1) const
Subscriptor & operator=(const Subscriptor &)
Definition: subscriptor.h:291
Definition: tensor.h:503
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition: tria.h:3795
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:4172
virtual void clear()
bool anisotropic_refinement
Definition: tria.h:4184
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition: tria.h:4242
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, std::bitset< 3 > > > periodic_face_map
Definition: tria.h:3775
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:4167
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:4191
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:4219
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:3706
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:4161
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
void load_user_indices_line(const std::vector< unsigned int > &v)
void clear_user_flags_hex()
void save_user_pointers_hex(std::vector< void * > &v) const
const std::vector< ReferenceCell > & get_reference_cells() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition: tria.h:3796
void load_user_pointers(const std::vector< void * > &v)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition: tria.h:4202
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
active_line_iterator begin_active_line(const unsigned int level=0) const
void save_user_indices_quad(std::vector< unsigned int > &v) const
void load_user_pointers_hex(const std::vector< void * > &v)
cell_iterator end() const
virtual bool has_hanging_nodes() const
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition: tria.h:3767
unsigned int n_raw_cells(const unsigned int level) const
void load_coarsen_flags(std::istream &out)
quad_iterator end_quad() const
line_iterator begin_line(const unsigned int level=0) const
unsigned int max_adjacent_cells() const
vertex_iterator begin_vertex() const
void clear_user_flags()
unsigned int n_hexs() const
vertex_iterator end_vertex() const
void load_user_pointers_line(const std::vector< void * > &v)
hex_iterator end_hex() const
hex_iterator begin_hex(const unsigned int level=0) const
virtual void execute_coarsening_and_refinement()
active_cell_iterator end_active(const unsigned int level) const
bool is_mixed_mesh() const
cell_iterator last() const
unsigned int n_active_quads() const
void load_user_indices_hex(const std::vector< unsigned int > &v)
unsigned int n_raw_quads() const
void save_user_pointers(std::vector< void * > &v) const
face_iterator begin_face() const
unsigned int n_cells() const
virtual bool prepare_coarsening_and_refinement()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition: tria.h:3797
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifolds
Definition: tria.h:4179
MeshSmoothing smooth_grid
Definition: tria.h:3700
void save_refine_flags(std::ostream &out) const
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition: tria.h:3758
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition: tria.h:2448
virtual ~Triangulation() override
void save_user_indices(std::vector< unsigned int > &v) const
bool all_reference_cells_are_simplex() const
std::vector< std::unique_ptr<::internal::TriangulationImplementation::TriaLevel > > levels
Definition: tria.h:4153
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:1683
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition: tria.cc:1690
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:1666
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition: tria.cc:1660
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition: tria.cc:1697
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition: tria.cc:1676
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition: tria.cc:1705
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:442
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
Point< 3 > vertices[4]
Point< 2 > second
Definition: grid_out.cc:4604
Point< 2 > first
Definition: grid_out.cc:4603
unsigned int level
Definition: grid_out.cc:4606
AdjacentCell adjacent_cells[2]
Definition: grid_tools.cc:1213
unsigned int vertex_indices[2]
Definition: grid_tools.cc:1293
unsigned int cell_index
Definition: grid_tools.cc:1129
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:578
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:1473
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:532
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1667
static ::ExceptionBase & ExcLineInexistant(int arg1, int arg2)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
Definition: exceptions.h:1536
#define AssertIndexRange(index, range)
Definition: exceptions.h:1732
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:555
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:509
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:604
#define AssertThrow(cond, exc)
Definition: exceptions.h:1583
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition: tria.h:1490
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition: tria.h:1481
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition: tria.h:1501
typename IteratorSelector::quad_iterator quad_iterator
Definition: tria.h:1466
typename IteratorSelector::line_iterator line_iterator
Definition: tria.h:1442
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition: tria.h:1355
typename IteratorSelector::active_line_iterator active_line_iterator
Definition: tria.h:1457
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
#define AssertIsNotUsed(obj)
Definition: exceptions.h:1767
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:260
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
@ valid
Iterator points to a valid object.
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
bool get_bit(const unsigned char number, const unsigned int n)
Definition: utilities.h:1707
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition: tria.cc:13741
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition: tria.cc:11131
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition: tria.cc:13734
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition: tria.cc:1119
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition: tria.cc:1322
const types::boundary_id internal_face_boundary_id
Definition: types.h:260
const types::subdomain_id invalid_subdomain_id
Definition: types.h:281
static const unsigned int invalid_unsigned_int
Definition: types.h:201
const types::manifold_id flat_manifold_id
Definition: types.h:269
const types::global_dof_index invalid_dof_index
Definition: types.h:216
::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 > &)
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:1536
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition: tria.h:2146
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition: tria.cc:11007
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition: tria.cc:11118
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:11092
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:11011
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:11077
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:11110
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:11101
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition: tria.cc:2018
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition: tria.cc:2705
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition: tria.cc:2646
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition: tria.cc:10655
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:2118
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition: tria.cc:10743
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:3000
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition: tria.cc:2668
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition: tria.cc:2112
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:6299
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:3997
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:3630
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition: tria.cc:1911
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition: tria.cc:10662
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition: tria.cc:1823
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition: tria.cc:10937
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:2758
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition: tria.cc:10753
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:2862
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition: tria.cc:4506
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:5046
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:2297
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition: tria.cc:4737
static void process_subcelldata(const CRS< T > &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition: tria.cc:2539
std::vector< std::vector< CellData< dim > > > cell_infos
const ::Triangulation< dim, spacedim > & tria