deal.II version GIT relicensing-2659-g040196caa3 2025-02-18 14:20:01+00:00
\(\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// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1999 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15
18#include <deal.II/base/mpi.templates.h>
23
26
31#include <deal.II/grid/tria.h>
37
38#include <boost/archive/text_iarchive.hpp>
39#include <boost/archive/text_oarchive.hpp>
40
41#include <algorithm>
42#include <array>
43#include <cmath>
44#include <cstdint>
45#include <fstream>
46#include <functional>
47#include <limits>
48#include <list>
49#include <map>
50#include <memory>
51#include <numeric>
52
53
55
56
57namespace internal
58{
59 namespace TriangulationImplementation
60 {
62 : n_levels(0)
63 , n_lines(0)
64 , n_active_lines(0)
65 // all other fields are
66 // default constructed
67 {}
68
69
70
71 std::size_t
73 {
74 std::size_t mem =
79 MemoryConsumption::memory_consumption(n_active_lines_level);
80
81 if (active_cell_index_partitioner)
82 mem += active_cell_index_partitioner->memory_consumption();
83
84 for (const auto &partitioner : level_cell_index_partitioners)
85 if (partitioner)
86 mem += partitioner->memory_consumption();
87
88 return mem;
89 }
90
91
93 : n_quads(0)
94 , n_active_quads(0)
95 // all other fields are
96 // default constructed
97 {}
98
99
100
101 std::size_t
110
111
112
114 : n_hexes(0)
115 , n_active_hexes(0)
116 // all other fields are
117 // default constructed
118 {}
119
120
121
122 std::size_t
131 } // namespace TriangulationImplementation
132
133
134 template <int dim, int spacedim>
137 : variable_size_data_stored(false)
138 {}
139
140
141 template <int dim, int spacedim>
143 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
145 const std::vector<
146 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
147 &pack_callbacks_fixed,
148 const std::vector<
149 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
150 &pack_callbacks_variable,
151 const MPI_Comm &mpi_communicator)
152 {
153 Assert(src_data_fixed.empty(),
154 ExcMessage("Previously packed data has not been released yet!"));
155 Assert(src_sizes_variable.empty(), ExcInternalError());
156
157 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
158 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
159
160 // Store information that we packed variable size data in
161 // a member variable for later.
162 variable_size_data_stored = (n_callbacks_variable > 0);
163
164 // If variable transfer is scheduled, we will store the data size that
165 // each variable size callback function writes in this auxiliary
166 // container. The information will be stored by each cell in this vector
167 // temporarily.
168 std::vector<unsigned int> cell_sizes_variable_cumulative(
170
171 // Prepare the buffer structure, in which each callback function will
172 // store its data for each active cell.
173 // The outmost shell in this container construct corresponds to the
174 // data packed per cell. The next layer resembles the data that
175 // each callback function packs on the corresponding cell. These
176 // buffers are chains of chars stored in an std::vector<char>.
177 // A visualisation of the data structure:
178 /* clang-format off */
179 // | cell_1 | | cell_2 | ...
180 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
181 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
182 /* clang-format on */
183 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
184 cell_relations.size());
185 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
186 variable_size_data_stored ? cell_relations.size() : 0);
187
188 //
189 // --------- Pack data for fixed and variable size transfer ---------
190 //
191 // Iterate over all cells, call all callback functions on each cell,
192 // and store their data in the corresponding buffer scope.
193 {
194 auto cell_rel_it = cell_relations.cbegin();
197 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
198 {
199 const auto &dealii_cell = cell_rel_it->first;
200 const auto &cell_status = cell_rel_it->second;
201
202 // Assertions about the tree structure.
203 switch (cell_status)
204 {
207 // double check the condition that we will only ever attach
208 // data to active cells when we get here
209 Assert(dealii_cell->is_active(), ExcInternalError());
210 break;
211
213 // double check the condition that we will only ever attach
214 // data to cells with children when we get here. however, we
215 // can only tolerate one level of coarsening at a time, so
216 // check that the children are all active
217 Assert(dealii_cell->is_active() == false, ExcInternalError());
218 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
219 Assert(dealii_cell->child(c)->is_active(),
221 break;
222
224 // do nothing on invalid cells
225 break;
226
227 default:
229 break;
230 }
231
232 // Reserve memory corresponding to the number of callback
233 // functions that will be called.
234 // If variable size transfer is scheduled, we need to leave
235 // room for an array that holds information about how many
236 // bytes each of the variable size callback functions will
237 // write.
238 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
239 // will be stored.
240 const unsigned int n_fixed_size_data_sets_on_cell =
242 0 :
243 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
245
246 // We continue with packing all data on this specific cell.
247 auto data_fixed_it = data_cell_fixed_it->begin();
248
249 // First, we pack the CellStatus information.
250 // to get consistent data sizes on each cell for the fixed size
251 // transfer, we won't allow compression
253 Utilities::pack(cell_status, /*allow_compression=*/false);
255
256 // Proceed with all registered callback functions.
257 // Skip cells with the CellStatus::cell_invalid flag.
259 {
260 // Pack fixed size data.
261 for (auto callback_it = pack_callbacks_fixed.cbegin();
262 callback_it != pack_callbacks_fixed.cend();
264 {
265 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
266 }
267
268 // Pack variable size data.
269 // If we store variable size data, we need to transfer
270 // the sizes of each corresponding callback function
271 // via fixed size transfer as well.
272 if (variable_size_data_stored)
273 {
274 const unsigned int n_variable_size_data_sets_on_cell =
276 0 :
278 data_cell_variable_it->resize(
280
281 auto callback_it = pack_callbacks_variable.cbegin();
283 auto sizes_variable_it =
285 for (; callback_it != pack_callbacks_variable.cend();
287 {
289 (*callback_it)(dealii_cell, cell_status);
290
291 // Store data sizes for each callback function first.
292 // Make it cumulative below.
294 }
295
296 // Turn size vector into its cumulative representation.
297 std::partial_sum(cell_sizes_variable_cumulative.begin(),
300
301 // Serialize cumulative variable size vector
302 // value-by-value. This way we can circumvent the overhead
303 // of storing the container object as a whole, since we
304 // know its size by the number of registered callback
305 // functions.
307 sizeof(unsigned int));
308 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
309 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
311 sizeof(unsigned int));
312
314 }
315
316 // Double check that we packed everything we wanted
317 // in the fixed size buffers.
320 }
321
323
324 // Increment the variable size data iterator
325 // only if we actually pack this kind of data
326 // to avoid getting out of bounds.
327 if (variable_size_data_stored)
329 } // loop over cell_relations
330 }
331
332 //
333 // ----------- Gather data sizes for fixed size transfer ------------
334 //
335 // Generate a vector which stores the sizes of each callback function,
336 // including the packed CellStatus transfer.
337 // Find the very first cell that we wrote to with all callback
338 // functions (i.e. a cell that was not flagged with
339 // CellStatus::cell_invalid) and store the sizes of each buffer.
340 //
341 // To deal with the case that at least one of the processors does not
342 // own any cell at all, we will exchange the information about the data
343 // sizes among them later. The code in between is still well-defined,
344 // since the following loops will be skipped.
345 std::vector<unsigned int> local_sizes_fixed(
346 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
347 for (const auto &data_cell : packed_fixed_size_data)
348 {
349 if (data_cell.size() == local_sizes_fixed.size())
350 {
351 auto sizes_fixed_it = local_sizes_fixed.begin();
352 auto data_fixed_it = data_cell.cbegin();
353 for (; data_fixed_it != data_cell.cend();
355 {
356 *sizes_fixed_it = data_fixed_it->size();
357 }
358
359 break;
360 }
361 }
362
363 // Check if all cells have valid sizes.
364 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
367 {
368 Assert((data_cell_fixed_it->size() == 1) ||
369 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
371 }
372
373 // Share information about the packed data sizes
374 // of all callback functions across all processors, in case one
375 // of them does not own any cells at all.
376 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
378 mpi_communicator,
380
381 // Construct cumulative sizes, since this is the only information
382 // we need from now on.
383 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
384 std::partial_sum(global_sizes_fixed.begin(),
385 global_sizes_fixed.end(),
386 sizes_fixed_cumulative.begin());
387
388 //
389 // ---------- Gather data sizes for variable size transfer ----------
390 //
391 if (variable_size_data_stored)
392 {
393 src_sizes_variable.reserve(packed_variable_size_data.size());
394 for (const auto &data_cell : packed_variable_size_data)
395 {
397
398 for (const auto &data : data_cell)
400
401 src_sizes_variable.push_back(variable_data_size_on_cell);
402 }
403 }
404
405 //
406 // ------------------------ Build buffers ---------------------------
407 //
408 const unsigned int expected_size_fixed =
409 cell_relations.size() * sizes_fixed_cumulative.back();
410 const unsigned int expected_size_variable =
411 std::accumulate(src_sizes_variable.begin(),
412 src_sizes_variable.end(),
413 std::vector<int>::size_type(0));
414
415 // Move every piece of packed fixed size data into the consecutive
416 // buffer.
417 src_data_fixed.reserve(expected_size_fixed);
418 for (const auto &data_cell_fixed : packed_fixed_size_data)
419 {
420 // Move every fraction of packed data into the buffer
421 // reserved for this particular cell.
422 for (const auto &data_fixed : data_cell_fixed)
423 std::move(data_fixed.begin(),
424 data_fixed.end(),
425 std::back_inserter(src_data_fixed));
426
427 // If we only packed the CellStatus information
428 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
429 // fill the remaining space with invalid entries.
430 // We can skip this if there is nothing else to pack.
431 if ((data_cell_fixed.size() == 1) &&
432 (sizes_fixed_cumulative.size() > 1))
433 {
434 const std::size_t bytes_skipped =
435 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
436
437 src_data_fixed.insert(src_data_fixed.end(),
439 static_cast<char>(-1)); // invalid_char
441 }
442
443 // Move every piece of packed variable size data into the consecutive
444 // buffer.
445 if (variable_size_data_stored)
446 {
447 src_data_variable.reserve(expected_size_variable);
448 for (const auto &data_cell : packed_variable_size_data)
449 {
450 // Move every fraction of packed data into the buffer
451 // reserved for this particular cell.
452 for (const auto &data : data_cell)
453 std::move(data.begin(),
454 data.end(),
455 std::back_inserter(src_data_variable));
456 }
457 }
458
459 // Double check that we packed everything correctly.
460 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
461 Assert(src_data_variable.size() == expected_size_variable,
463 }
465
466
467 template <int dim, int spacedim>
469 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
470 std::vector<
472 &cell_relations) const
473 {
474 Assert(sizes_fixed_cumulative.size() > 0,
475 ExcMessage("No data has been packed!"));
476 if (cell_relations.size() > 0)
477 {
478 Assert(dest_data_fixed.size() > 0,
479 ExcMessage("No data has been received!"));
480 }
481
482 // Size of CellStatus object that will be unpacked on each cell.
483 const unsigned int size = sizes_fixed_cumulative.front();
484
485 // Iterate over all cells and overwrite the CellStatus
486 // information from the transferred data.
487 // Proceed buffer iterator position to next cell after
488 // each iteration.
489 auto cell_rel_it = cell_relations.begin();
490 auto dest_fixed_it = dest_data_fixed.cbegin();
491 for (; cell_rel_it != cell_relations.end();
492 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
493 {
494 cell_rel_it->second = // cell_status
495 Utilities::unpack<CellStatus>(dest_fixed_it,
497 /*allow_compression=*/false);
498 }
499 }
500
501
502
503 template <int dim, int spacedim>
505 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
506 const std::vector<
509 const unsigned int handle,
510 const std::function<
511 void(const cell_iterator &,
513 const boost::iterator_range<std::vector<char>::const_iterator> &)>
514 &unpack_callback) const
515 {
516 // We decode the handle returned by register_data_attach() back into
517 // a format we can use. All even handles belong to those callback
518 // functions which write/read variable size data, all odd handles
519 // interact with fixed size buffers.
520 const bool callback_variable_transfer = (handle % 2 == 0);
521 const unsigned int callback_index = handle / 2;
522
523 // Cells will always receive fixed size data (i.e., CellStatus
524 // information), but not necessarily variable size data (e.g., with a
525 // ParticleHandler a cell might not contain any particle at all).
526 // Thus it is sufficient to check if fixed size data has been received.
527 Assert(sizes_fixed_cumulative.size() > 0,
528 ExcMessage("No data has been packed!"));
529 if (cell_relations.size() > 0)
530 {
531 Assert(dest_data_fixed.size() > 0,
532 ExcMessage("No data has been received!"));
533 }
534
535 std::vector<char>::const_iterator dest_data_it;
536 std::vector<char>::const_iterator dest_sizes_cell_it;
537
538 // Depending on whether our callback function unpacks fixed or
539 // variable size data, we have to pursue different approaches
540 // to localize the correct fraction of the buffer from which
541 // we are allowed to read.
542 unsigned int offset = numbers::invalid_unsigned_int;
543 unsigned int size = numbers::invalid_unsigned_int;
545
547 {
548 // For the variable size data, we need to extract the
549 // data size from the fixed size buffer on each cell.
550 //
551 // We packed this information last, so the last packed
552 // object in the fixed size buffer corresponds to the
553 // variable data sizes.
554 //
555 // The last entry of sizes_fixed_cumulative corresponds
556 // to the size of all fixed size data packed on the cell.
557 // To get the offset for the last packed object, we need
558 // to get the next-to-last entry.
559 const unsigned int offset_variable_data_sizes =
560 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
561
562 // This iterator points to the data size that the
563 // callback_function packed for each specific cell.
564 // Adjust buffer iterator to the offset of the callback
565 // function so that we only have to advance its position
566 // to the next cell after each iteration.
567 dest_sizes_cell_it = dest_data_fixed.cbegin() +
569 callback_index * sizeof(unsigned int);
570
571 // Let the data iterator point to the correct buffer.
572 dest_data_it = dest_data_variable.cbegin();
573 }
574 else
575 {
576 // For the fixed size data, we can get the information about
577 // the buffer location on each cell directly from the
578 // sizes_fixed_cumulative vector.
579 offset = sizes_fixed_cumulative[callback_index];
580 size = sizes_fixed_cumulative[callback_index + 1] - offset;
581 data_increment = sizes_fixed_cumulative.back();
582
583 // Let the data iterator point to the correct buffer.
584 // Adjust buffer iterator to the offset of the callback
585 // function so that we only have to advance its position
586 // to the next cell after each iteration.
587 if (cell_relations.begin() != cell_relations.end())
588 dest_data_it = dest_data_fixed.cbegin() + offset;
589 }
590
591 // Iterate over all cells and unpack the transferred data.
592 auto cell_rel_it = cell_relations.begin();
593 auto dest_sizes_it = dest_sizes_variable.cbegin();
594 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
595 {
596 const auto &dealii_cell = cell_rel_it->first;
597 const auto &cell_status = cell_rel_it->second;
598
600 {
601 // Update the increment according to the whole data size
602 // of the current cell.
604
606 {
607 // Extract the corresponding values for offset and size from
608 // the cumulative sizes array stored in the fixed size
609 // buffer.
610 if (callback_index == 0)
611 offset = 0;
612 else
613 std::memcpy(&offset,
614 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
615 sizeof(unsigned int));
616
617 std::memcpy(&size,
619 sizeof(unsigned int));
620
621 size -= offset;
622
623 // Move the data iterator to the corresponding position
624 // of the callback function and adjust the increment
625 // accordingly.
626 dest_data_it += offset;
627 data_increment -= offset;
628 }
629
630 // Advance data size iterators to the next cell, avoid iterating
631 // past the end of dest_sizes_cell_it
632 if (cell_rel_it != cell_relations.end() - 1)
633 dest_sizes_cell_it += sizes_fixed_cumulative.back();
635 }
636
637 switch (cell_status)
638 {
641 unpack_callback(dealii_cell,
643 boost::make_iterator_range(dest_data_it,
644 dest_data_it + size));
645 break;
646
648 unpack_callback(dealii_cell->parent(),
650 boost::make_iterator_range(dest_data_it,
651 dest_data_it + size));
652 break;
653
655 // Skip this cell.
656 break;
657
658 default:
660 break;
661 }
662
663 if (cell_rel_it != cell_relations.end() - 1)
665 }
666 }
667
668
669
670 template <int dim, int spacedim>
672 void CellAttachedDataSerializer<dim, spacedim>::save(
673 const unsigned int global_first_cell,
674 const unsigned int global_num_cells,
675 const std::string &file_basename,
676 const MPI_Comm &mpi_communicator) const
677 {
678 Assert(sizes_fixed_cumulative.size() > 0,
679 ExcMessage("No data has been packed!"));
680
681#ifdef DEAL_II_WITH_MPI
682 // Large fractions of this function have been copied from
683 // DataOutInterface::write_vtu_in_parallel.
684 // TODO: Write general MPIIO interface.
685
686 const unsigned int myrank =
687 Utilities::MPI::this_mpi_process(mpi_communicator);
688 const unsigned int mpisize =
689 Utilities::MPI::n_mpi_processes(mpi_communicator);
690
691 if (mpisize > 1)
692 {
693 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
694
695 //
696 // ---------- Fixed size data ----------
697 //
698 {
699 const std::string fname_fixed =
700 std::string(file_basename) + "_fixed.data";
701
703 int ierr = MPI_Info_create(&info);
705
706 MPI_File fh;
707 ierr = MPI_File_open(mpi_communicator,
708 fname_fixed.c_str(),
710 info,
711 &fh);
713
714 ierr = MPI_File_set_size(fh, 0); // delete the file contents
716 // this barrier is necessary, because otherwise others might already
717 // write while one core is still setting the size to zero.
718 ierr = MPI_Barrier(mpi_communicator);
722 // ------------------
723
724 // Write cumulative sizes to file.
725 // Since each processor owns the same information about the data
726 // sizes, it is sufficient to let only the first processor perform
727 // this task.
728 if (myrank == 0)
729 {
731 fh,
732 0,
733 sizes_fixed_cumulative.data(),
734 sizes_fixed_cumulative.size(),
738 }
739
740 // Write packed data to file simultaneously.
741 const MPI_Offset size_header =
742 sizes_fixed_cumulative.size() * sizeof(unsigned int);
743
744 // Make sure we do the following computation in 64bit integers to be
745 // able to handle 4GB+ files:
749
750 ierr =
753 src_data_fixed.data(),
754 src_data_fixed.size(),
755 MPI_BYTE,
758
761 }
762
763
764
765 //
766 // ---------- Variable size data ----------
767 //
768 if (variable_size_data_stored)
769 {
770 const std::string fname_variable =
771 std::string(file_basename) + "_variable.data";
772
774 int ierr = MPI_Info_create(&info);
776
777 MPI_File fh;
778 ierr = MPI_File_open(mpi_communicator,
779 fname_variable.c_str(),
781 info,
782 &fh);
784
785 ierr = MPI_File_set_size(fh, 0); // delete the file contents
787 // this barrier is necessary, because otherwise others might already
788 // write while one core is still setting the size to zero.
789 ierr = MPI_Barrier(mpi_communicator);
793
794 // Write sizes of each cell into file simultaneously.
795 {
797 static_cast<MPI_Offset>(global_first_cell) *
798 sizeof(unsigned int);
799
800 // It is very unlikely that a single process has more than
801 // 2 billion cells, but we might as well check.
802 AssertThrow(src_sizes_variable.size() <
803 static_cast<std::size_t>(
804 std::numeric_limits<int>::max()),
806
808 fh,
810 src_sizes_variable.data(),
811 src_sizes_variable.size(),
812 MPI_INT,
815 }
816
817 // Gather size of data in bytes we want to store from this
818 // processor and compute the prefix sum. We do this in 64 bit
819 // to avoid overflow for files larger than 4GB:
820 const std::uint64_t size_on_proc = src_data_variable.size();
821 std::uint64_t prefix_sum = 0;
823 &prefix_sum,
824 1,
826 MPI_SUM,
827 mpi_communicator);
829
831 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
833
834 // Write data consecutively into file.
836 fh,
838 src_data_variable.data(),
839 src_data_variable.size(),
840 MPI_BYTE,
843
844
847 }
848 } // if (mpisize > 1)
849 else
850#endif
851 {
854 (void)mpi_communicator;
855
856 //
857 // ---------- Fixed size data ----------
858 //
859 {
860 const std::string fname_fixed =
861 std::string(file_basename) + "_fixed.data";
862
863 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
864 AssertThrow(file.fail() == false, ExcIO());
865
866 // Write header data.
867 file.write(reinterpret_cast<const char *>(
868 sizes_fixed_cumulative.data()),
869 sizes_fixed_cumulative.size() * sizeof(unsigned int));
870
871 // Write packed data.
872 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
873 src_data_fixed.size() * sizeof(char));
874 }
875
876 //
877 // ---------- Variable size data ----------
878 //
879 if (variable_size_data_stored)
880 {
881 const std::string fname_variable =
882 std::string(file_basename) + "_variable.data";
883
884 std::ofstream file(fname_variable,
885 std::ios::binary | std::ios::out);
886 AssertThrow(file.fail() == false, ExcIO());
887
888 // Write header data.
889 file.write(reinterpret_cast<const char *>(
890 src_sizes_variable.data()),
891 src_sizes_variable.size() * sizeof(int));
892
893 // Write packed data.
894 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
895 src_data_variable.size() * sizeof(char));
896 }
897 }
898 }
899
900
901 template <int dim, int spacedim>
903 void CellAttachedDataSerializer<dim, spacedim>::load(
904 const unsigned int global_first_cell,
905 const unsigned int global_num_cells,
906 const unsigned int local_num_cells,
907 const std::string &file_basename,
910 const MPI_Comm &mpi_communicator)
911 {
912 Assert(dest_data_fixed.empty(),
913 ExcMessage("Previously loaded data has not been released yet!"));
914
915 variable_size_data_stored = (n_attached_deserialize_variable > 0);
916
917#ifdef DEAL_II_WITH_MPI
918 // Large fractions of this function have been copied from
919 // DataOutInterface::write_vtu_in_parallel.
920 // TODO: Write general MPIIO interface.
921
922 const unsigned int mpisize =
923 Utilities::MPI::n_mpi_processes(mpi_communicator);
924
925 if (mpisize > 1)
926 {
927 //
928 // ---------- Fixed size data ----------
929 //
930 {
931 const std::string fname_fixed =
932 std::string(file_basename) + "_fixed.data";
933
935 int ierr = MPI_Info_create(&info);
937
938 MPI_File fh;
940 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
942
945
946 // Read cumulative sizes from file.
947 // Since all processors need the same information about the data
948 // sizes, let each of them retrieve it by reading from the same
949 // location in the file.
950 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
951 (variable_size_data_stored ? 1 : 0));
953 fh,
954 0,
955 sizes_fixed_cumulative.data(),
956 sizes_fixed_cumulative.size(),
960
961 // Allocate sufficient memory.
962 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
963 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
965
966 // Read packed data from file simultaneously.
967 const MPI_Offset size_header =
968 sizes_fixed_cumulative.size() * sizeof(unsigned int);
969
970 // Make sure we do the following computation in 64bit integers to be
971 // able to handle 4GB+ files:
975
976 ierr =
979 dest_data_fixed.data(),
980 dest_data_fixed.size(),
981 MPI_BYTE,
984
985
988 }
989
990 //
991 // ---------- Variable size data ----------
992 //
993 if (variable_size_data_stored)
994 {
995 const std::string fname_variable =
996 std::string(file_basename) + "_variable.data";
997
999 int ierr = MPI_Info_create(&info);
1001
1002 MPI_File fh;
1003 ierr = MPI_File_open(mpi_communicator,
1004 fname_variable.c_str(),
1006 info,
1007 &fh);
1009
1012
1013 // Read sizes of all locally owned cells.
1014 dest_sizes_variable.resize(local_num_cells);
1015
1017 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1018
1020 fh,
1022 dest_sizes_variable.data(),
1023 dest_sizes_variable.size(),
1024 MPI_INT,
1027
1028
1029 // Compute my data size in bytes and compute prefix sum. We do this
1030 // in 64 bit to avoid overflow for files larger than 4 GB:
1031 const std::uint64_t size_on_proc =
1032 std::accumulate(dest_sizes_variable.begin(),
1033 dest_sizes_variable.end(),
1034 0ULL);
1035
1036 std::uint64_t prefix_sum = 0;
1038 &prefix_sum,
1039 1,
1041 MPI_SUM,
1042 mpi_communicator);
1044
1046 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1047 prefix_sum;
1048
1049 dest_data_variable.resize(size_on_proc);
1050
1052 fh,
1054 dest_data_variable.data(),
1055 dest_data_variable.size(),
1056 MPI_BYTE,
1059
1062 }
1063 }
1064 else // if (mpisize > 1)
1065#endif
1066 {
1067 (void)mpi_communicator;
1070
1071 //
1072 // ---------- Fixed size data ----------
1073 //
1074 {
1075 const std::string fname_fixed =
1076 std::string(file_basename) + "_fixed.data";
1077
1078 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1079 AssertThrow(file.fail() == false, ExcIO());
1080
1081 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1082 (variable_size_data_stored ? 1 : 0));
1083 // Read header data.
1084 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1085 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1086
1087 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1088 dest_data_fixed.resize(static_cast<size_t>(local_num_cells) *
1090
1091 // Read packed data.
1092 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1093 dest_data_fixed.size() * sizeof(char));
1094 }
1095
1096 //
1097 // ---------- Variable size data ----------
1098 //
1099 if (variable_size_data_stored)
1100 {
1101 const std::string fname_variable =
1102 std::string(file_basename) + "_variable.data";
1103
1104 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1105 AssertThrow(file.fail() == false, ExcIO());
1106
1107 // Read header data.
1108 dest_sizes_variable.resize(local_num_cells);
1109 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1110 dest_sizes_variable.size() * sizeof(int));
1111
1112 // Read packed data.
1113 const std::uint64_t size =
1114 std::accumulate(dest_sizes_variable.begin(),
1115 dest_sizes_variable.end(),
1116 0ULL);
1117 dest_data_variable.resize(size);
1118 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1119 dest_data_variable.size() * sizeof(char));
1120 }
1121 }
1122 }
1123
1124
1125 template <int dim, int spacedim>
1127 void CellAttachedDataSerializer<dim, spacedim>::clear()
1128 {
1129 variable_size_data_stored = false;
1130
1131 // free information about data sizes
1132 sizes_fixed_cumulative.clear();
1133 sizes_fixed_cumulative.shrink_to_fit();
1134
1135 // free fixed size transfer data
1136 src_data_fixed.clear();
1137 src_data_fixed.shrink_to_fit();
1138
1139 dest_data_fixed.clear();
1140 dest_data_fixed.shrink_to_fit();
1141
1142 // free variable size transfer data
1143 src_sizes_variable.clear();
1144 src_sizes_variable.shrink_to_fit();
1145
1146 src_data_variable.clear();
1147 src_data_variable.shrink_to_fit();
1148
1149 dest_sizes_variable.clear();
1150 dest_sizes_variable.shrink_to_fit();
1151
1152 dest_data_variable.clear();
1153 dest_data_variable.shrink_to_fit();
1154 }
1155
1156} // namespace internal
1157
1158// anonymous namespace for internal helper functions
1159namespace
1160{
1161 // return whether the given cell is
1162 // patch_level_1, i.e. determine
1163 // whether either all or none of
1164 // its children are further
1165 // refined. this function can only
1166 // be called for non-active cells.
1167 template <int dim, int spacedim>
1168 bool
1171 {
1172 Assert(cell->is_active() == false, ExcInternalError());
1173
1174 unsigned int n_active_children = 0;
1175 for (unsigned int i = 0; i < cell->n_children(); ++i)
1176 if (cell->child(i)->is_active())
1178
1179 return (n_active_children == 0) ||
1180 (n_active_children == cell->n_children());
1181 }
1182
1183
1184
1185 // return, whether a given @p cell will be
1186 // coarsened, which is the case if all
1187 // children are active and have their coarsen
1188 // flag set. In case only part of the coarsen
1189 // flags are set, remove them.
1190 template <int dim, int spacedim>
1191 bool
1194 {
1195 // only cells with children should be
1196 // considered for coarsening
1197
1198 if (cell->has_children())
1199 {
1200 unsigned int children_to_coarsen = 0;
1201 const unsigned int n_children = cell->n_children();
1202
1203 for (unsigned int c = 0; c < n_children; ++c)
1204 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1206 if (children_to_coarsen == n_children)
1207 return true;
1208 else
1209 for (unsigned int c = 0; c < n_children; ++c)
1210 if (cell->child(c)->is_active())
1211 cell->child(c)->clear_coarsen_flag();
1212 }
1213 // no children, so no coarsening
1214 // possible. however, no children also
1215 // means that this cell will be in the same
1216 // state as if it had children and was
1217 // coarsened. So, what should we return -
1218 // false or true?
1219 // make sure we do not have to do this at
1220 // all...
1221 Assert(cell->has_children(), ExcInternalError());
1222 // ... and then simply return false
1223 return false;
1224 }
1225
1226
1227 // return, whether the face @p face_no of the
1228 // given @p cell will be refined after the
1229 // current refinement step, considering
1230 // refine and coarsen flags and considering
1231 // only those refinemnts that will be caused
1232 // by the neighboring cell.
1233
1234 // this function is used on both active cells
1235 // and cells with children. on cells with
1236 // children it also of interest to know 'how'
1237 // the face will be refined. thus there is an
1238 // additional third argument @p
1239 // expected_face_ref_case returning just
1240 // that. be aware, that this variable will
1241 // only contain useful information if this
1242 // function is called for an active cell.
1243 //
1244 // thus, this is an internal function, users
1245 // should call one of the two alternatives
1246 // following below.
1247 template <int dim, int spacedim>
1248 bool
1251 const unsigned int face_no,
1253 {
1254 // first of all: set the default value for
1255 // expected_face_ref_case, which is no
1256 // refinement at all
1257 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1258
1259 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1260 cell->neighbor(face_no);
1261
1262 // If we are at the boundary, there is no
1263 // neighbor which could refine the face
1264 if (neighbor.state() != IteratorState::valid)
1265 return false;
1266
1267 if (neighbor->has_children())
1268 {
1269 // if the neighbor is refined, it may be
1270 // coarsened. if so, then it won't refine
1271 // the face, no matter what else happens
1272 if (cell_will_be_coarsened(neighbor))
1273 return false;
1274 else
1275 // if the neighbor is refined, then it
1276 // is also refined at our current
1277 // face. It will stay so without
1278 // coarsening, so return true in that
1279 // case.
1280 {
1281 expected_face_ref_case = cell->face(face_no)->refinement_case();
1282 return true;
1283 }
1284 }
1285
1286 // now, the neighbor is not refined, but
1287 // perhaps it will be
1288 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1290 {
1291 // now we need to know, which of the
1292 // neighbors faces points towards us
1293 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1294 // check, whether the cell will be
1295 // refined in a way that refines our
1296 // face
1297 const RefinementCase<dim - 1> face_ref_case =
1301 neighbor->face_orientation(neighbor_neighbor),
1302 neighbor->face_flip(neighbor_neighbor),
1303 neighbor->face_rotation(neighbor_neighbor));
1305 {
1307 neighbor_face = neighbor->face(neighbor_neighbor);
1308 const int this_face_index = cell->face_index(face_no);
1309
1310 // there are still two basic
1311 // possibilities here: the neighbor
1312 // might be coarser or as coarse
1313 // as we are
1314 if (neighbor_face->index() == this_face_index)
1315 // the neighbor is as coarse as
1316 // we are and will be refined at
1317 // the face of consideration, so
1318 // return true
1319 {
1321 return true;
1322 }
1323 else
1324 {
1325 // the neighbor is coarser.
1326 // this is the most complicated
1327 // case. It might be, that the
1328 // neighbor's face will be
1329 // refined, but that we will
1330 // not see this, as we are
1331 // refined in a similar way.
1332
1333 // so, the neighbor's face must
1334 // have children. check, if our
1335 // cell's face is one of these
1336 // (it could also be a
1337 // grand_child)
1338 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1339 if (neighbor_face->child_index(c) == this_face_index)
1340 {
1341 // if the flagged refine
1342 // case of the face is a
1343 // subset or the same as
1344 // the current refine case,
1345 // then the face, as seen
1346 // from our cell, won't be
1347 // refined by the neighbor
1348 if ((neighbor_face->refinement_case() | face_ref_case) ==
1349 neighbor_face->refinement_case())
1350 return false;
1351 else
1352 {
1353 // if we are active, we
1354 // must be an
1355 // anisotropic child
1356 // and the coming
1357 // face_ref_case is
1358 // isotropic. Thus,
1359 // from our cell we
1360 // will see exactly the
1361 // opposite refine case
1362 // that the face has
1363 // now...
1364 Assert(
1365 face_ref_case ==
1369 ~neighbor_face->refinement_case();
1370 return true;
1371 }
1372 }
1373
1374 // so, obviously we were not
1375 // one of the children, but a
1376 // grandchild. This is only
1377 // possible in 3d.
1378 Assert(dim == 3, ExcInternalError());
1379 // In that case, however, no
1380 // matter what the neighbor
1381 // does, it won't be finer
1382 // after the next refinement
1383 // step.
1384 return false;
1385 }
1386 } // if face will be refined
1387 } // if neighbor is flagged for refinement
1388
1389 // no cases left, so the neighbor will not
1390 // refine the face
1391 return false;
1392 }
1393
1394 // version of above function for both active
1395 // and non-active cells
1396 template <int dim, int spacedim>
1397 bool
1400 const unsigned int face_no)
1401 {
1402 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1404 }
1405
1406 // version of above function for active cells
1407 // only. Additionally returning the refine
1408 // case (to come) of the face under
1409 // consideration
1410 template <int dim, int spacedim>
1411 bool
1414 const unsigned int face_no,
1416 {
1418 face_no,
1420 }
1421
1422
1423
1424 template <int dim, int spacedim>
1425 bool
1428 {
1429 std::vector<unsigned int> min_adjacent_cell_level(
1430 triangulation.n_vertices(), triangulation.n_levels());
1431 std::vector<unsigned int> max_adjacent_cell_level(
1432 triangulation.n_vertices(), 0);
1433
1434 for (const auto &cell : triangulation.active_cell_iterators())
1435 for (const unsigned int v : cell->vertex_indices())
1436 {
1437 min_adjacent_cell_level[cell->vertex_index(v)] =
1438 std::min<unsigned int>(
1439 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1440 max_adjacent_cell_level[cell->vertex_index(v)] =
1441 std::max<unsigned int>(
1442 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1443 }
1444
1445 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1446 if (triangulation.vertex_used(k))
1448 return false;
1449 return true;
1450 }
1451
1452
1453
1471 template <int dim, int spacedim>
1472 unsigned int
1475 {
1476 if (line->has_children())
1477 return line->child(0)->vertex_index(1);
1479 }
1480
1481
1482 template <int dim, int spacedim>
1483 unsigned int
1486 {
1487 switch (static_cast<unsigned char>(quad->refinement_case()))
1488 {
1490 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1491 break;
1493 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1494 break;
1496 return quad->child(0)->vertex_index(3);
1497 break;
1498 default:
1499 break;
1500 }
1502 }
1503
1504
1505 template <int dim, int spacedim>
1506 unsigned int
1509 {
1510 switch (static_cast<unsigned char>(hex->refinement_case()))
1511 {
1513 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1514 break;
1516 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1517 break;
1519 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1520 break;
1522 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1523 break;
1525 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1526 break;
1528 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1529 break;
1531 return hex->child(0)->vertex_index(7);
1532 break;
1533 default:
1534 break;
1535 }
1537 }
1538
1539
1552 template <class TRIANGULATION>
1553 inline typename TRIANGULATION::DistortedCellList
1555 {
1556 return typename TRIANGULATION::DistortedCellList();
1557 }
1558
1559
1560
1569 template <int dim>
1572 {
1573 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1574 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1575 {
1577 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1578 vertices[i] = cell->vertex(i);
1579
1582
1583 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1584 if (determinants[i] <=
1585 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1586 {
1587 distorted_cells.distorted_cells.push_back(cell);
1588 break;
1589 }
1590 }
1591
1592 return distorted_cells;
1593 }
1594
1595
1602 template <int dim>
1603 bool
1605 const typename Triangulation<dim, dim>::cell_iterator &cell)
1606 {
1607 Assert(cell->has_children(), ExcInternalError());
1608
1609 for (unsigned int c = 0; c < cell->n_children(); ++c)
1610 {
1612 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1613 vertices[i] = cell->child(c)->vertex(i);
1614
1617
1618 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1619 if (determinants[i] <=
1620 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1621 return true;
1622 }
1623
1624 return false;
1625 }
1626
1627
1635 template <int dim, int spacedim>
1636 bool
1639 {
1640 return false;
1641 }
1642
1643
1644 template <int dim, int spacedim>
1645 void
1649 unsigned int n_face_1,
1650 unsigned int n_face_2,
1651 const types::geometric_orientation orientation,
1652 typename std::map<
1654 unsigned int>,
1655 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1656 unsigned int>,
1657 types::geometric_orientation>> &periodic_face_map)
1658 {
1660 const FaceIterator face_1 = cell_1->face(n_face_1);
1661 const FaceIterator face_2 = cell_2->face(n_face_2);
1662
1663 const auto inverse_orientation =
1664 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1665
1666#ifdef DEBUG
1667 const auto [face_orientation, face_rotation, face_flip] =
1669
1670 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1671 face_rotation == false),
1672 ExcMessage("The supplied orientation "
1673 "(face_orientation, face_flip, face_rotation) "
1674 "is invalid for 1d"));
1675
1676 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1677 ExcMessage("The supplied orientation "
1678 "(face_orientation, face_flip, face_rotation) "
1679 "is invalid for 2d"));
1680#endif
1681
1682 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1683
1684 Assert(face_1->at_boundary() && face_2->at_boundary(),
1685 ExcMessage("Periodic faces must be on the boundary"));
1686
1687 // Check if the requirement that each edge can only have at most one hanging
1688 // node, and as a consequence neighboring cells can differ by at most
1689 // one refinement level is enforced. In 1d, there are no hanging nodes and
1690 // so neighboring cells can differ by more than one refinement level.
1691 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1693
1694 // insert periodic face pair for both cells
1695 using CellFace =
1696 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1697 unsigned int>;
1700 const std::pair<CellFace, types::geometric_orientation>
1702
1703 const std::pair<CellFace, std::pair<CellFace, types::geometric_orientation>>
1705
1706 // Only one periodic neighbor is allowed
1707 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1708 periodic_face_map.insert(periodic_faces);
1709
1710 if (dim == 1)
1711 {
1712 if (cell_1->has_children())
1713 {
1714 if (cell_2->has_children())
1715 {
1717 cell_1->child(n_face_1),
1718 cell_2->child(n_face_2),
1719 n_face_1,
1720 n_face_2,
1721 orientation,
1722 periodic_face_map);
1723 }
1724 else // only face_1 has children
1725 {
1727 cell_1->child(n_face_1),
1728 cell_2,
1729 n_face_1,
1730 n_face_2,
1731 orientation,
1732 periodic_face_map);
1733 }
1734 }
1735 }
1736 else // dim == 2 || dim == 3
1737 {
1738 if (cell_1->has_children())
1739 {
1740 if (cell_2->has_children())
1741 {
1742 // In the case that both faces have children, we loop over all
1743 // children and apply update_periodic_face_map_recursively
1744 // recursively:
1745
1746 Assert(face_1->n_children() ==
1748 face_2->n_children() ==
1751
1752 const auto reference_cell = cell_1->reference_cell();
1753
1754 for (unsigned int i = 0;
1756 ++i)
1757 {
1758 // Lookup the index for the second face
1759 const unsigned int j =
1760 reference_cell.standard_to_real_face_vertex(
1762
1763 // find subcell ids that belong to the subface indices
1764 unsigned int child_cell_1 =
1766 cell_1->refinement_case(),
1767 n_face_1,
1768 i,
1769 cell_1->face_orientation(n_face_1),
1770 cell_1->face_flip(n_face_1),
1771 cell_1->face_rotation(n_face_1),
1772 face_1->refinement_case());
1773 unsigned int child_cell_2 =
1775 cell_2->refinement_case(),
1776 n_face_2,
1777 j,
1778 cell_2->face_orientation(n_face_2),
1779 cell_2->face_flip(n_face_2),
1780 cell_2->face_rotation(n_face_2),
1781 face_2->refinement_case());
1782
1783 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1784 face_1->child(i),
1786 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1787 face_2->child(j),
1789
1790 // precondition: subcell has the same orientation as cell
1791 // (so that the face numbers coincide) recursive call
1793 cell_1->child(child_cell_1),
1794 cell_2->child(child_cell_2),
1795 n_face_1,
1796 n_face_2,
1797 orientation,
1798 periodic_face_map);
1799 }
1800 }
1801 else // only face_1 has children
1802 {
1803 for (unsigned int i = 0;
1805 ++i)
1806 {
1807 // find subcell ids that belong to the subface indices
1808 unsigned int child_cell_1 =
1810 cell_1->refinement_case(),
1811 n_face_1,
1812 i,
1813 cell_1->face_orientation(n_face_1),
1814 cell_1->face_flip(n_face_1),
1815 cell_1->face_rotation(n_face_1),
1816 face_1->refinement_case());
1817
1818 // recursive call
1820 cell_1->child(child_cell_1),
1821 cell_2,
1822 n_face_1,
1823 n_face_2,
1824 orientation,
1825 periodic_face_map);
1826 }
1827 }
1828 }
1829 }
1830 }
1831
1832 // Given the child number and parent's line orientation, return the child face
1833 // number.
1834 unsigned int
1835 child_line_index(const unsigned int child_no,
1836 const types::geometric_orientation line_orientation)
1837 {
1839 Assert(line_orientation == numbers::default_geometric_orientation ||
1840 line_orientation == numbers::reverse_line_orientation,
1843 if (child_no == 0)
1844 return line_orientation == D ? 0 : 1;
1845 else
1846 return line_orientation == D ? 1 : 0;
1847 }
1848
1849 // Several parts of Triangulation (e.g., TriaLevel) are not templated on the
1850 // dimension and thus require de-templated versions of some ReferenceCell
1851 // functions.
1852 unsigned int
1853 max_n_faces(const unsigned int structdim)
1854 {
1855 switch (structdim)
1856 {
1857 case 0:
1858 return ReferenceCells::max_n_faces<0>();
1859 case 1:
1860 return ReferenceCells::max_n_faces<1>();
1861 case 2:
1862 return ReferenceCells::max_n_faces<2>();
1863 case 3:
1864 return ReferenceCells::max_n_faces<3>();
1865 default:
1868 }
1869 }
1870} // end of anonymous namespace
1871
1872
1873namespace internal
1874{
1875 namespace TriangulationImplementation
1876 {
1877 // make sure that if in the following we
1878 // write Triangulation<dim,spacedim>
1879 // we mean the *class*
1880 // ::Triangulation, not the
1881 // enclosing namespace
1882 // internal::TriangulationImplementation
1883 using ::Triangulation;
1884
1890 int,
1891 << "Something went wrong upon construction of cell "
1892 << arg1);
1903 int,
1904 << "Cell " << arg1
1905 << " has negative measure. This typically "
1906 << "indicates some distortion in the cell, or a mistakenly "
1907 << "swapped pair of vertices in the input to "
1908 << "Triangulation::create_triangulation().");
1917 int,
1918 int,
1919 int,
1920 << "Error while creating cell " << arg1
1921 << ": the vertex index " << arg2 << " must be between 0 and "
1922 << arg3 << '.');
1929 int,
1930 int,
1932 << "The input data for creating a triangulation contained "
1933 << "information about a line with indices " << arg1 << " and " << arg2
1934 << " that is described to have boundary indicator "
1935 << static_cast<int>(arg3)
1936 << ". However, this is an internal line not located on the "
1937 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1938 << std::endl
1939 << "If this happened at a place where you call "
1940 << "Triangulation::create_triangulation() yourself, you need "
1941 << "to check the SubCellData object you pass to this function."
1942 << std::endl
1943 << std::endl
1944 << "If this happened in a place where you are reading a mesh "
1945 << "from a file, then you need to investigate why such a line "
1946 << "ended up in the input file. A typical case is a geometry "
1947 << "that consisted of multiple parts and for which the mesh "
1948 << "generator program assumes that the interface between "
1949 << "two parts is a boundary when that isn't supposed to be "
1950 << "the case, or where the mesh generator simply assigns "
1951 << "'geometry indicators' to lines at the perimeter of "
1952 << "a part that are not supposed to be interpreted as "
1953 << "'boundary indicators'.");
1960 int,
1961 int,
1962 int,
1963 int,
1965 << "The input data for creating a triangulation contained "
1966 << "information about a quad with indices " << arg1 << ", " << arg2
1967 << ", " << arg3 << ", and " << arg4
1968 << " that is described to have boundary indicator "
1969 << static_cast<int>(arg5)
1970 << ". However, this is an internal quad not located on the "
1971 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1972 << std::endl
1973 << "If this happened at a place where you call "
1974 << "Triangulation::create_triangulation() yourself, you need "
1975 << "to check the SubCellData object you pass to this function."
1976 << std::endl
1977 << std::endl
1978 << "If this happened in a place where you are reading a mesh "
1979 << "from a file, then you need to investigate why such a quad "
1980 << "ended up in the input file. A typical case is a geometry "
1981 << "that consisted of multiple parts and for which the mesh "
1982 << "generator program assumes that the interface between "
1983 << "two parts is a boundary when that isn't supposed to be "
1984 << "the case, or where the mesh generator simply assigns "
1985 << "'geometry indicators' to quads at the surface of "
1986 << "a part that are not supposed to be interpreted as "
1987 << "'boundary indicators'.");
1994 int,
1995 int,
1996 << "In SubCellData the line info of the line with vertex indices " << arg1
1997 << " and " << arg2 << " appears more than once. "
1998 << "This is not allowed.");
2005 int,
2006 int,
2007 std::string,
2008 << "In SubCellData the line info of the line with vertex indices " << arg1
2009 << " and " << arg2 << " appears multiple times with different (valid) "
2010 << arg3 << ". This is not allowed.");
2017 int,
2018 int,
2019 int,
2020 int,
2021 std::string,
2022 << "In SubCellData the quad info of the quad with line indices " << arg1
2023 << ", " << arg2 << ", " << arg3 << " and " << arg4
2024 << " appears multiple times with different (valid) " << arg5
2025 << ". This is not allowed.");
2026
2027 /*
2028 * Reserve space for TriaFaces. Details:
2029 *
2030 * Reserve space for line_orientations.
2031 *
2032 * @note Used only for dim=3.
2033 */
2034 void
2036 const unsigned int new_quads_in_pairs,
2037 const unsigned int new_quads_single)
2038 {
2040
2042
2043 unsigned int next_free_single = 0;
2044 unsigned int next_free_pair = 0;
2045
2046 // count the number of objects, of unused single objects and of
2047 // unused pairs of objects
2048 [[maybe_unused]] unsigned int n_quads = 0;
2049 unsigned int n_unused_pairs = 0;
2050 unsigned int n_unused_singles = 0;
2051 for (unsigned int i = 0; i < tria_faces.quads.used.size(); ++i)
2052 {
2053 if (tria_faces.quads.used[i])
2054 ++n_quads;
2055 else if (i + 1 < tria_faces.quads.used.size())
2056 {
2057 if (tria_faces.quads.used[i + 1])
2058 {
2060 if (next_free_single == 0)
2061 next_free_single = i;
2062 }
2063 else
2064 {
2066 if (next_free_pair == 0)
2067 next_free_pair = i;
2068 ++i;
2069 }
2070 }
2071 else
2073 }
2074 Assert(n_quads + 2 * n_unused_pairs + n_unused_singles ==
2075 tria_faces.quads.used.size(),
2077
2078 // how many single quads are needed in addition to n_unused_quads?
2080
2081 unsigned int new_size =
2082 tria_faces.quads.used.size() + new_quads_in_pairs - 2 * n_unused_pairs;
2085
2086 // see above...
2087 if (new_size > tria_faces.quads.n_objects())
2088 {
2089 // reserve the field of the derived class
2090 tria_faces.quads_line_orientations.resize(
2091 new_size * ReferenceCells::max_n_lines<2>(), true);
2092
2093 auto &q_is_q = tria_faces.quad_is_quadrilateral;
2094 q_is_q.reserve(new_size);
2095 q_is_q.insert(q_is_q.end(), new_size - q_is_q.size(), true);
2096 }
2097 }
2098
2099
2100
2111 void
2113 const unsigned int total_cells,
2114 const unsigned int space_dimension,
2115 const bool tetraheder_in_mesh = false)
2116 {
2117 const unsigned int dim = tria_level.dim;
2118
2119 // we need space for total_cells cells. Maybe we have more already
2120 // with those cells which are unused, so only allocate new space if
2121 // needed.
2122 //
2123 // note that all arrays should have equal sizes (checked by
2124 // @p{monitor_memory}
2125 if (total_cells > tria_level.refine_flags.size())
2126 {
2127 tria_level.refine_flags.reserve(total_cells);
2128 tria_level.refine_flags.insert(tria_level.refine_flags.end(),
2129 total_cells -
2130 tria_level.refine_flags.size(),
2131 /*RefinementCase::no_refinement=*/0);
2132
2134 {
2135 tria_level.refine_choice.reserve(total_cells);
2136 tria_level.refine_choice.insert(
2137 tria_level.refine_choice.end(),
2138 total_cells - tria_level.refine_choice.size(),
2139 static_cast<char>(
2141 }
2142
2143 tria_level.coarsen_flags.reserve(total_cells);
2144 tria_level.coarsen_flags.insert(tria_level.coarsen_flags.end(),
2145 total_cells -
2146 tria_level.coarsen_flags.size(),
2147 false);
2148
2149 tria_level.active_cell_indices.reserve(total_cells);
2150 tria_level.active_cell_indices.insert(
2151 tria_level.active_cell_indices.end(),
2152 total_cells - tria_level.active_cell_indices.size(),
2154
2155 tria_level.subdomain_ids.reserve(total_cells);
2156 tria_level.subdomain_ids.insert(tria_level.subdomain_ids.end(),
2157 total_cells -
2158 tria_level.subdomain_ids.size(),
2159 0);
2160
2161 tria_level.level_subdomain_ids.reserve(total_cells);
2162 tria_level.level_subdomain_ids.insert(
2163 tria_level.level_subdomain_ids.end(),
2164 total_cells - tria_level.level_subdomain_ids.size(),
2165 0);
2166
2167 tria_level.global_active_cell_indices.reserve(total_cells);
2168 tria_level.global_active_cell_indices.insert(
2169 tria_level.global_active_cell_indices.end(),
2170 total_cells - tria_level.global_active_cell_indices.size(),
2172
2173 tria_level.global_level_cell_indices.reserve(total_cells);
2174 tria_level.global_level_cell_indices.insert(
2175 tria_level.global_level_cell_indices.end(),
2176 total_cells - tria_level.global_level_cell_indices.size(),
2178
2179 if (dim == space_dimension - 1)
2180 {
2181 tria_level.direction_flags.reserve(total_cells);
2182 tria_level.direction_flags.insert(
2183 tria_level.direction_flags.end(),
2184 total_cells - tria_level.direction_flags.size(),
2185 true);
2186 }
2187 else
2188 tria_level.direction_flags.clear();
2189
2190 tria_level.parents.reserve((total_cells + 1) / 2);
2191 tria_level.parents.insert(tria_level.parents.end(),
2192 (total_cells + 1) / 2 -
2193 tria_level.parents.size(),
2194 -1);
2195
2196 tria_level.neighbors.reserve(total_cells * max_n_faces(dim));
2197 tria_level.neighbors.insert(tria_level.neighbors.end(),
2198 total_cells * max_n_faces(dim) -
2199 tria_level.neighbors.size(),
2200 std::make_pair(-1, -1));
2201
2202 if (dim == 2 || dim == 3)
2203 {
2204 tria_level.face_orientations.resize(total_cells *
2205 max_n_faces(dim));
2206
2207 tria_level.reference_cell.reserve(total_cells);
2208 tria_level.reference_cell.insert(
2209 tria_level.reference_cell.end(),
2210 total_cells - tria_level.reference_cell.size(),
2213 }
2214 }
2215 }
2216
2217
2218
2223 int,
2224 int,
2225 << "The containers have sizes " << arg1 << " and " << arg2
2226 << ", which is not as expected.");
2227
2233 void
2235 const unsigned int true_dimension)
2236 {
2237 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2238 tria_level.neighbors.size(),
2239 ExcMemoryInexact(tria_level.refine_flags.size(),
2240 tria_level.neighbors.size()));
2241 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2242 tria_level.neighbors.size(),
2243 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2244 tria_level.neighbors.size()));
2245 }
2246
2247
2248
2261 void
2263 const unsigned int new_objects_in_pairs,
2264 const unsigned int new_objects_single = 0)
2265 {
2266 if (tria_objects.structdim <= 2)
2267 {
2269
2270 tria_objects.next_free_single = 0;
2271 tria_objects.next_free_pair = 0;
2272 tria_objects.reverse_order_next_free_single = false;
2273
2274 // count the number of objects, of unused single objects and of
2275 // unused pairs of objects
2276 [[maybe_unused]] unsigned int n_objects = 0;
2277 unsigned int n_unused_pairs = 0;
2278 unsigned int n_unused_singles = 0;
2279 for (unsigned int i = 0; i < tria_objects.used.size(); ++i)
2280 {
2281 if (tria_objects.used[i])
2282 ++n_objects;
2283 else if (i + 1 < tria_objects.used.size())
2284 {
2285 if (tria_objects.used[i + 1])
2286 {
2288 if (tria_objects.next_free_single == 0)
2289 tria_objects.next_free_single = i;
2290 }
2291 else
2292 {
2294 if (tria_objects.next_free_pair == 0)
2295 tria_objects.next_free_pair = i;
2296 ++i;
2297 }
2298 }
2299 else
2301 }
2302 Assert(n_objects + 2 * n_unused_pairs + n_unused_singles ==
2303 tria_objects.used.size(),
2305
2306 // how many single objects are needed in addition to
2307 // n_unused_objects?
2308 const int additional_single_objects =
2310
2311 unsigned int new_size = tria_objects.used.size() +
2315
2316 // only allocate space if necessary
2317 if (new_size > tria_objects.n_objects())
2318 {
2319 const unsigned int max_children_per_cell =
2320 1 << tria_objects.structdim;
2321
2322 tria_objects.cells.reserve(new_size *
2323 max_n_faces(tria_objects.structdim));
2324 tria_objects.cells.insert(tria_objects.cells.end(),
2325 (new_size - tria_objects.n_objects()) *
2326 max_n_faces(tria_objects.structdim),
2327 -1);
2328
2329 tria_objects.used.reserve(new_size);
2330 tria_objects.used.insert(tria_objects.used.end(),
2331 new_size - tria_objects.used.size(),
2332 false);
2333
2334 tria_objects.user_flags.reserve(new_size);
2335 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2336 new_size -
2337 tria_objects.user_flags.size(),
2338 false);
2339
2340 const unsigned int factor = max_children_per_cell / 2;
2341 tria_objects.children.reserve(factor * new_size);
2342 tria_objects.children.insert(tria_objects.children.end(),
2343 factor * new_size -
2344 tria_objects.children.size(),
2345 -1);
2346
2347 if (tria_objects.structdim > 1)
2348 {
2349 tria_objects.refinement_cases.reserve(new_size);
2350 tria_objects.refinement_cases.insert(
2351 tria_objects.refinement_cases.end(),
2352 new_size - tria_objects.refinement_cases.size(),
2353 /*RefinementCase::no_refinement=*/0);
2354 }
2355
2356 // first reserve, then resize. Otherwise the std library can
2357 // decide to allocate more entries.
2358 tria_objects.boundary_or_material_id.reserve(new_size);
2359 tria_objects.boundary_or_material_id.resize(new_size);
2360
2361 tria_objects.user_data.reserve(new_size);
2362 tria_objects.user_data.resize(new_size);
2363
2364 tria_objects.manifold_id.reserve(new_size);
2365 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2366 new_size -
2367 tria_objects.manifold_id.size(),
2369 }
2370
2371 if (n_unused_singles == 0)
2372 {
2373 tria_objects.next_free_single = new_size - 1;
2374 tria_objects.reverse_order_next_free_single = true;
2375 }
2376 }
2377 else
2378 {
2379 const unsigned int new_hexes = new_objects_in_pairs;
2380
2381 const unsigned int new_size =
2382 new_hexes + std::count(tria_objects.used.begin(),
2383 tria_objects.used.end(),
2384 true);
2385
2386 // see above...
2387 if (new_size > tria_objects.n_objects())
2388 {
2389 tria_objects.cells.reserve(new_size *
2390 max_n_faces(tria_objects.structdim));
2391 tria_objects.cells.insert(tria_objects.cells.end(),
2392 (new_size - tria_objects.n_objects()) *
2393 max_n_faces(tria_objects.structdim),
2394 -1);
2395
2396 tria_objects.used.reserve(new_size);
2397 tria_objects.used.insert(tria_objects.used.end(),
2398 new_size - tria_objects.used.size(),
2399 false);
2400
2401 tria_objects.user_flags.reserve(new_size);
2402 tria_objects.user_flags.insert(tria_objects.user_flags.end(),
2403 new_size -
2404 tria_objects.user_flags.size(),
2405 false);
2406
2407 tria_objects.children.reserve(4 * new_size);
2408 tria_objects.children.insert(tria_objects.children.end(),
2409 4 * new_size -
2410 tria_objects.children.size(),
2411 -1);
2412
2413 // for the following fields, we know exactly how many elements
2414 // we need, so first reserve then resize (resize itself, at least
2415 // with some compiler libraries, appears to round up the size it
2416 // actually reserves)
2417 tria_objects.boundary_or_material_id.reserve(new_size);
2418 tria_objects.boundary_or_material_id.resize(new_size);
2419
2420 tria_objects.manifold_id.reserve(new_size);
2421 tria_objects.manifold_id.insert(tria_objects.manifold_id.end(),
2422 new_size -
2423 tria_objects.manifold_id.size(),
2425
2426 tria_objects.user_data.reserve(new_size);
2427 tria_objects.user_data.resize(new_size);
2428
2429 tria_objects.refinement_cases.reserve(new_size);
2430 tria_objects.refinement_cases.insert(
2431 tria_objects.refinement_cases.end(),
2432 new_size - tria_objects.refinement_cases.size(),
2433 /*RefinementCase::no_refinement=*/0);
2434 }
2435 tria_objects.next_free_single = tria_objects.next_free_pair = 0;
2436 }
2437 }
2438
2439
2440
2446 void
2447 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2448 {
2449 Assert(tria_object.n_objects() == tria_object.used.size(),
2450 ExcMemoryInexact(tria_object.n_objects(),
2451 tria_object.used.size()));
2452 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2453 ExcMemoryInexact(tria_object.n_objects(),
2454 tria_object.user_flags.size()));
2455 Assert(tria_object.n_objects() ==
2456 tria_object.boundary_or_material_id.size(),
2457 ExcMemoryInexact(tria_object.n_objects(),
2458 tria_object.boundary_or_material_id.size()));
2459 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2460 ExcMemoryInexact(tria_object.n_objects(),
2461 tria_object.manifold_id.size()));
2462 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2463 ExcMemoryInexact(tria_object.n_objects(),
2464 tria_object.user_data.size()));
2465
2466 if (tria_object.structdim == 1)
2467 {
2468 Assert(1 * tria_object.n_objects() == tria_object.children.size(),
2469 ExcMemoryInexact(tria_object.n_objects(),
2470 tria_object.children.size()));
2471 }
2472 else if (tria_object.structdim == 2)
2473 {
2474 Assert(2 * tria_object.n_objects() == tria_object.children.size(),
2475 ExcMemoryInexact(tria_object.n_objects(),
2476 tria_object.children.size()));
2477 }
2478 else if (tria_object.structdim == 3)
2479 {
2480 Assert(4 * tria_object.n_objects() == tria_object.children.size(),
2481 ExcMemoryInexact(tria_object.n_objects(),
2482 tria_object.children.size()));
2483 }
2484 }
2485
2486
2487
2492 template <int dim, int spacedim>
2494 {
2495 public:
2499 virtual ~Policy() = default;
2500
2504 virtual void
2506
2510 virtual void
2514 std::vector<unsigned int> &line_cell_count,
2515 std::vector<unsigned int> &quad_cell_count) = 0;
2516
2522 const bool check_for_distorted_cells) = 0;
2523
2527 virtual void
2530
2534 virtual void
2537
2541 virtual bool
2543 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2544
2551 virtual std::unique_ptr<Policy<dim, spacedim>>
2552 clone() = 0;
2553 };
2554
2555
2556
2562 template <int dim, int spacedim, typename T>
2563 class PolicyWrapper : public Policy<dim, spacedim>
2564 {
2565 public:
2566 void
2568 {
2569 T::update_neighbors(tria);
2570 }
2571
2572 void
2576 std::vector<unsigned int> &line_cell_count,
2577 std::vector<unsigned int> &quad_cell_count) override
2578 {
2579 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2580 }
2581
2584 const bool check_for_distorted_cells) override
2585 {
2586 return T::execute_refinement(triangulation, check_for_distorted_cells);
2587 }
2588
2589 void
2592 {
2593 T::prevent_distorted_boundary_cells(triangulation);
2594 }
2595
2596 void
2599 {
2600 T::prepare_refinement_dim_dependent(triangulation);
2601 }
2602
2603 bool
2606 override
2607 {
2608 return T::template coarsening_allowed<dim, spacedim>(cell);
2609 }
2610
2611 std::unique_ptr<Policy<dim, spacedim>>
2612 clone() override
2613 {
2614 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2615 }
2616 };
2617
2618
2619
2716 {
2728 template <int dim, int spacedim>
2729 static void
2732 const unsigned int level_objects,
2734 {
2735 using line_iterator =
2737
2738 number_cache.n_levels = 0;
2739 if (level_objects > 0)
2740 // find the last level on which there are used cells
2741 for (unsigned int level = 0; level < level_objects; ++level)
2742 if (triangulation.begin(level) != triangulation.end(level))
2743 number_cache.n_levels = level + 1;
2744
2745 // no cells at all?
2746 Assert(number_cache.n_levels > 0, ExcInternalError());
2747
2748 //---------------------------------
2749 // update the number of lines on the different levels in the
2750 // cache
2751 number_cache.n_lines = 0;
2752 number_cache.n_active_lines = 0;
2753
2754 // for 1d, lines have levels so take count the objects per
2755 // level and globally
2756 if (dim == 1)
2757 {
2758 number_cache.n_lines_level.resize(number_cache.n_levels);
2759 number_cache.n_active_lines_level.resize(number_cache.n_levels);
2760
2761 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
2762 {
2763 // count lines on this level
2764 number_cache.n_lines_level[level] = 0;
2765 number_cache.n_active_lines_level[level] = 0;
2766
2767 line_iterator line = triangulation.begin_line(level),
2768 endc =
2769 (level == number_cache.n_levels - 1 ?
2770 line_iterator(triangulation.end_line()) :
2771 triangulation.begin_line(level + 1));
2772 for (; line != endc; ++line)
2773 {
2774 ++number_cache.n_lines_level[level];
2775 if (line->has_children() == false)
2776 ++number_cache.n_active_lines_level[level];
2777 }
2778
2779 // update total number of lines
2780 number_cache.n_lines += number_cache.n_lines_level[level];
2781 number_cache.n_active_lines +=
2782 number_cache.n_active_lines_level[level];
2783 }
2784 }
2785 else
2786 {
2787 // for dim>1, there are no levels for lines
2788 number_cache.n_lines_level.clear();
2789 number_cache.n_active_lines_level.clear();
2790
2791 line_iterator line = triangulation.begin_line(),
2792 endc = triangulation.end_line();
2793 for (; line != endc; ++line)
2794 {
2795 ++number_cache.n_lines;
2796 if (line->has_children() == false)
2797 ++number_cache.n_active_lines;
2798 }
2799 }
2800 }
2801
2816 template <int dim, int spacedim>
2817 static void
2820 const unsigned int level_objects,
2822 {
2823 // update lines and n_levels in number_cache. since we don't
2824 // access any of these numbers, we can do this in the
2825 // background
2827 static_cast<
2828 void (*)(const Triangulation<dim, spacedim> &,
2829 const unsigned int,
2835 number_cache));
2836
2837 using quad_iterator =
2839
2840 //---------------------------------
2841 // update the number of quads on the different levels in the
2842 // cache
2843 number_cache.n_quads = 0;
2844 number_cache.n_active_quads = 0;
2845
2846 // for 2d, quads have levels so take count the objects per
2847 // level and globally
2848 if (dim == 2)
2849 {
2850 // count the number of levels; the function we called above
2851 // on a separate Task for lines also does this and puts it into
2852 // number_cache.n_levels, but this datum may not yet be
2853 // available as we call the function on a separate task
2854 unsigned int n_levels = 0;
2855 if (level_objects > 0)
2856 // find the last level on which there are used cells
2857 for (unsigned int level = 0; level < level_objects; ++level)
2858 if (triangulation.begin(level) != triangulation.end(level))
2859 n_levels = level + 1;
2860
2861 number_cache.n_quads_level.resize(n_levels);
2862 number_cache.n_active_quads_level.resize(n_levels);
2863
2864 for (unsigned int level = 0; level < n_levels; ++level)
2865 {
2866 // count quads on this level
2867 number_cache.n_quads_level[level] = 0;
2868 number_cache.n_active_quads_level[level] = 0;
2869
2870 quad_iterator quad = triangulation.begin_quad(level),
2871 endc =
2872 (level == n_levels - 1 ?
2873 quad_iterator(triangulation.end_quad()) :
2874 triangulation.begin_quad(level + 1));
2875 for (; quad != endc; ++quad)
2876 {
2877 ++number_cache.n_quads_level[level];
2878 if (quad->has_children() == false)
2879 ++number_cache.n_active_quads_level[level];
2880 }
2881
2882 // update total number of quads
2883 number_cache.n_quads += number_cache.n_quads_level[level];
2884 number_cache.n_active_quads +=
2885 number_cache.n_active_quads_level[level];
2886 }
2887 }
2888 else
2889 {
2890 // for dim>2, there are no levels for quads
2891 number_cache.n_quads_level.clear();
2892 number_cache.n_active_quads_level.clear();
2893
2894 quad_iterator quad = triangulation.begin_quad(),
2895 endc = triangulation.end_quad();
2896 for (; quad != endc; ++quad)
2897 {
2898 ++number_cache.n_quads;
2899 if (quad->has_children() == false)
2900 ++number_cache.n_active_quads;
2901 }
2902 }
2903
2904 // wait for the background computation for lines
2905 update_lines.join();
2906 }
2907
2923 template <int dim, int spacedim>
2924 static void
2927 const unsigned int level_objects,
2929 {
2930 // update quads, lines and n_levels in number_cache. since we
2931 // don't access any of these numbers, we can do this in the
2932 // background
2934 static_cast<
2935 void (*)(const Triangulation<dim, spacedim> &,
2936 const unsigned int,
2942 number_cache));
2943
2944 using hex_iterator =
2946
2947 //---------------------------------
2948 // update the number of hexes on the different levels in the
2949 // cache
2950 number_cache.n_hexes = 0;
2951 number_cache.n_active_hexes = 0;
2952
2953 // for 3d, hexes have levels so take count the objects per
2954 // level and globally
2955 if (dim == 3)
2956 {
2957 // count the number of levels; the function we called
2958 // above on a separate Task for quads (recursively, via
2959 // the lines function) also does this and puts it into
2960 // number_cache.n_levels, but this datum may not yet be
2961 // available as we call the function on a separate task
2962 unsigned int n_levels = 0;
2963 if (level_objects > 0)
2964 // find the last level on which there are used cells
2965 for (unsigned int level = 0; level < level_objects; ++level)
2966 if (triangulation.begin(level) != triangulation.end(level))
2967 n_levels = level + 1;
2968
2969 number_cache.n_hexes_level.resize(n_levels);
2970 number_cache.n_active_hexes_level.resize(n_levels);
2971
2972 for (unsigned int level = 0; level < n_levels; ++level)
2973 {
2974 // count hexes on this level
2975 number_cache.n_hexes_level[level] = 0;
2976 number_cache.n_active_hexes_level[level] = 0;
2977
2978 hex_iterator hex = triangulation.begin_hex(level),
2979 endc = (level == n_levels - 1 ?
2980 hex_iterator(triangulation.end_hex()) :
2981 triangulation.begin_hex(level + 1));
2982 for (; hex != endc; ++hex)
2983 {
2984 ++number_cache.n_hexes_level[level];
2985 if (hex->has_children() == false)
2986 ++number_cache.n_active_hexes_level[level];
2987 }
2988
2989 // update total number of hexes
2990 number_cache.n_hexes += number_cache.n_hexes_level[level];
2991 number_cache.n_active_hexes +=
2992 number_cache.n_active_hexes_level[level];
2993 }
2994 }
2995 else
2996 {
2997 // for dim>3, there are no levels for hexes
2998 number_cache.n_hexes_level.clear();
2999 number_cache.n_active_hexes_level.clear();
3000
3001 hex_iterator hex = triangulation.begin_hex(),
3002 endc = triangulation.end_hex();
3003 for (; hex != endc; ++hex)
3004 {
3005 ++number_cache.n_hexes;
3006 if (hex->has_children() == false)
3007 ++number_cache.n_active_hexes;
3008 }
3009 }
3010
3011 // wait for the background computation for quads
3013 }
3014
3015
3016 template <int dim, int spacedim>
3017 static void
3020 const unsigned int level_objects,
3022 {
3024
3025 number_cache.active_cell_index_partitioner =
3026 std::make_shared<const Utilities::MPI::Partitioner>(
3027 triangulation.n_active_cells());
3028
3029 number_cache.level_cell_index_partitioners.resize(
3030 triangulation.n_levels());
3031 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3032 number_cache.level_cell_index_partitioners[level] =
3033 std::make_shared<const Utilities::MPI::Partitioner>(
3034 triangulation.n_cells(level));
3035 }
3036
3037
3038 template <int spacedim>
3039 static void
3042
3043
3044 template <int dim, int spacedim>
3045 static void
3047 {
3048 // each face can be neighbored on two sides
3049 // by cells. according to the face's
3050 // intrinsic normal we define the left
3051 // neighbor as the one for which the face
3052 // normal points outward, and store that
3053 // one first; the second one is then
3054 // the right neighbor for which the
3055 // face normal points inward. This
3056 // information depends on the type of cell
3057 // and local number of face for the
3058 // 'standard ordering and orientation' of
3059 // faces and then on the face_orientation
3060 // information for the real mesh. Set up a
3061 // table to have fast access to those
3062 // offsets (0 for left and 1 for
3063 // right). Some of the values are invalid
3064 // as they reference too large face
3065 // numbers, but we just leave them at a
3066 // zero value.
3067 //
3068 // Note, that in 2d for lines as faces the
3069 // normal direction given in the
3070 // GeometryInfo class is not consistent. We
3071 // thus define here that the normal for a
3072 // line points to the right if the line
3073 // points upwards.
3074 //
3075 // There is one more point to
3076 // consider, however: if we have
3077 // dim<spacedim, then we may have
3078 // cases where cells are
3079 // inverted. In effect, both
3080 // cells think they are the left
3081 // neighbor of an edge, for
3082 // example, which leads us to
3083 // forget neighborship
3084 // information (a case that shows
3085 // this is
3086 // codim_one/hanging_nodes_02). We
3087 // store whether a cell is
3088 // inverted using the
3089 // direction_flag, so if a cell
3090 // has a false direction_flag,
3091 // then we need to invert our
3092 // selection whether we are a
3093 // left or right neighbor in all
3094 // following computations.
3095 //
3096 // first index: dimension (minus 2)
3097 // second index: local face index
3098 // third index: face_orientation (false and true)
3099 static const unsigned int left_right_offset[2][6][2] = {
3100 // quadrilateral
3101 {{0, 1}, // face 0, face_orientation = false and true
3102 {1, 0}, // face 1, face_orientation = false and true
3103 {1, 0}, // face 2, face_orientation = false and true
3104 {0, 1}, // face 3, face_orientation = false and true
3105 {0, 0}, // face 4, invalid face
3106 {0, 0}}, // face 5, invalid face
3107 // hexahedron
3108 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3109
3110 // now create a vector of the two active
3111 // neighbors (left and right) for each face
3112 // and fill it by looping over all cells. For
3113 // cases with anisotropic refinement and more
3114 // then one cell neighboring at a given side
3115 // of the face we will automatically get the
3116 // active one on the highest level as we loop
3117 // over cells from lower levels first.
3119 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3120 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3121
3122 for (const auto &cell : triangulation.cell_iterators())
3123 for (auto f : cell->face_indices())
3124 {
3126 cell->face(f);
3127
3128 const unsigned int offset =
3129 (cell->direction_flag() ?
3130 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3131 1 -
3132 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3133
3134 adjacent_cells[2 * face->index() + offset] = cell;
3135
3136 // if this cell is not refined, but the
3137 // face is, then we'll have to set our
3138 // cell as neighbor for the child faces
3139 // as well. Fortunately the normal
3140 // orientation of children will be just
3141 // the same.
3142 if (dim == 2)
3143 {
3144 if (cell->is_active() && face->has_children())
3145 {
3146 adjacent_cells[2 * face->child(0)->index() + offset] =
3147 cell;
3148 adjacent_cells[2 * face->child(1)->index() + offset] =
3149 cell;
3150 }
3151 }
3152 else // -> dim == 3
3153 {
3154 // We need the same as in 2d
3155 // here. Furthermore, if the face is
3156 // refined with cut_x or cut_y then
3157 // those children again in the other
3158 // direction, and if this cell is
3159 // refined isotropically (along the
3160 // face) then the neighbor will
3161 // (probably) be refined as cut_x or
3162 // cut_y along the face. For those
3163 // neighboring children cells, their
3164 // neighbor will be the current,
3165 // inactive cell, as our children are
3166 // too fine to be neighbors. Catch that
3167 // case by also acting on inactive
3168 // cells with isotropic refinement
3169 // along the face. If the situation
3170 // described is not present, the data
3171 // will be overwritten later on when we
3172 // visit cells on finer levels, so no
3173 // harm will be done.
3174 if (face->has_children() &&
3175 (cell->is_active() ||
3177 cell->refinement_case(), f) ==
3179 {
3180 for (unsigned int c = 0; c < face->n_children(); ++c)
3181 adjacent_cells[2 * face->child(c)->index() + offset] =
3182 cell;
3183 if (face->child(0)->has_children())
3184 {
3185 adjacent_cells[2 * face->child(0)->child(0)->index() +
3186 offset] = cell;
3187 adjacent_cells[2 * face->child(0)->child(1)->index() +
3188 offset] = cell;
3189 }
3190 if (face->child(1)->has_children())
3191 {
3192 adjacent_cells[2 * face->child(1)->child(0)->index() +
3193 offset] = cell;
3194 adjacent_cells[2 * face->child(1)->child(1)->index() +
3195 offset] = cell;
3196 }
3197 } // if cell active and face refined
3198 } // else -> dim==3
3199 } // for all faces of all cells
3200
3201 // now loop again over all cells and set the
3202 // corresponding neighbor cell. Note, that we
3203 // have to use the opposite of the
3204 // left_right_offset in this case as we want
3205 // the offset of the neighbor, not our own.
3206 for (const auto &cell : triangulation.cell_iterators())
3207 for (auto f : cell->face_indices())
3208 {
3209 const unsigned int offset =
3210 (cell->direction_flag() ?
3211 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3212 1 -
3213 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3214 cell->set_neighbor(
3215 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3216 }
3217 }
3218
3219
3223 template <int dim, int spacedim>
3224 static void
3225 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3226 const std::vector<CellData<dim>> &cells,
3227 const SubCellData &subcelldata,
3229 {
3230 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3231 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3232
3233 // Check that all cells have positive volume.
3234#ifndef _MSC_VER
3235 // TODO: The following code does not compile with MSVC. Find a way
3236 // around it
3237 if (dim == spacedim)
3238 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3239 {
3240 // If we should check for distorted cells, then we permit them
3241 // to exist. If a cell has negative measure, then it must be
3242 // distorted (the converse is not necessarily true); hence
3243 // throw an exception if no such cells should exist.
3244 if (tria.check_for_distorted_cells)
3245 {
3246 const double cell_measure = GridTools::cell_measure<spacedim>(
3247 vertices,
3248 ArrayView<const unsigned int>(cells[cell_no].vertices));
3249 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3250 }
3251 }
3252#endif
3253
3254 // clear old content
3255 tria.levels.clear();
3256 tria.levels.push_back(
3257 std::make_unique<
3259
3260 if (dim > 1)
3261 tria.faces = std::make_unique<
3263
3264 // copy vertices
3265 tria.vertices = vertices;
3266 tria.vertices_used.assign(vertices.size(), true);
3267
3268 // compute connectivity
3269 const auto connectivity = build_connectivity<unsigned int>(cells);
3270 const unsigned int n_cell = cells.size();
3271
3272 // TriaObjects: lines
3273 if (dim >= 2)
3274 {
3275 auto &lines_0 = tria.faces->lines; // data structure to be filled
3276
3277 // get connectivity between quads and lines
3278 const auto &crs = connectivity.entity_to_entities(1, 0);
3279 const unsigned int n_lines = crs.ptr.size() - 1;
3280
3281 // allocate memory
3282 reserve_space_(lines_0, n_lines);
3283
3284 // loop over lines
3285 for (unsigned int line = 0; line < n_lines; ++line)
3286 for (unsigned int i = crs.ptr[line], j = 0; i < crs.ptr[line + 1];
3287 ++i, ++j)
3288 lines_0.cells[line * ReferenceCells::max_n_faces<1>() + j] =
3289 crs.col[i]; // set vertex indices
3290 }
3291
3292 // TriaObjects: quads
3293 if (dim == 3)
3294 {
3295 auto &quads_0 = tria.faces->quads; // data structures to be filled
3296 auto &faces = *tria.faces;
3297
3298 // get connectivity between quads and lines
3299 const auto &crs = connectivity.entity_to_entities(2, 1);
3300 const unsigned int n_quads = crs.ptr.size() - 1;
3301
3302 // allocate memory
3303 reserve_space_(quads_0, n_quads);
3304 reserve_space_(faces, 2 /*structdim*/, n_quads);
3305
3306 // loop over all quads -> entity type, line indices/orientations
3307 for (unsigned int q = 0, k = 0; q < n_quads; ++q)
3308 {
3309 // set entity type of quads
3310 const auto reference_cell = connectivity.entity_types(2)[q];
3311 faces.set_quad_type(q, reference_cell);
3312
3313 // loop over all its lines
3314 for (unsigned int i = crs.ptr[q], j = 0; i < crs.ptr[q + 1];
3315 ++i, ++j, ++k)
3316 {
3317 AssertIndexRange(j, reference_cell.n_lines());
3318 // set line index
3319 quads_0.cells[q * ReferenceCells::max_n_lines<2>() + j] =
3320 crs.col[i];
3321
3322 // set line orientations
3323 const auto combined_orientation =
3324 connectivity.entity_orientations(1)
3325 .get_combined_orientation(k);
3326 // it doesn't make sense to set any flags except
3327 // orientation for a line
3333 // Same convention as TriaAccessor::set_line_orientation():
3334 // store true for the default orientation and false for
3335 // reversed.
3336 faces.quads_line_orientations
3337 [q * ReferenceCells::max_n_lines<2>() + j] =
3340 }
3341 }
3342 }
3343
3344 // TriaObjects/TriaLevel: cell
3345 {
3346 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3347 auto &level = *tria.levels[0];
3348
3349 // get connectivity between cells/faces and cells/cells
3350 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3351 const auto &nei = connectivity.entity_to_entities(dim, dim);
3352
3353 // in 2d optional: since in in pure QUAD meshes same line
3354 // orientations can be guaranteed
3355 bool orientation_needed = false;
3356 if (dim == 3)
3357 orientation_needed = true;
3358 else if (dim == 2)
3359 {
3360 const auto &orientations = connectivity.entity_orientations(1);
3361 for (unsigned int i = 0; i < orientations.n_objects(); ++i)
3362 if (orientations.get_combined_orientation(i) !=
3364 {
3365 orientation_needed = true;
3366 break;
3367 }
3368 }
3369
3370 // allocate memory
3373
3374 // loop over all cells
3375 for (unsigned int cell = 0; cell < n_cell; ++cell)
3376 {
3377 // set material ids
3378 cells_0.boundary_or_material_id[cell].material_id =
3379 cells[cell].material_id;
3380
3381 // set manifold ids
3382 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3383
3384 // set entity types
3385 level.reference_cell[cell] = connectivity.entity_types(dim)[cell];
3386
3387 // loop over faces
3388 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3389 ++i, ++j)
3390 {
3391 // set neighbor if not at boundary
3392 if (nei.col[i] != static_cast<unsigned int>(-1))
3393 level.neighbors[cell * ReferenceCells::max_n_faces<dim>() +
3394 j] = {0, nei.col[i]};
3395
3396 // set face indices
3397 cells_0.cells[cell * ReferenceCells::max_n_faces<dim>() + j] =
3398 crs.col[i];
3399
3400 // set face orientation if needed
3402 {
3403 level.face_orientations.set_combined_orientation(
3404 cell * ReferenceCells::max_n_faces<dim>() + j,
3405 connectivity.entity_orientations(dim - 1)
3406 .get_combined_orientation(i));
3407 }
3408 }
3409 }
3410 }
3411
3412 // TriaFaces: boundary id of boundary faces
3413 if (dim > 1)
3414 {
3415 auto &bids_face = dim == 3 ?
3416 tria.faces->quads.boundary_or_material_id :
3417 tria.faces->lines.boundary_or_material_id;
3418
3419 // count number of cells a face is belonging to
3420 std::vector<unsigned int> count(bids_face.size(), 0);
3421
3422 // get connectivity between cells/faces
3423 const auto &crs = connectivity.entity_to_entities(dim, dim - 1);
3424
3425 // count how many cells are adjacent to the same face
3426 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3427 for (unsigned int i = crs.ptr[cell]; i < crs.ptr[cell + 1]; ++i)
3428 count[crs.col[i]]++;
3429
3430 // loop over all faces
3431 for (unsigned int face = 0; face < count.size(); ++face)
3432 {
3433 if (count[face] != 1) // inner face
3434 continue;
3435
3436 // boundary faces ...
3437 bids_face[face].boundary_id = 0;
3438
3439 if (dim != 3)
3440 continue;
3441
3442 // ... and the lines of quads in 3d
3443 const auto &crs = connectivity.entity_to_entities(2, 1);
3444 for (unsigned int i = crs.ptr[face]; i < crs.ptr[face + 1]; ++i)
3445 tria.faces->lines.boundary_or_material_id[crs.col[i]]
3446 .boundary_id = 0;
3447 }
3448 }
3449 else // 1d
3450 {
3451 static const unsigned int t_tba = static_cast<unsigned int>(-1);
3452 static const unsigned int t_inner = static_cast<unsigned int>(-2);
3453
3454 std::vector<unsigned int> type(vertices.size(), t_tba);
3455
3456 const auto &crs = connectivity.entity_to_entities(1, 0);
3457
3458 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3459 for (unsigned int i = crs.ptr[cell], j = 0; i < crs.ptr[cell + 1];
3460 ++i, ++j)
3461 if (type[crs.col[i]] != t_inner)
3462 type[crs.col[i]] = type[crs.col[i]] == t_tba ? j : t_inner;
3463
3464 for (unsigned int face = 0; face < type.size(); ++face)
3465 {
3466 // note: we also treat manifolds here!?
3467 (*tria.vertex_to_manifold_id_map_1d)[face] =
3469 if (type[face] != t_inner && type[face] != t_tba)
3470 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3471 }
3472 }
3473
3474 // SubCellData: line
3475 if (dim >= 2)
3476 process_subcelldata(connectivity.entity_to_entities(1, 0),
3477 tria.faces->lines,
3478 subcelldata.boundary_lines,
3479 vertices);
3480
3481 // SubCellData: quad
3482 if (dim == 3)
3483 process_subcelldata(connectivity.entity_to_entities(2, 0),
3484 tria.faces->quads,
3485 subcelldata.boundary_quads,
3486 vertices);
3487 }
3488
3489
3490 template <int structdim, int spacedim, typename T>
3491 static void
3493 const CRS<T> &crs,
3495 const std::vector<CellData<structdim>> &boundary_objects_in,
3496 const std::vector<Point<spacedim>> &vertex_locations)
3497 {
3498 AssertDimension(obj.structdim, structdim);
3499
3500 if (boundary_objects_in.empty())
3501 return; // empty subcelldata -> nothing to do
3502
3503 // pre-sort subcelldata
3505
3506 // ... sort vertices
3507 for (auto &boundary_object : boundary_objects)
3508 std::sort(boundary_object.vertices.begin(),
3509 boundary_object.vertices.end());
3510
3511 // ... sort cells
3512 std::sort(boundary_objects.begin(),
3513 boundary_objects.end(),
3514 [](const auto &a, const auto &b) {
3515 return a.vertices < b.vertices;
3516 });
3517
3518 [[maybe_unused]] unsigned int counter = 0;
3519
3520 std::vector<unsigned int> key;
3521 key.reserve(ReferenceCells::max_n_vertices<structdim>());
3522
3523 for (unsigned int o = 0; o < obj.n_objects(); ++o)
3524 {
3525 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
3526 auto &manifold_id = obj.manifold_id[o];
3527
3528 // assert that object has not been visited yet and its value
3529 // has not been modified yet
3530 AssertThrow(boundary_id == 0 ||
3535
3536 // create key
3537 key.assign(crs.col.data() + crs.ptr[o],
3538 crs.col.data() + crs.ptr[o + 1]);
3539 std::sort(key.begin(), key.end());
3540
3541 // is subcelldata provided? -> binary search
3542 const auto subcell_object =
3543 std::lower_bound(boundary_objects.begin(),
3544 boundary_objects.end(),
3545 key,
3546 [&](const auto &cell, const auto &key) {
3547 return cell.vertices < key;
3548 });
3549
3550 // no subcelldata provided for this object
3551 if (subcell_object == boundary_objects.end() ||
3552 subcell_object->vertices != key)
3553 continue;
3554
3555 ++counter;
3556
3557 // set manifold id
3558 manifold_id = subcell_object->manifold_id;
3559
3560 // set boundary id
3561 if (subcell_object->boundary_id !=
3563 {
3566 ExcMessage(
3567 "The input arguments for creating a triangulation "
3568 "specified a boundary id for an internal face. This "
3569 "is not allowed."
3570 "\n\n"
3571 "The object in question has vertex indices " +
3572 [subcell_object]() {
3573 std::string s;
3574 for (const auto v : subcell_object->vertices)
3575 s += std::to_string(v) + ',';
3576 return s;
3577 }() +
3578 " which are located at coordinates " +
3580 std::ostringstream s;
3581 for (unsigned int i = 0;
3582 i < subcell_object->vertices.size();
3583 ++i)
3584 s << '('
3585 << vertex_locations[subcell_object->vertices[i]]
3586 << (i != subcell_object->vertices.size() - 1 ? "), " :
3587 ")");
3588 return s.str();
3589 }() +
3590 "."));
3591 boundary_id = subcell_object->boundary_id;
3592 }
3593 }
3594
3595 // make sure that all subcelldata entries have been processed
3596 // TODO: this is not guaranteed, why?
3597 // AssertDimension(counter, boundary_objects_in.size());
3598 }
3599
3600
3601
3602 static void
3604 const unsigned structdim,
3605 const unsigned int size)
3606 {
3607 const unsigned int dim = faces.dim;
3608
3609 if (dim == 3 && structdim == 2)
3610 {
3611 // quad entity types
3612 faces.quad_is_quadrilateral.assign(size, true);
3613
3614 // quad line orientations
3615 faces.quads_line_orientations.assign(size * max_n_faces(structdim),
3616 true);
3617 }
3618 }
3619
3620
3621
3622 static void
3624 const unsigned int spacedim,
3625 const unsigned int size,
3626 const bool orientation_needed)
3627 {
3628 const unsigned int dim = level.dim;
3629
3630 level.active_cell_indices.assign(size, numbers::invalid_unsigned_int);
3631 level.subdomain_ids.assign(size, 0);
3632 level.level_subdomain_ids.assign(size, 0);
3633
3634 level.refine_flags.assign(size, 0u);
3635 level.refine_choice.assign(size, 0u);
3636 level.coarsen_flags.assign(size, false);
3637
3638 level.parents.assign((size + 1) / 2, -1);
3639
3640 if (dim == spacedim - 1)
3641 level.direction_flags.assign(size, true);
3642
3643 level.neighbors.assign(size * max_n_faces(dim), {-1, -1});
3644
3645 level.reference_cell.assign(size, ReferenceCells::Invalid);
3646
3648 level.face_orientations.reinit(size * max_n_faces(dim));
3649
3650
3651 level.global_active_cell_indices.assign(size,
3653 level.global_level_cell_indices.assign(size,
3655 }
3656
3657
3658
3659 static void
3660 reserve_space_(TriaObjects &obj, const unsigned int size)
3661 {
3662 const unsigned int structdim = obj.structdim;
3663
3664 const unsigned int max_children_per_cell = 1 << structdim;
3665
3666 obj.used.assign(size, true);
3667 obj.boundary_or_material_id.assign(
3668 size,
3670 BoundaryOrMaterialId());
3671 obj.manifold_id.assign(size, -1);
3672 obj.user_flags.assign(size, false);
3673 obj.user_data.resize(size);
3674
3675 if (structdim > 1) // TODO: why?
3676 obj.refinement_cases.assign(size, 0);
3677
3678 obj.children.assign(max_children_per_cell / 2 * size, -1);
3679
3680 obj.cells.assign(size * max_n_faces(structdim), -1);
3681
3682 if (structdim <= 2)
3683 {
3684 obj.next_free_single = size - 1;
3685 obj.next_free_pair = 0;
3686 obj.reverse_order_next_free_single = true;
3687 }
3688 else
3689 {
3690 obj.next_free_single = obj.next_free_pair = 0;
3691 }
3692 }
3693
3694
3710 template <int spacedim>
3711 static void
3714 std::vector<unsigned int> &,
3715 std::vector<unsigned int> &)
3716 {
3717 const unsigned int dim = 1;
3718
3719 // first we need to reset the
3720 // neighbor pointers of the
3721 // neighbors of this cell's
3722 // children to this cell. This is
3723 // different for one dimension,
3724 // since there neighbors can have a
3725 // refinement level differing from
3726 // that of this cell's children by
3727 // more than one level.
3728
3729 Assert(!cell->child(0)->has_children() &&
3730 !cell->child(1)->has_children(),
3732
3733 // first do it for the cells to the
3734 // left
3735 if (cell->neighbor(0).state() == IteratorState::valid)
3736 if (cell->neighbor(0)->has_children())
3737 {
3739 cell->neighbor(0);
3740 Assert(neighbor->level() == cell->level(), ExcInternalError());
3741
3742 // right child
3743 neighbor = neighbor->child(1);
3744 while (true)
3745 {
3746 Assert(neighbor->neighbor(1) == cell->child(0),
3748 neighbor->set_neighbor(1, cell);
3749
3750 // move on to further
3751 // children on the
3752 // boundary between this
3753 // cell and its neighbor
3754 if (neighbor->has_children())
3755 neighbor = neighbor->child(1);
3756 else
3757 break;
3758 }
3759 }
3760
3761 // now do it for the cells to the
3762 // left
3763 if (cell->neighbor(1).state() == IteratorState::valid)
3764 if (cell->neighbor(1)->has_children())
3765 {
3767 cell->neighbor(1);
3768 Assert(neighbor->level() == cell->level(), ExcInternalError());
3769
3770 // left child
3771 neighbor = neighbor->child(0);
3772 while (true)
3773 {
3774 Assert(neighbor->neighbor(0) == cell->child(1),
3776 neighbor->set_neighbor(0, cell);
3777
3778 // move on to further
3779 // children on the
3780 // boundary between this
3781 // cell and its neighbor
3782 if (neighbor->has_children())
3783 neighbor = neighbor->child(0);
3784 else
3785 break;
3786 }
3787 }
3788
3789
3790 // delete the vertex which will not
3791 // be needed anymore. This vertex
3792 // is the second of the first child
3793 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
3794
3795 // invalidate children. clear user
3796 // pointers, to avoid that they may
3797 // appear at unwanted places later
3798 // on...
3799 for (unsigned int child = 0; child < cell->n_children(); ++child)
3800 {
3801 cell->child(child)->clear_user_data();
3802 cell->child(child)->clear_user_flag();
3803 cell->child(child)->clear_used_flag();
3804 }
3805
3806
3807 // delete pointer to children
3808 cell->clear_children();
3809 cell->clear_user_flag();
3810 }
3811
3812
3813
3814 template <int spacedim>
3815 static void
3818 std::vector<unsigned int> &line_cell_count,
3819 std::vector<unsigned int> &)
3820 {
3821 const unsigned int dim = 2;
3822 const RefinementCase<dim> ref_case = cell->refinement_case();
3823
3824 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3826
3827 // vectors to hold all lines which
3828 // may be deleted
3829 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3830 lines_to_delete(0);
3831
3832 lines_to_delete.reserve(4 * 2 + 4);
3833
3834 // now we decrease the counters for
3835 // lines contained in the child
3836 // cells
3837 for (unsigned int c = 0; c < cell->n_children(); ++c)
3838 {
3840 cell->child(c);
3841 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
3842 --line_cell_count[child->line_index(l)];
3843 }
3844
3845
3846 // delete the vertex which will not
3847 // be needed anymore. This vertex
3848 // is the second of the second line
3849 // of the first child, if the cell
3850 // is refined with cut_xy, else there
3851 // is no inner vertex.
3852 // additionally delete unneeded inner
3853 // lines
3855 {
3857 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
3858
3859 lines_to_delete.push_back(cell->child(0)->line(1));
3860 lines_to_delete.push_back(cell->child(0)->line(3));
3861 lines_to_delete.push_back(cell->child(3)->line(0));
3862 lines_to_delete.push_back(cell->child(3)->line(2));
3863 }
3864 else
3865 {
3866 unsigned int inner_face_no =
3868
3869 // the inner line will not be
3870 // used any more
3871 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
3872 }
3873
3874 // invalidate children
3875 for (unsigned int child = 0; child < cell->n_children(); ++child)
3876 {
3877 cell->child(child)->clear_user_data();
3878 cell->child(child)->clear_user_flag();
3879 cell->child(child)->clear_used_flag();
3880 }
3881
3882
3883 // delete pointer to children
3884 cell->clear_children();
3885 cell->clear_refinement_case();
3886 cell->clear_user_flag();
3887
3888 // look at the refinement of outer
3889 // lines. if nobody needs those
3890 // anymore we can add them to the
3891 // list of lines to be deleted.
3892 for (unsigned int line_no = 0;
3894 ++line_no)
3895 {
3897 cell->line(line_no);
3898
3899 if (line->has_children())
3900 {
3901 // if one of the cell counters is
3902 // zero, the other has to be as well
3903
3904 Assert((line_cell_count[line->child_index(0)] == 0 &&
3905 line_cell_count[line->child_index(1)] == 0) ||
3906 (line_cell_count[line->child_index(0)] > 0 &&
3907 line_cell_count[line->child_index(1)] > 0),
3909
3910 if (line_cell_count[line->child_index(0)] == 0)
3911 {
3912 for (unsigned int c = 0; c < 2; ++c)
3913 Assert(!line->child(c)->has_children(),
3915
3916 // we may delete the line's
3917 // children and the middle vertex
3918 // as no cell references them
3919 // anymore
3921 .vertices_used[line->child(0)->vertex_index(1)] = false;
3922
3923 lines_to_delete.push_back(line->child(0));
3924 lines_to_delete.push_back(line->child(1));
3925
3926 line->clear_children();
3927 }
3928 }
3929 }
3930
3931 // finally, delete unneeded lines
3932
3933 // clear user pointers, to avoid that
3934 // they may appear at unwanted places
3935 // later on...
3936 // same for user flags, then finally
3937 // delete the lines
3938 typename std::vector<
3940 line = lines_to_delete.begin(),
3941 endline = lines_to_delete.end();
3942 for (; line != endline; ++line)
3943 {
3944 (*line)->clear_user_data();
3945 (*line)->clear_user_flag();
3946 (*line)->clear_used_flag();
3947 }
3948 }
3949
3950
3951
3952 template <int spacedim>
3953 static void
3956 std::vector<unsigned int> &line_cell_count,
3957 std::vector<unsigned int> &quad_cell_count)
3958 {
3959 const unsigned int dim = 3;
3960
3961 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
3963 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
3965
3966 // first of all, we store the RefineCase of
3967 // this cell
3968 const RefinementCase<dim> ref_case = cell->refinement_case();
3969 // vectors to hold all lines and quads which
3970 // may be deleted
3971 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
3972 lines_to_delete(0);
3973 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
3974 quads_to_delete(0);
3975
3976 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
3977 quads_to_delete.reserve(6 * 4 + 12);
3978
3979 // now we decrease the counters for lines and
3980 // quads contained in the child cells
3981 for (unsigned int c = 0; c < cell->n_children(); ++c)
3982 {
3984 cell->child(c);
3985 const auto line_indices = TriaAccessorImplementation::
3986 Implementation::get_line_indices_of_cell(*child);
3987 for (const unsigned int l : cell->line_indices())
3988 --line_cell_count[line_indices[l]];
3989 for (auto f : GeometryInfo<dim>::face_indices())
3990 --quad_cell_count[child->quad_index(f)];
3991 }
3992
3993 //-------------------------------------
3994 // delete interior quads and lines and the
3995 // interior vertex, depending on the
3996 // refinement case of the cell
3997 //
3998 // for append quads and lines: only append
3999 // them to the list of objects to be deleted
4000
4001 switch (ref_case)
4002 {
4004 quads_to_delete.push_back(cell->child(0)->face(1));
4005 break;
4007 quads_to_delete.push_back(cell->child(0)->face(3));
4008 break;
4010 quads_to_delete.push_back(cell->child(0)->face(5));
4011 break;
4013 quads_to_delete.push_back(cell->child(0)->face(1));
4014 quads_to_delete.push_back(cell->child(0)->face(3));
4015 quads_to_delete.push_back(cell->child(3)->face(0));
4016 quads_to_delete.push_back(cell->child(3)->face(2));
4017
4018 lines_to_delete.push_back(cell->child(0)->line(11));
4019 break;
4021 quads_to_delete.push_back(cell->child(0)->face(1));
4022 quads_to_delete.push_back(cell->child(0)->face(5));
4023 quads_to_delete.push_back(cell->child(3)->face(0));
4024 quads_to_delete.push_back(cell->child(3)->face(4));
4025
4026 lines_to_delete.push_back(cell->child(0)->line(5));
4027 break;
4029 quads_to_delete.push_back(cell->child(0)->face(3));
4030 quads_to_delete.push_back(cell->child(0)->face(5));
4031 quads_to_delete.push_back(cell->child(3)->face(2));
4032 quads_to_delete.push_back(cell->child(3)->face(4));
4033
4034 lines_to_delete.push_back(cell->child(0)->line(7));
4035 break;
4037 quads_to_delete.push_back(cell->child(0)->face(1));
4038 quads_to_delete.push_back(cell->child(2)->face(1));
4039 quads_to_delete.push_back(cell->child(4)->face(1));
4040 quads_to_delete.push_back(cell->child(6)->face(1));
4041
4042 quads_to_delete.push_back(cell->child(0)->face(3));
4043 quads_to_delete.push_back(cell->child(1)->face(3));
4044 quads_to_delete.push_back(cell->child(4)->face(3));
4045 quads_to_delete.push_back(cell->child(5)->face(3));
4046
4047 quads_to_delete.push_back(cell->child(0)->face(5));
4048 quads_to_delete.push_back(cell->child(1)->face(5));
4049 quads_to_delete.push_back(cell->child(2)->face(5));
4050 quads_to_delete.push_back(cell->child(3)->face(5));
4051
4052 lines_to_delete.push_back(cell->child(0)->line(5));
4053 lines_to_delete.push_back(cell->child(0)->line(7));
4054 lines_to_delete.push_back(cell->child(0)->line(11));
4055 lines_to_delete.push_back(cell->child(7)->line(0));
4056 lines_to_delete.push_back(cell->child(7)->line(2));
4057 lines_to_delete.push_back(cell->child(7)->line(8));
4058 // delete the vertex which will not
4059 // be needed anymore. This vertex
4060 // is the vertex at the heart of
4061 // this cell, which is the sixth of
4062 // the first child
4063 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4064 false;
4065 break;
4066 default:
4067 // only remaining case is
4068 // no_refinement, thus an error
4070 break;
4071 }
4072
4073
4074 // invalidate children
4075 for (unsigned int child = 0; child < cell->n_children(); ++child)
4076 {
4077 cell->child(child)->clear_user_data();
4078 cell->child(child)->clear_user_flag();
4079
4080 for (auto f : GeometryInfo<dim>::face_indices())
4081 // set flags denoting deviations from standard orientation of
4082 // faces back to initialization values
4083 cell->child(child)->set_combined_face_orientation(
4085
4086 cell->child(child)->clear_used_flag();
4087 }
4088
4089
4090 // delete pointer to children
4091 cell->clear_children();
4092 cell->clear_refinement_case();
4093 cell->clear_user_flag();
4094
4095 // so far we only looked at inner quads,
4096 // lines and vertices. Now we have to
4097 // consider outer ones as well. here, we have
4098 // to check, whether there are other cells
4099 // still needing these objects. otherwise we
4100 // can delete them. first for quads (and
4101 // their inner lines).
4102
4103 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4104 {
4106 cell->face(quad_no);
4107
4108 Assert(
4110 quad->has_children()) ||
4114
4115 switch (quad->refinement_case())
4116 {
4117 case RefinementCase<dim - 1>::no_refinement:
4118 // nothing to do as the quad
4119 // is not refined
4120 break;
4121 case RefinementCase<dim - 1>::cut_x:
4122 case RefinementCase<dim - 1>::cut_y:
4123 {
4124 // if one of the cell counters is
4125 // zero, the other has to be as
4126 // well
4127 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4128 quad_cell_count[quad->child_index(1)] == 0) ||
4129 (quad_cell_count[quad->child_index(0)] > 0 &&
4130 quad_cell_count[quad->child_index(1)] > 0),
4132 // it might be, that the quad is
4133 // refined twice anisotropically,
4134 // first check, whether we may
4135 // delete possible grand_children
4136 unsigned int deleted_grandchildren = 0;
4137 unsigned int number_of_child_refinements = 0;
4138
4139 for (unsigned int c = 0; c < 2; ++c)
4140 if (quad->child(c)->has_children())
4141 {
4143 // if one of the cell counters is
4144 // zero, the other has to be as
4145 // well
4146 Assert(
4147 (quad_cell_count[quad->child(c)->child_index(0)] ==
4148 0 &&
4149 quad_cell_count[quad->child(c)->child_index(1)] ==
4150 0) ||
4151 (quad_cell_count[quad->child(c)->child_index(0)] >
4152 0 &&
4153 quad_cell_count[quad->child(c)->child_index(1)] >
4154 0),
4156 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4157 0)
4158 {
4159 // Assert, that the two
4160 // anisotropic
4161 // refinements add up to
4162 // isotropic refinement
4163 Assert(quad->refinement_case() +
4164 quad->child(c)->refinement_case() ==
4167 // we may delete the
4168 // quad's children and
4169 // the inner line as no
4170 // cell references them
4171 // anymore
4172 quads_to_delete.push_back(
4173 quad->child(c)->child(0));
4174 quads_to_delete.push_back(
4175 quad->child(c)->child(1));
4176 if (quad->child(c)->refinement_case() ==
4178 lines_to_delete.push_back(
4179 quad->child(c)->child(0)->line(1));
4180 else
4181 lines_to_delete.push_back(
4182 quad->child(c)->child(0)->line(3));
4183 quad->child(c)->clear_children();
4184 quad->child(c)->clear_refinement_case();
4186 }
4187 }
4188 // if no grandchildren are left, we
4189 // may as well delete the
4190 // refinement of the inner line
4191 // between our children and the
4192 // corresponding vertex
4195 {
4198 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4199 middle_line = quad->child(0)->line(1);
4200 else
4201 middle_line = quad->child(0)->line(3);
4202
4203 lines_to_delete.push_back(middle_line->child(0));
4204 lines_to_delete.push_back(middle_line->child(1));
4207 middle_line)] = false;
4208 middle_line->clear_children();
4209 }
4210
4211 // now consider the direct children
4212 // of the given quad
4213 if (quad_cell_count[quad->child_index(0)] == 0)
4214 {
4215 // we may delete the quad's
4216 // children and the inner line
4217 // as no cell references them
4218 // anymore
4219 quads_to_delete.push_back(quad->child(0));
4220 quads_to_delete.push_back(quad->child(1));
4221 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4222 lines_to_delete.push_back(quad->child(0)->line(1));
4223 else
4224 lines_to_delete.push_back(quad->child(0)->line(3));
4225
4226 // if the counters just dropped
4227 // to zero, otherwise the
4228 // children would have been
4229 // deleted earlier, then this
4230 // cell's children must have
4231 // contained the anisotropic
4232 // quad children. thus, if
4233 // those have again anisotropic
4234 // children, which are in
4235 // effect isotropic children of
4236 // the original quad, those are
4237 // still needed by a
4238 // neighboring cell and we
4239 // cannot delete them. instead,
4240 // we have to reset this quad's
4241 // refine case to isotropic and
4242 // set the children
4243 // accordingly.
4244 if (quad->child(0)->has_children())
4245 if (quad->refinement_case() ==
4247 {
4248 // now evereything is
4249 // quite complicated. we
4250 // have the children
4251 // numbered according to
4252 //
4253 // *---*---*
4254 // |n+1|m+1|
4255 // *---*---*
4256 // | n | m |
4257 // *---*---*
4258 //
4259 // from the original
4260 // anisotropic
4261 // refinement. we have to
4262 // reorder them as
4263 //
4264 // *---*---*
4265 // | m |m+1|
4266 // *---*---*
4267 // | n |n+1|
4268 // *---*---*
4269 //
4270 // for isotropic refinement.
4271 //
4272 // this is a bit ugly, of
4273 // course: loop over all
4274 // cells on all levels
4275 // and look for faces n+1
4276 // (switch_1) and m
4277 // (switch_2).
4278 const typename Triangulation<dim, spacedim>::
4280 quad->child(0)->child(1),
4281 switch_2 =
4282 quad->child(1)->child(0);
4283
4284 Assert(!switch_1->has_children(),
4286 Assert(!switch_2->has_children(),
4288
4289 const int switch_1_index = switch_1->index();
4290 const int switch_2_index = switch_2->index();
4291 for (unsigned int l = 0;
4292 l < triangulation.levels.size();
4293 ++l)
4294 for (unsigned int h = 0;
4295 h <
4296 triangulation.levels[l]->cells.n_objects();
4297 ++h)
4298 for (const unsigned int q :
4300 {
4301 const int index =
4302 triangulation.levels[l]
4303 ->cells.get_bounding_object_indices(
4304 h)[q];
4305 if (index == switch_1_index)
4306 triangulation.levels[l]
4307 ->cells.get_bounding_object_indices(
4308 h)[q] = switch_2_index;
4309 else if (index == switch_2_index)
4310 triangulation.levels[l]
4311 ->cells.get_bounding_object_indices(
4312 h)[q] = switch_1_index;
4313 }
4314 // now we have to copy
4315 // all information of the
4316 // two quads
4317 const int switch_1_lines[4] = {
4318 static_cast<signed int>(
4319 switch_1->line_index(0)),
4320 static_cast<signed int>(
4321 switch_1->line_index(1)),
4322 static_cast<signed int>(
4323 switch_1->line_index(2)),
4324 static_cast<signed int>(
4325 switch_1->line_index(3))};
4328 switch_1->line_orientation(0),
4329 switch_1->line_orientation(1),
4330 switch_1->line_orientation(2),
4331 switch_1->line_orientation(3)};
4333 switch_1->boundary_id();
4334 const unsigned int switch_1_user_index =
4335 switch_1->user_index();
4336 const bool switch_1_user_flag =
4337 switch_1->user_flag_set();
4338
4339 switch_1->set_bounding_object_indices(
4340 {switch_2->line_index(0),
4341 switch_2->line_index(1),
4342 switch_2->line_index(2),
4343 switch_2->line_index(3)});
4344 switch_1->set_line_orientation(
4345 0, switch_2->line_orientation(0));
4346 switch_1->set_line_orientation(
4347 1, switch_2->line_orientation(1));
4348 switch_1->set_line_orientation(
4349 2, switch_2->line_orientation(2));
4350 switch_1->set_line_orientation(
4351 3, switch_2->line_orientation(3));
4352 switch_1->set_boundary_id_internal(
4353 switch_2->boundary_id());
4354 switch_1->set_manifold_id(
4355 switch_2->manifold_id());
4356 switch_1->set_user_index(switch_2->user_index());
4357 if (switch_2->user_flag_set())
4358 switch_1->set_user_flag();
4359 else
4360 switch_1->clear_user_flag();
4361
4362 switch_2->set_bounding_object_indices(
4363 {switch_1_lines[0],
4364 switch_1_lines[1],
4365 switch_1_lines[2],
4366 switch_1_lines[3]});
4367 switch_2->set_line_orientation(
4369 switch_2->set_line_orientation(
4371 switch_2->set_line_orientation(
4373 switch_2->set_line_orientation(
4375 switch_2->set_boundary_id_internal(
4377 switch_2->set_manifold_id(
4378 switch_1->manifold_id());
4379 switch_2->set_user_index(switch_1_user_index);
4381 switch_2->set_user_flag();
4382 else
4383 switch_2->clear_user_flag();
4384
4385 const unsigned int child_0 =
4386 quad->child(0)->child_index(0);
4387 const unsigned int child_2 =
4388 quad->child(1)->child_index(0);
4389 quad->clear_children();
4390 quad->clear_refinement_case();
4391 quad->set_refinement_case(
4393 quad->set_children(0, child_0);
4394 quad->set_children(2, child_2);
4395 std::swap(quad_cell_count[child_0 + 1],
4397 }
4398 else
4399 {
4400 // the face was refined
4401 // with cut_y, thus the
4402 // children are already
4403 // in correct order. we
4404 // only have to set them
4405 // correctly, deleting
4406 // the indirection of two
4407 // anisotropic refinement
4408 // and going directly
4409 // from the quad to
4410 // isotropic children
4411 const unsigned int child_0 =
4412 quad->child(0)->child_index(0);
4413 const unsigned int child_2 =
4414 quad->child(1)->child_index(0);
4415 quad->clear_children();
4416 quad->clear_refinement_case();
4417 quad->set_refinement_case(
4419 quad->set_children(0, child_0);
4420 quad->set_children(2, child_2);
4421 }
4422 else
4423 {
4424 quad->clear_children();
4425 quad->clear_refinement_case();
4426 }
4427 }
4428 break;
4429 }
4430 case RefinementCase<dim - 1>::cut_xy:
4431 {
4432 // if one of the cell counters is
4433 // zero, the others have to be as
4434 // well
4435
4436 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4437 quad_cell_count[quad->child_index(1)] == 0 &&
4438 quad_cell_count[quad->child_index(2)] == 0 &&
4439 quad_cell_count[quad->child_index(3)] == 0) ||
4440 (quad_cell_count[quad->child_index(0)] > 0 &&
4441 quad_cell_count[quad->child_index(1)] > 0 &&
4442 quad_cell_count[quad->child_index(2)] > 0 &&
4443 quad_cell_count[quad->child_index(3)] > 0),
4445
4446 if (quad_cell_count[quad->child_index(0)] == 0)
4447 {
4448 // we may delete the quad's
4449 // children, the inner lines
4450 // and the middle vertex as no
4451 // cell references them anymore
4452 lines_to_delete.push_back(quad->child(0)->line(1));
4453 lines_to_delete.push_back(quad->child(3)->line(0));
4454 lines_to_delete.push_back(quad->child(0)->line(3));
4455 lines_to_delete.push_back(quad->child(3)->line(2));
4456
4457 for (unsigned int child = 0; child < quad->n_children();
4458 ++child)
4459 quads_to_delete.push_back(quad->child(child));
4460
4462 .vertices_used[quad->child(0)->vertex_index(3)] =
4463 false;
4464
4465 quad->clear_children();
4466 quad->clear_refinement_case();
4467 }
4468 }
4469 break;
4470
4471 default:
4473 break;
4474 }
4475 }
4476
4477 // now we repeat a similar procedure
4478 // for the outer lines of this cell.
4479
4480 // if in debug mode: check that each
4481 // of the lines for which we consider
4482 // deleting the children in fact has
4483 // children (the bits/coarsening_3d
4484 // test tripped over this initially)
4485 for (unsigned int line_no = 0;
4487 ++line_no)
4488 {
4490 cell->line(line_no);
4491
4492 Assert(
4494 line->has_children()) ||
4498
4499 if (line->has_children())
4500 {
4501 // if one of the cell counters is
4502 // zero, the other has to be as well
4503
4504 Assert((line_cell_count[line->child_index(0)] == 0 &&
4505 line_cell_count[line->child_index(1)] == 0) ||
4506 (line_cell_count[line->child_index(0)] > 0 &&
4507 line_cell_count[line->child_index(1)] > 0),
4509
4510 if (line_cell_count[line->child_index(0)] == 0)
4511 {
4512 for (unsigned int c = 0; c < 2; ++c)
4513 Assert(!line->child(c)->has_children(),
4515
4516 // we may delete the line's
4517 // children and the middle vertex
4518 // as no cell references them
4519 // anymore
4521 .vertices_used[line->child(0)->vertex_index(1)] = false;
4522
4523 lines_to_delete.push_back(line->child(0));
4524 lines_to_delete.push_back(line->child(1));
4525
4526 line->clear_children();
4527 }
4528 }
4529 }
4530
4531 // finally, delete unneeded quads and lines
4532
4533 // clear user pointers, to avoid that
4534 // they may appear at unwanted places
4535 // later on...
4536 // same for user flags, then finally
4537 // delete the quads and lines
4538 typename std::vector<
4540 line = lines_to_delete.begin(),
4541 endline = lines_to_delete.end();
4542 for (; line != endline; ++line)
4543 {
4544 (*line)->clear_user_data();
4545 (*line)->clear_user_flag();
4546 (*line)->clear_used_flag();
4547 }
4548
4549 typename std::vector<
4551 quad = quads_to_delete.begin(),
4552 endquad = quads_to_delete.end();
4553 for (; quad != endquad; ++quad)
4554 {
4555 (*quad)->clear_user_data();
4556 (*quad)->clear_children();
4557 (*quad)->clear_refinement_case();
4558 (*quad)->clear_user_flag();
4559 (*quad)->clear_used_flag();
4560 }
4561 }
4562
4563
4581 template <int spacedim>
4582 static void
4585 unsigned int &next_unused_vertex,
4590 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4591 {
4592 const unsigned int dim = 2;
4593 // clear refinement flag
4594 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4595 cell->clear_refine_flag();
4596
4597 /* For the refinement process: since we go the levels up from the
4598 lowest, there are (unlike above) only two possibilities: a neighbor
4599 cell is on the same level or one level up (in both cases, it may or
4600 may not be refined later on, but we don't care here).
4601
4602 First:
4603 Set up an array of the 3x3 vertices, which are distributed on the
4604 cell (the array consists of indices into the @p{vertices} std::vector
4605
4606 2--7--3
4607 | | |
4608 4--8--5
4609 | | |
4610 0--6--1
4611
4612 note: in case of cut_x or cut_y not all these vertices are needed for
4613 the new cells
4614
4615 Second:
4616 Set up an array of the new lines (the array consists of iterator
4617 pointers into the lines arrays)
4618
4619 .-6-.-7-. The directions are: .->-.->-.
4620 1 9 3 ^ ^ ^
4621 .-10.11-. .->-.->-.
4622 0 8 2 ^ ^ ^
4623 .-4-.-5-. .->-.->-.
4624
4625 cut_x:
4626 .-4-.-5-.
4627 | | |
4628 0 6 1
4629 | | |
4630 .-2-.-3-.
4631
4632 cut_y:
4633 .---5---.
4634 1 3
4635 .---6---.
4636 0 2
4637 .---4---.
4638
4639
4640 Third:
4641 Set up an array of neighbors:
4642
4643 6 7
4644 .--.--.
4645 1| | |3
4646 .--.--.
4647 0| | |2
4648 .--.--.
4649 4 5
4650
4651 We need this array for two reasons: first to get the lines which will
4652 bound the four subcells (if the neighboring cell is refined, these
4653 lines already exist), and second to update neighborship information.
4654 Since if a neighbor is not refined, its neighborship record only
4655 points to the present, unrefined, cell rather than the children we
4656 are presently creating, we only need the neighborship information
4657 if the neighbor cells are refined. In all other cases, we store
4658 the unrefined neighbor address
4659
4660 We also need for every neighbor (if refined) which number among its
4661 neighbors the present (unrefined) cell has, since that number is to
4662 be replaced and because that also is the number of the subline which
4663 will be the interface between that neighbor and the to be created
4664 cell. We will store this number (between 0 and 3) in the field
4665 @p{neighbors_neighbor}.
4666
4667 It would be sufficient to use the children of the common line to the
4668 neighbor, if we only wanted to get the new sublines and the new
4669 vertex, but because we need to update the neighborship information of
4670 the two refined subcells of the neighbor, we need to search these
4671 anyway.
4672
4673 Convention:
4674 The created children are numbered like this:
4675
4676 .--.--.
4677 |2 . 3|
4678 .--.--.
4679 |0 | 1|
4680 .--.--.
4681 */
4682 // collect the indices of the eight surrounding vertices
4683 // 2--7--3
4684 // | | |
4685 // 4--8--5
4686 // | | |
4687 // 0--6--1
4688 int new_vertices[9];
4689 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
4690 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
4691 for (unsigned int line_no = 0; line_no < 4; ++line_no)
4692 if (cell->line(line_no)->has_children())
4693 new_vertices[4 + line_no] =
4694 cell->line(line_no)->child(0)->vertex_index(1);
4695
4697 {
4698 // find the next
4699 // unused vertex and
4700 // allocate it for
4701 // the new vertex we
4702 // need here
4703 while (triangulation.vertices_used[next_unused_vertex] == true)
4705 Assert(next_unused_vertex < triangulation.vertices.size(),
4706 ExcMessage(
4707 "Internal error: During refinement, the triangulation "
4708 "wants to access an element of the 'vertices' array "
4709 "but it turns out that the array is not large enough."));
4710 triangulation.vertices_used[next_unused_vertex] = true;
4711
4713
4714 // determine middle vertex by transfinite interpolation to be
4715 // consistent with what happens to quads in a
4716 // Triangulation<3,3> when they are refined
4718 cell->center(true, true);
4719 }
4720
4721
4722 // Now the lines:
4724 unsigned int lmin = 8;
4725 unsigned int lmax = 12;
4727 {
4728 lmin = 6;
4729 lmax = 7;
4730 }
4731
4732 for (unsigned int l = lmin; l < lmax; ++l)
4733 {
4734 while (next_unused_line->used() == true)
4738
4740 }
4741
4743 {
4744 // .-6-.-7-.
4745 // 1 9 3
4746 // .-10.11-.
4747 // 0 8 2
4748 // .-4-.-5-.
4749
4750 // lines 0-7 already exist, create only the four interior
4751 // lines 8-11
4752 unsigned int l = 0;
4753 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
4754 for (unsigned int c = 0; c < 2; ++c, ++l)
4755 new_lines[l] = cell->line(face_no)->child(c);
4756 Assert(l == 8, ExcInternalError());
4757
4758 new_lines[8]->set_bounding_object_indices(
4759 {new_vertices[6], new_vertices[8]});
4760 new_lines[9]->set_bounding_object_indices(
4761 {new_vertices[8], new_vertices[7]});
4762 new_lines[10]->set_bounding_object_indices(
4763 {new_vertices[4], new_vertices[8]});
4764 new_lines[11]->set_bounding_object_indices(
4765 {new_vertices[8], new_vertices[5]});
4766 }
4768 {
4769 // .-4-.-5-.
4770 // | | |
4771 // 0 6 1
4772 // | | |
4773 // .-2-.-3-.
4774 new_lines[0] = cell->line(0);
4775 new_lines[1] = cell->line(1);
4776 new_lines[2] = cell->line(2)->child(0);
4777 new_lines[3] = cell->line(2)->child(1);
4778 new_lines[4] = cell->line(3)->child(0);
4779 new_lines[5] = cell->line(3)->child(1);
4780 new_lines[6]->set_bounding_object_indices(
4781 {new_vertices[6], new_vertices[7]});
4782 }
4783 else
4784 {
4786 // .---5---.
4787 // 1 3
4788 // .---6---.
4789 // 0 2
4790 // .---4---.
4791 new_lines[0] = cell->line(0)->child(0);
4792 new_lines[1] = cell->line(0)->child(1);
4793 new_lines[2] = cell->line(1)->child(0);
4794 new_lines[3] = cell->line(1)->child(1);
4795 new_lines[4] = cell->line(2);
4796 new_lines[5] = cell->line(3);
4797 new_lines[6]->set_bounding_object_indices(
4798 {new_vertices[4], new_vertices[5]});
4799 }
4800
4801 for (unsigned int l = lmin; l < lmax; ++l)
4802 {
4803 new_lines[l]->set_used_flag();
4804 new_lines[l]->clear_user_flag();
4805 new_lines[l]->clear_user_data();
4806 new_lines[l]->clear_children();
4807 // interior line
4808 new_lines[l]->set_boundary_id_internal(
4810 new_lines[l]->set_manifold_id(cell->manifold_id());
4811 }
4812
4813 // Now add the four (two)
4814 // new cells!
4817 while (next_unused_cell->used() == true)
4819
4820 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
4821 for (unsigned int i = 0; i < n_children; ++i)
4822 {
4826 if (i % 2 == 1 && i < n_children - 1)
4827 while (next_unused_cell->used() == true)
4829 }
4830
4832 {
4833 // children:
4834 // .--.--.
4835 // |2 . 3|
4836 // .--.--.
4837 // |0 | 1|
4838 // .--.--.
4839 // lines:
4840 // .-6-.-7-.
4841 // 1 9 3
4842 // .-10.11-.
4843 // 0 8 2
4844 // .-4-.-5-.
4845 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4846 new_lines[8]->index(),
4847 new_lines[4]->index(),
4848 new_lines[10]->index()});
4849 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
4850 new_lines[2]->index(),
4851 new_lines[5]->index(),
4852 new_lines[11]->index()});
4853 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
4854 new_lines[9]->index(),
4855 new_lines[10]->index(),
4856 new_lines[6]->index()});
4857 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
4858 new_lines[3]->index(),
4859 new_lines[11]->index(),
4860 new_lines[7]->index()});
4861 }
4863 {
4864 // children:
4865 // .--.--.
4866 // | . |
4867 // .0 . 1.
4868 // | | |
4869 // .--.--.
4870 // lines:
4871 // .-4-.-5-.
4872 // | | |
4873 // 0 6 1
4874 // | | |
4875 // .-2-.-3-.
4876 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4877 new_lines[6]->index(),
4878 new_lines[2]->index(),
4879 new_lines[4]->index()});
4880 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
4881 new_lines[1]->index(),
4882 new_lines[3]->index(),
4883 new_lines[5]->index()});
4884 }
4885 else
4886 {
4888 // children:
4889 // .-----.
4890 // | 1 |
4891 // .-----.
4892 // | 0 |
4893 // .-----.
4894 // lines:
4895 // .---5---.
4896 // 1 3
4897 // .---6---.
4898 // 0 2
4899 // .---4---.
4900 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
4901 new_lines[2]->index(),
4902 new_lines[4]->index(),
4903 new_lines[6]->index()});
4904 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
4905 new_lines[3]->index(),
4906 new_lines[6]->index(),
4907 new_lines[5]->index()});
4908 }
4909
4910 types::subdomain_id subdomainid = cell->subdomain_id();
4911
4912 for (unsigned int i = 0; i < n_children; ++i)
4913 {
4914 subcells[i]->set_used_flag();
4915 subcells[i]->clear_refine_flag();
4916 subcells[i]->clear_user_flag();
4917 subcells[i]->clear_user_data();
4918 subcells[i]->clear_children();
4919 // inherit material properties
4920 subcells[i]->set_material_id(cell->material_id());
4921 subcells[i]->set_manifold_id(cell->manifold_id());
4922 subcells[i]->set_subdomain_id(subdomainid);
4923
4924 if (i % 2 == 0)
4925 subcells[i]->set_parent(cell->index());
4926 }
4927
4928
4929
4930 // set child index for even children i=0,2 (0)
4931 for (unsigned int i = 0; i < n_children / 2; ++i)
4932 cell->set_children(2 * i, subcells[2 * i]->index());
4933 // set the refine case
4934 cell->set_refinement_case(ref_case);
4935
4936 // note that the
4937 // refinement flag was
4938 // already cleared at the
4939 // beginning of this function
4940
4941 if (dim == spacedim - 1)
4942 for (unsigned int c = 0; c < n_children; ++c)
4943 cell->child(c)->set_direction_flag(cell->direction_flag());
4944 }
4945
4946
4947
4948 template <int dim, int spacedim>
4951 const bool check_for_distorted_cells)
4952 {
4953 AssertDimension(dim, 2);
4954
4955 // Check whether a new level is needed. We have to check for
4956 // this on the highest level only
4957 for (const auto &cell : triangulation.active_cell_iterators_on_level(
4958 triangulation.levels.size() - 1))
4959 if (cell->refine_flag_set())
4960 {
4961 triangulation.levels.push_back(
4962 std::make_unique<
4964 break;
4965 }
4966
4968 triangulation.begin_line();
4969 line != triangulation.end_line();
4970 ++line)
4971 {
4972 line->clear_user_flag();
4973 line->clear_user_data();
4974 }
4975
4976 unsigned int n_single_lines = 0;
4977 unsigned int n_lines_in_pairs = 0;
4978 unsigned int needed_vertices = 0;
4979
4980 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
4981 {
4982 // count number of flagged cells on this level and compute
4983 // how many new vertices and new lines will be needed
4984 unsigned int needed_cells = 0;
4985
4986 for (const auto &cell :
4987 triangulation.active_cell_iterators_on_level(level))
4988 if (cell->refine_flag_set())
4989 {
4990 if (cell->reference_cell() == ReferenceCells::Triangle)
4991 {
4992 needed_cells += 4;
4993 needed_vertices += 0;
4994 n_single_lines += 3;
4995 }
4996 else if (cell->reference_cell() ==
4998 {
4999 needed_cells += 4;
5000 needed_vertices += 1;
5001 n_single_lines += 4;
5002 }
5003 else
5004 {
5006 }
5007
5008 for (const auto line_no : cell->face_indices())
5009 {
5010 auto line = cell->line(line_no);
5011 if (line->has_children() == false)
5012 line->set_user_flag();
5013 }
5014 }
5015
5016
5017 const unsigned int used_cells =
5018 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5019 triangulation.levels[level + 1]->cells.used.end(),
5020 true);
5021
5022
5023 reserve_space(*triangulation.levels[level + 1],
5025 spacedim);
5026
5027 reserve_space(triangulation.levels[level + 1]->cells,
5029 0);
5030 }
5031
5032 for (auto line = triangulation.begin_line();
5033 line != triangulation.end_line();
5034 ++line)
5035 if (line->user_flag_set())
5036 {
5037 Assert(line->has_children() == false, ExcInternalError());
5038 n_lines_in_pairs += 2;
5039 needed_vertices += 1;
5040 }
5041
5043
5044 needed_vertices += std::count(triangulation.vertices_used.begin(),
5045 triangulation.vertices_used.end(),
5046 true);
5047
5048 if (needed_vertices > triangulation.vertices.size())
5049 {
5050 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5051 triangulation.vertices_used.resize(needed_vertices, false);
5052 }
5053
5054 unsigned int next_unused_vertex = 0;
5055
5056 {
5058 line = triangulation.begin_active_line(),
5059 endl = triangulation.end_line();
5061 next_unused_line = triangulation.begin_raw_line();
5062
5063 for (; line != endl; ++line)
5064 if (line->user_flag_set())
5065 {
5066 // This line needs to be refined. Find the next unused vertex
5067 // and set it appropriately
5068 while (triangulation.vertices_used[next_unused_vertex] == true)
5070 Assert(next_unused_vertex < triangulation.vertices.size(),
5071 ExcMessage(
5072 "Internal error: During refinement, the triangulation "
5073 "wants to access an element of the 'vertices' array "
5074 "but it turns out that the array is not large "
5075 "enough."));
5076 triangulation.vertices_used[next_unused_vertex] = true;
5077
5078 triangulation.vertices[next_unused_vertex] = line->center(true);
5079
5080 [[maybe_unused]] bool pair_found = false;
5082 if (!next_unused_line->used() &&
5083 !(++next_unused_line)->used())
5084 {
5086 pair_found = true;
5087 break;
5088 }
5090
5091 line->set_children(0, next_unused_line->index());
5092
5094 children[2] = {next_unused_line, ++next_unused_line};
5095
5096 AssertIsNotUsed(children[0]);
5097 AssertIsNotUsed(children[1]);
5098
5099 children[0]->set_bounding_object_indices(
5100 {line->vertex_index(0), next_unused_vertex});
5101 children[1]->set_bounding_object_indices(
5102 {next_unused_vertex, line->vertex_index(1)});
5103
5104 for (auto &child : children)
5105 {
5106 child->set_used_flag();
5107 child->clear_children();
5108 child->clear_user_data();
5109 child->clear_user_flag();
5110 child->set_boundary_id_internal(line->boundary_id());
5111 child->set_manifold_id(line->manifold_id());
5112 // Line orientation is relative to the cell it is on so
5113 // those cannot be set at this point.
5114 }
5115
5116 line->clear_user_flag();
5117 }
5118 }
5119
5120 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5121
5124
5126 next_unused_line = triangulation.begin_raw_line();
5127
5128 const auto create_children = [](auto &triangulation,
5129 unsigned int &next_unused_vertex,
5130 auto &next_unused_line,
5131 auto &next_unused_cell,
5132 const auto &cell) {
5133 const auto ref_case = cell->refine_flag_set();
5134 cell->clear_refine_flag();
5135
5136 unsigned int n_new_vertices = 0;
5137
5138 if (cell->reference_cell() == ReferenceCells::Triangle)
5139 n_new_vertices = 6;
5140 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5141 n_new_vertices = 9;
5142 else
5144
5145 std::vector<unsigned int> new_vertices(n_new_vertices,
5147 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5148 ++vertex_no)
5149 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5150 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5151 if (cell->line(line_no)->has_children())
5152 new_vertices[cell->n_vertices() + line_no] =
5153 cell->line(line_no)->child(0)->vertex_index(1);
5154
5155 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5156 {
5157 while (triangulation.vertices_used[next_unused_vertex] == true)
5159 Assert(
5160 next_unused_vertex < triangulation.vertices.size(),
5161 ExcMessage(
5162 "Internal error: During refinement, the triangulation wants "
5163 "to access an element of the 'vertices' array but it turns "
5164 "out that the array is not large enough."));
5165 triangulation.vertices_used[next_unused_vertex] = true;
5166
5168
5170 cell->center(true, true);
5171 }
5172
5173 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5174 12>
5175 new_lines;
5176 std::array<types::geometric_orientation, 12> inherited_orientations;
5178 unsigned int lmin = 0;
5179 unsigned int lmax = 0;
5180
5181 if (cell->reference_cell() == ReferenceCells::Triangle)
5182 {
5183 lmin = 6;
5184 lmax = 9;
5185 // For triangles, the innermost faces are always reversed for the
5186 // first three children and are in the standard orientation for
5187 // the last one.
5188 std::fill(inherited_orientations.begin() + lmin,
5189 inherited_orientations.begin() + lmax,
5191 }
5192 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5193 {
5194 lmin = 8;
5195 lmax = 12;
5196 }
5197 else
5198 {
5200 }
5201
5202 for (unsigned int l = lmin; l < lmax; ++l)
5203 {
5204 while (next_unused_line->used() == true)
5208
5210 }
5211
5212 // set up lines which have parents:
5213 for (const unsigned int face_no : cell->face_indices())
5214 {
5215 // Check the face (line) orientation to ensure that the (six or
5216 // eight) outer lines in new_lines are indexed in the default
5217 // orientation. This way we can index into this array in the
5218 // without special casing orientations (e.g., quadrilateral child
5219 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5220 const auto combined_orientation =
5221 cell->combined_face_orientation(face_no);
5227 for (unsigned int c = 0; c < 2; ++c)
5228 {
5229 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5231 cell->combined_face_orientation(face_no);
5232 }
5234 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5235 }
5236
5237 // set up lines which do not have parents:
5238 if (cell->reference_cell() == ReferenceCells::Triangle)
5239 {
5240 new_lines[6]->set_bounding_object_indices(
5241 {new_vertices[3], new_vertices[4]});
5242 new_lines[7]->set_bounding_object_indices(
5243 {new_vertices[4], new_vertices[5]});
5244 new_lines[8]->set_bounding_object_indices(
5245 {new_vertices[5], new_vertices[3]});
5246 }
5247 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5248 {
5249 new_lines[8]->set_bounding_object_indices(
5250 {new_vertices[6], new_vertices[8]});
5251 new_lines[9]->set_bounding_object_indices(
5252 {new_vertices[8], new_vertices[7]});
5253 new_lines[10]->set_bounding_object_indices(
5254 {new_vertices[4], new_vertices[8]});
5255 new_lines[11]->set_bounding_object_indices(
5256 {new_vertices[8], new_vertices[5]});
5257 }
5258 else
5259 {
5261 }
5262
5263 for (unsigned int l = lmin; l < lmax; ++l)
5264 {
5265 new_lines[l]->set_used_flag();
5266 new_lines[l]->clear_user_flag();
5267 new_lines[l]->clear_user_data();
5268 new_lines[l]->clear_children();
5269 // new lines are always internal.
5270 new_lines[l]->set_boundary_id_internal(
5272 new_lines[l]->set_manifold_id(cell->manifold_id());
5273 }
5274
5277 while (next_unused_cell->used() == true)
5279
5280 unsigned int n_children = 0;
5281 if (cell->reference_cell() == ReferenceCells::Triangle)
5282 n_children = 4;
5283 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5284 n_children = 4;
5285 else
5287
5288 for (unsigned int i = 0; i < n_children; ++i)
5289 {
5293 if (i % 2 == 1 && i < n_children - 1)
5294 while (next_unused_cell->used() == true)
5296 }
5297
5298 // Assign lines to child cells:
5299 constexpr unsigned int X = numbers::invalid_unsigned_int;
5301 {{{{0, 8, 5, X}}, {{1, 2, 6, X}}, {{7, 3, 4, X}}, {{6, 7, 8, X}}}};
5303 quad_child_lines = {{{{0, 8, 4, 10}},
5304 {{8, 2, 5, 11}},
5305 {{1, 9, 10, 6}},
5306 {{9, 3, 11, 7}}}};
5307 // Here and below we assume that child cells have the same reference
5308 // cell type as the parent.
5309 const auto &child_lines =
5310 cell->reference_cell() == ReferenceCells::Triangle ?
5313 for (unsigned int i = 0; i < n_children; ++i)
5314 {
5315 if (cell->reference_cell() == ReferenceCells::Triangle)
5316 subcells[i]->set_bounding_object_indices(
5317 {new_lines[child_lines[i][0]]->index(),
5318 new_lines[child_lines[i][1]]->index(),
5319 new_lines[child_lines[i][2]]->index()});
5320 else
5321 subcells[i]->set_bounding_object_indices(
5322 {new_lines[child_lines[i][0]]->index(),
5323 new_lines[child_lines[i][1]]->index(),
5324 new_lines[child_lines[i][2]]->index(),
5325 new_lines[child_lines[i][3]]->index()});
5326
5327 subcells[i]->set_used_flag();
5328 subcells[i]->clear_refine_flag();
5329 subcells[i]->clear_user_flag();
5330 subcells[i]->clear_user_data();
5331 subcells[i]->clear_children();
5332 // inherit material properties
5333 subcells[i]->set_material_id(cell->material_id());
5334 subcells[i]->set_manifold_id(cell->manifold_id());
5335 subcells[i]->set_subdomain_id(cell->subdomain_id());
5336
5337 triangulation.levels[subcells[i]->level()]
5338 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5339
5340 // Finally, now that children are marked as used, we can set
5341 // orientation flags:
5342 for (unsigned int face_no : cell->face_indices())
5343 subcells[i]->set_combined_face_orientation(
5345
5346 if (i % 2 == 0)
5347 subcells[i]->set_parent(cell->index());
5348 }
5349
5350 // Unlike the same lines on other children, the innermost triangle's
5351 // faces are all in the default orientation:
5352 if (cell->reference_cell() == ReferenceCells::Triangle)
5353 for (unsigned int face_no : cell->face_indices())
5354 subcells[3]->set_combined_face_orientation(
5356
5357 for (unsigned int i = 0; i < n_children / 2; ++i)
5358 cell->set_children(2 * i, subcells[2 * i]->index());
5359
5360 cell->set_refinement_case(ref_case);
5361
5362 if (dim == spacedim - 1)
5363 for (unsigned int c = 0; c < n_children; ++c)
5364 cell->child(c)->set_direction_flag(cell->direction_flag());
5365 };
5366
5367 for (int level = 0;
5368 level < static_cast<int>(triangulation.levels.size()) - 1;
5369 ++level)
5370 {
5373
5374 for (const auto &cell :
5375 triangulation.active_cell_iterators_on_level(level))
5376 if (cell->refine_flag_set())
5377 {
5382 cell);
5383
5384 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5385 check_for_distorted_cells &&
5387 cells_with_distorted_children.distorted_cells.push_back(
5388 cell);
5389
5390 triangulation.signals.post_refinement_on_cell(cell);
5391 }
5392 }
5393
5395 }
5396
5397
5398
5403 template <int spacedim>
5406 const bool /*check_for_distorted_cells*/)
5407 {
5408 const unsigned int dim = 1;
5409
5410 // Check whether a new level is needed. We have to check for
5411 // this on the highest level only
5412 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5413 triangulation.levels.size() - 1))
5414 if (cell->refine_flag_set())
5415 {
5416 triangulation.levels.push_back(
5417 std::make_unique<
5419 break;
5420 }
5421
5422
5423 // check how much space is needed on every level. We need not
5424 // check the highest level since either - on the highest level
5425 // no cells are flagged for refinement - there are, but
5426 // prepare_refinement added another empty level
5427 unsigned int needed_vertices = 0;
5428 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5429 {
5430 // count number of flagged
5431 // cells on this level
5432 unsigned int flagged_cells = 0;
5433
5434 for (const auto &acell :
5435 triangulation.active_cell_iterators_on_level(level))
5436 if (acell->refine_flag_set())
5437 ++flagged_cells;
5438
5439 // count number of used cells
5440 // on the next higher level
5441 const unsigned int used_cells =
5442 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5443 triangulation.levels[level + 1]->cells.used.end(),
5444 true);
5445
5446 // reserve space for the used_cells cells already existing
5447 // on the next higher level as well as for the
5448 // 2*flagged_cells that will be created on that level
5449 reserve_space(*triangulation.levels[level + 1],
5452 spacedim);
5453 // reserve space for 2*flagged_cells new lines on the next
5454 // higher level
5455 reserve_space(triangulation.levels[level + 1]->cells,
5458 0);
5459
5461 }
5462
5463 // add to needed vertices how many
5464 // vertices are already in use
5465 needed_vertices += std::count(triangulation.vertices_used.begin(),
5466 triangulation.vertices_used.end(),
5467 true);
5468 // if we need more vertices: create them, if not: leave the
5469 // array as is, since shrinking is not really possible because
5470 // some of the vertices at the end may be in use
5471 if (needed_vertices > triangulation.vertices.size())
5472 {
5473 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5474 triangulation.vertices_used.resize(needed_vertices, false);
5475 }
5476
5477
5478 // Do REFINEMENT on every level; exclude highest level as
5479 // above
5480
5481 // index of next unused vertex
5482 unsigned int next_unused_vertex = 0;
5483
5484 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5485 {
5488
5489 for (const auto &cell :
5490 triangulation.active_cell_iterators_on_level(level))
5491 if (cell->refine_flag_set())
5492 {
5493 // clear refinement flag
5494 cell->clear_refine_flag();
5495
5496 // search for next unused
5497 // vertex
5498 while (triangulation.vertices_used[next_unused_vertex] ==
5499 true)
5501 Assert(
5502 next_unused_vertex < triangulation.vertices.size(),
5503 ExcMessage(
5504 "Internal error: During refinement, the triangulation "
5505 "wants to access an element of the 'vertices' array "
5506 "but it turns out that the array is not large enough."));
5507
5508 // Now we always ask the cell itself where to put
5509 // the new point. The cell in turn will query the
5510 // manifold object internally.
5512 cell->center(true);
5513
5514 triangulation.vertices_used[next_unused_vertex] = true;
5515
5516 // search for next two unused cell (++ takes care of
5517 // the end of the vector)
5521 while (next_unused_cell->used() == true)
5524 first_child->set_used_flag();
5525 first_child->clear_user_data();
5529 second_child->set_used_flag();
5530 second_child->clear_user_data();
5531
5532 types::subdomain_id subdomainid = cell->subdomain_id();
5533
5534 // insert first child
5535 cell->set_children(0, first_child->index());
5536 first_child->clear_children();
5537 first_child->set_bounding_object_indices(
5538 {cell->vertex_index(0), next_unused_vertex});
5539 first_child->set_material_id(cell->material_id());
5540 first_child->set_manifold_id(cell->manifold_id());
5541 first_child->set_subdomain_id(subdomainid);
5542 if (dim == spacedim - 1)
5543 first_child->set_direction_flag(cell->direction_flag());
5544
5545 first_child->set_parent(cell->index());
5546
5547 // Set manifold id of the right face. Only do this
5548 // on the first child.
5549 first_child->face(1)->set_manifold_id(cell->manifold_id());
5550
5551 // reset neighborship info (refer to
5552 // internal::TriangulationImplementation::TriaLevel<0> for
5553 // details)
5554 first_child->set_neighbor(1, second_child);
5555 if (cell->neighbor(0).state() != IteratorState::valid)
5556 first_child->set_neighbor(0, cell->neighbor(0));
5557 else if (cell->neighbor(0)->is_active())
5558 {
5559 // since the neighbors level is always <=level,
5560 // if the cell is active, then there are no
5561 // cells to the left which may want to know
5562 // about this new child cell.
5563 Assert(cell->neighbor(0)->level() <= cell->level(),
5565 first_child->set_neighbor(0, cell->neighbor(0));
5566 }
5567 else
5568 // left neighbor is refined
5569 {
5570 // set neighbor to cell on same level
5571 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
5572 first_child->set_neighbor(0,
5573 cell->neighbor(0)->child(nbnb));
5574
5575 // reset neighbor info of all right descendant
5576 // of the left neighbor of cell
5578 left_neighbor = cell->neighbor(0);
5579 while (left_neighbor->has_children())
5580 {
5582 left_neighbor->set_neighbor(nbnb, first_child);
5583 }
5584 }
5585
5586 // insert second child
5587 second_child->clear_children();
5588 second_child->set_bounding_object_indices(
5589 {next_unused_vertex, cell->vertex_index(1)});
5590 second_child->set_neighbor(0, first_child);
5591 second_child->set_material_id(cell->material_id());
5592 second_child->set_manifold_id(cell->manifold_id());
5593 second_child->set_subdomain_id(subdomainid);
5594 if (dim == spacedim - 1)
5595 second_child->set_direction_flag(cell->direction_flag());
5596
5597 if (cell->neighbor(1).state() != IteratorState::valid)
5598 second_child->set_neighbor(1, cell->neighbor(1));
5599 else if (cell->neighbor(1)->is_active())
5600 {
5601 Assert(cell->neighbor(1)->level() <= cell->level(),
5603 second_child->set_neighbor(1, cell->neighbor(1));
5604 }
5605 else
5606 // right neighbor is refined same as above
5607 {
5608 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
5609 second_child->set_neighbor(
5610 1, cell->neighbor(1)->child(nbnb));
5611
5613 right_neighbor = cell->neighbor(1);
5614 while (right_neighbor->has_children())
5615 {
5617 right_neighbor->set_neighbor(nbnb, second_child);
5618 }
5619 }
5620 // inform all listeners that cell refinement is done
5621 triangulation.signals.post_refinement_on_cell(cell);
5622 }
5623 }
5624
5625 // in 1d, we can not have distorted children unless the parent
5626 // was already distorted (that is because we don't use
5627 // boundary information for 1d triangulations). so return an
5628 // empty list
5630 }
5631
5632
5637 template <int spacedim>
5640 const bool check_for_distorted_cells)
5641 {
5642 const unsigned int dim = 2;
5643
5644 // First check whether we can get away with isotropic refinement, or
5645 // whether we need to run through the full anisotropic algorithm
5646 {
5647 bool do_isotropic_refinement = true;
5648 for (const auto &cell : triangulation.active_cell_iterators())
5649 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
5650 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
5651 {
5653 break;
5654 }
5655
5658 check_for_distorted_cells);
5659 }
5660
5661 // If we get here, we are doing anisotropic refinement.
5662
5663 // Check whether a new level is needed. We have to check for
5664 // this on the highest level only
5665 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5666 triangulation.levels.size() - 1))
5667 if (cell->refine_flag_set())
5668 {
5669 triangulation.levels.push_back(
5670 std::make_unique<
5672 break;
5673 }
5674
5675 // TODO[WB]: we clear user flags and pointers of lines; we're going
5676 // to use them to flag which lines need refinement
5678 triangulation.begin_line();
5679 line != triangulation.end_line();
5680 ++line)
5681 {
5682 line->clear_user_flag();
5683 line->clear_user_data();
5684 }
5685 // running over all cells and lines count the number
5686 // n_single_lines of lines which can be stored as single
5687 // lines, e.g. inner lines
5688 unsigned int n_single_lines = 0;
5689
5690 // New lines to be created: number lines which are stored in
5691 // pairs (the children of lines must be stored in pairs)
5692 unsigned int n_lines_in_pairs = 0;
5693
5694 // check how much space is needed on every level. We need not
5695 // check the highest level since either - on the highest level
5696 // no cells are flagged for refinement - there are, but
5697 // prepare_refinement added another empty level
5698 unsigned int needed_vertices = 0;
5699 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5700 {
5701 // count number of flagged cells on this level and compute
5702 // how many new vertices and new lines will be needed
5703 unsigned int needed_cells = 0;
5704
5705 for (const auto &cell :
5706 triangulation.active_cell_iterators_on_level(level))
5707 if (cell->refine_flag_set())
5708 {
5709 if (cell->refine_flag_set() == RefinementCase<dim>::cut_xy)
5710 {
5711 needed_cells += 4;
5712
5713 // new vertex at center of cell is needed in any
5714 // case
5716
5717 // the four inner lines can be stored as singles
5718 n_single_lines += 4;
5719 }
5720 else // cut_x || cut_y
5721 {
5722 // set the flag showing that anisotropic
5723 // refinement is used for at least one cell
5724 triangulation.anisotropic_refinement = true;
5725
5726 needed_cells += 2;
5727 // no vertex at center
5728
5729 // the inner line can be stored as single
5730 n_single_lines += 1;
5731 }
5732
5733 // mark all faces (lines) for refinement; checking
5734 // locally whether the neighbor would also like to
5735 // refine them is rather difficult for lines so we
5736 // only flag them and after visiting all cells, we
5737 // decide which lines need refinement;
5738 for (const unsigned int line_no :
5740 {
5742 cell->refine_flag_set(), line_no) ==
5744 {
5746 line = cell->line(line_no);
5747 if (line->has_children() == false)
5748 line->set_user_flag();
5749 }
5750 }
5751 }
5752
5753
5754 // count number of used cells on the next higher level
5755 const unsigned int used_cells =
5756 std::count(triangulation.levels[level + 1]->cells.used.begin(),
5757 triangulation.levels[level + 1]->cells.used.end(),
5758 true);
5759
5760
5761 // reserve space for the used_cells cells already existing
5762 // on the next higher level as well as for the
5763 // needed_cells that will be created on that level
5764 reserve_space(*triangulation.levels[level + 1],
5766 spacedim);
5767
5768 // reserve space for needed_cells new quads on the next
5769 // higher level
5770 reserve_space(triangulation.levels[level + 1]->cells,
5772 0);
5773 }
5774
5775 // now count the lines which were flagged for refinement
5777 triangulation.begin_line();
5778 line != triangulation.end_line();
5779 ++line)
5780 if (line->user_flag_set())
5781 {
5782 Assert(line->has_children() == false, ExcInternalError());
5783 n_lines_in_pairs += 2;
5784 needed_vertices += 1;
5785 }
5786 // reserve space for n_lines_in_pairs new lines. note, that
5787 // we can't reserve space for the single lines here as well,
5788 // as all the space reserved for lines in pairs would be
5789 // counted as unused and we would end up with too little space
5790 // to store all lines. memory reservation for n_single_lines
5791 // can only be done AFTER we refined the lines of the current
5792 // cells
5794
5795 // add to needed vertices how many vertices are already in use
5796 needed_vertices += std::count(triangulation.vertices_used.begin(),
5797 triangulation.vertices_used.end(),
5798 true);
5799 // if we need more vertices: create them, if not: leave the
5800 // array as is, since shrinking is not really possible because
5801 // some of the vertices at the end may be in use
5802 if (needed_vertices > triangulation.vertices.size())
5803 {
5804 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5805 triangulation.vertices_used.resize(needed_vertices, false);
5806 }
5807
5808
5809 // Do REFINEMENT on every level; exclude highest level as
5810 // above
5811
5812 // index of next unused vertex
5813 unsigned int next_unused_vertex = 0;
5814
5815 // first the refinement of lines. children are stored
5816 // pairwise
5817 {
5818 // only active objects can be refined further
5820 line = triangulation.begin_active_line(),
5821 endl = triangulation.end_line();
5823 next_unused_line = triangulation.begin_raw_line();
5824
5825 for (; line != endl; ++line)
5826 if (line->user_flag_set())
5827 {
5828 // this line needs to be refined
5829
5830 // find the next unused vertex and set it
5831 // appropriately
5832 while (triangulation.vertices_used[next_unused_vertex] == true)
5834 Assert(
5835 next_unused_vertex < triangulation.vertices.size(),
5836 ExcMessage(
5837 "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."));
5838 triangulation.vertices_used[next_unused_vertex] = true;
5839
5840 triangulation.vertices[next_unused_vertex] = line->center(true);
5841
5842 // now that we created the right point, make up the
5843 // two child lines. To this end, find a pair of
5844 // unused lines
5845 [[maybe_unused]] bool pair_found = false;
5847 if (!next_unused_line->used() &&
5848 !(++next_unused_line)->used())
5849 {
5850 // go back to the first of the two unused
5851 // lines
5853 pair_found = true;
5854 break;
5855 }
5857
5858 // there are now two consecutive unused lines, such
5859 // that the children of a line will be consecutive.
5860 // then set the child pointer of the present line
5861 line->set_children(0, next_unused_line->index());
5862
5863 // set the two new lines
5865 children[2] = {next_unused_line, ++next_unused_line};
5866 // some tests; if any of the iterators should be
5867 // invalid, then already dereferencing will fail
5868 AssertIsNotUsed(children[0]);
5869 AssertIsNotUsed(children[1]);
5870
5871 children[0]->set_bounding_object_indices(
5872 {line->vertex_index(0), next_unused_vertex});
5873 children[1]->set_bounding_object_indices(
5874 {next_unused_vertex, line->vertex_index(1)});
5875
5876 children[0]->set_used_flag();
5877 children[1]->set_used_flag();
5878 children[0]->clear_children();
5879 children[1]->clear_children();
5880 children[0]->clear_user_data();
5881 children[1]->clear_user_data();
5882 children[0]->clear_user_flag();
5883 children[1]->clear_user_flag();
5884
5885
5886 children[0]->set_boundary_id_internal(line->boundary_id());
5887 children[1]->set_boundary_id_internal(line->boundary_id());
5888
5889 children[0]->set_manifold_id(line->manifold_id());
5890 children[1]->set_manifold_id(line->manifold_id());
5891
5892 // finally clear flag indicating the need for
5893 // refinement
5894 line->clear_user_flag();
5895 }
5896 }
5897
5898
5899 // Now set up the new cells
5900
5901 // reserve space for inner lines (can be stored as single
5902 // lines)
5903 reserve_space(triangulation.faces->lines, 0, n_single_lines);
5904
5907
5908 // reset next_unused_line, as now also single empty places in
5909 // the vector can be used
5911 next_unused_line = triangulation.begin_raw_line();
5912
5913 for (int level = 0;
5914 level < static_cast<int>(triangulation.levels.size()) - 1;
5915 ++level)
5916 {
5919
5920 for (const auto &cell :
5921 triangulation.active_cell_iterators_on_level(level))
5922 if (cell->refine_flag_set())
5923 {
5924 // actually set up the children and update neighbor
5925 // information
5930 cell);
5931
5932 if (check_for_distorted_cells &&
5934 cells_with_distorted_children.distorted_cells.push_back(
5935 cell);
5936 // inform all listeners that cell refinement is done
5937 triangulation.signals.post_refinement_on_cell(cell);
5938 }
5939 }
5940
5942 }
5943
5944
5945 template <int spacedim>
5948 const bool check_for_distorted_cells)
5949 {
5950 static const int dim = 3;
5951 static const unsigned int X = numbers::invalid_unsigned_int;
5952 using raw_line_iterator =
5954 using raw_quad_iterator =
5956
5957 Assert(spacedim == 3, ExcNotImplemented());
5958
5959 Assert(triangulation.vertices.size() ==
5960 triangulation.vertices_used.size(),
5962
5963 // Check whether a new level is needed. We have to check for
5964 // this on the highest level only
5965 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5966 triangulation.levels.size() - 1))
5967 if (cell->refine_flag_set())
5968 {
5969 triangulation.levels.push_back(
5970 std::make_unique<
5972 break;
5973 }
5974
5975 // first clear user flags for quads and lines; we're going to
5976 // use them to flag which lines and quads need refinement
5977 triangulation.faces->quads.clear_user_data();
5978 triangulation.faces->lines.clear_user_flags();
5979 triangulation.faces->quads.clear_user_flags();
5980
5981 // check how much space is needed on every level. We need not
5982 // check the highest level since either
5983 // - on the highest level no cells are flagged for refinement
5984 // - there are, but prepare_refinement added another empty
5985 // level which then is the highest level
5986
5987 // variables to hold the number of newly to be created
5988 // vertices, lines and quads. as these are stored globally,
5989 // declare them outside the loop over al levels. we need lines
5990 // and quads in pairs for refinement of old ones and lines and
5991 // quads, that can be stored as single ones, as they are newly
5992 // created in the inside of an existing cell
5993 unsigned int needed_vertices = 0;
5994 unsigned int needed_lines_single = 0;
5995 unsigned int needed_quads_single = 0;
5996 unsigned int needed_lines_pair = 0;
5997 unsigned int needed_quads_pair = 0;
5998 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5999 {
6000 unsigned int new_cells = 0;
6001
6002 for (const auto &cell :
6003 triangulation.active_cell_iterators_on_level(level))
6004 if (cell->refine_flag_set())
6005 {
6006 // Only support isotropic refinement
6007 Assert(cell->refine_flag_set() ==
6010
6011 // Now count up how many new cells, faces, edges, and vertices
6012 // we will need to allocate to do this refinement.
6013 new_cells += cell->reference_cell().n_isotropic_children();
6014
6015 if (cell->reference_cell() == ReferenceCells::Hexahedron)
6016 {
6019 needed_quads_single += 12;
6020 }
6021 else if (cell->reference_cell() ==
6023 {
6026 }
6027 else
6028 {
6030 }
6031
6032 // Also check whether we have to refine any of the faces and
6033 // edges that bound this cell. They may of course already be
6034 // refined, so we only *mark* them for refinement by setting
6035 // the user flags
6036 for (const auto face : cell->face_indices())
6037 if (cell->face(face)->n_children() == 0)
6038 cell->face(face)->set_user_flag();
6039 else
6040 Assert(cell->face(face)->n_children() ==
6041 cell->reference_cell()
6042 .face_reference_cell(face)
6043 .n_isotropic_children(),
6045
6046 for (const auto line : cell->line_indices())
6047 if (cell->line(line)->has_children() == false)
6048 cell->line(line)->set_user_flag();
6049 else
6050 Assert(cell->line(line)->n_children() == 2,
6052 }
6053
6054 const unsigned int used_cells =
6055 std::count(triangulation.levels[level + 1]->cells.used.begin(),
6056 triangulation.levels[level + 1]->cells.used.end(),
6057 true);
6058
6059 if (triangulation.all_reference_cells_are_hyper_cube())
6060 reserve_space(*triangulation.levels[level + 1],
6062 spacedim,
6063 false);
6064 else
6065 reserve_space(*triangulation.levels[level + 1],
6067 spacedim,
6068 true);
6069
6070 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
6071 }
6072
6073 // now count the quads and lines which were flagged for
6074 // refinement
6076 triangulation.begin_quad();
6077 quad != triangulation.end_quad();
6078 ++quad)
6079 {
6080 if (quad->user_flag_set() == false)
6081 continue;
6082
6083 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6084 {
6085 needed_quads_pair += 4;
6086 needed_lines_pair += 4;
6087 needed_vertices += 1;
6088 }
6089 else if (quad->reference_cell() == ReferenceCells::Triangle)
6090 {
6091 needed_quads_pair += 4;
6093 }
6094 else
6095 {
6097 }
6098 }
6099
6101 triangulation.begin_line();
6102 line != triangulation.end_line();
6103 ++line)
6104 {
6105 if (line->user_flag_set() == false)
6106 continue;
6107
6108 needed_lines_pair += 2;
6109 needed_vertices += 1;
6110 }
6111
6112 reserve_space(triangulation.faces->lines,
6118 reserve_space(triangulation.faces->quads,
6121
6122
6123 // add to needed vertices how many vertices are already in use
6124 needed_vertices += std::count(triangulation.vertices_used.begin(),
6125 triangulation.vertices_used.end(),
6126 true);
6127
6128 if (needed_vertices > triangulation.vertices.size())
6129 {
6130 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6131 triangulation.vertices_used.resize(needed_vertices, false);
6132 }
6133
6134 //-----------------------------------------
6135 // Before we start with the actual refinement, we do some
6136 // sanity checks if in debug mode. especially, we try to catch
6137 // the notorious problem with lines being twice refined,
6138 // i.e. there are cells adjacent at one line ("around the
6139 // edge", but not at a face), with two cells differing by more
6140 // than one refinement level
6141 //
6142 // this check is very simple to implement here, since we have
6143 // all lines flagged if they shall be refined
6144#ifdef DEBUG
6145 for (const auto &cell : triangulation.active_cell_iterators())
6146 if (!cell->refine_flag_set())
6147 for (unsigned int line_n = 0; line_n < cell->n_lines(); ++line_n)
6148 if (cell->line(line_n)->has_children())
6149 for (unsigned int c = 0; c < 2; ++c)
6150 Assert(cell->line(line_n)->child(c)->user_flag_set() == false,
6152#endif
6153
6154 unsigned int current_vertex = 0;
6155
6156 // helper function - find the next available vertex number and mark it
6157 // as used.
6158 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6159 std::vector<bool> &vertices_used) {
6160 unsigned int next_vertex = current_vertex;
6161 while (next_vertex < vertices_used.size() &&
6162 vertices_used[next_vertex] == true)
6163 ++next_vertex;
6164 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6165 vertices_used[next_vertex] = true;
6166
6167 return next_vertex;
6168 };
6169
6170 // LINES
6171 {
6173 line = triangulation.begin_active_line(),
6174 endl = triangulation.end_line();
6175 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6176
6177 for (; line != endl; ++line)
6178 {
6179 if (line->user_flag_set() == false)
6180 continue;
6181
6183 triangulation.faces->lines.template next_free_pair_object<1>(
6187
6188 // now we found two consecutive unused lines, such
6189 // that the children of a line will be consecutive.
6190 // then set the child pointer of the present line
6191 line->set_children(0, next_unused_line->index());
6192
6193 const std::array<raw_line_iterator, 2> children{
6195
6196 AssertIsNotUsed(children[0]);
6197 AssertIsNotUsed(children[1]);
6198
6201 triangulation.vertices_used);
6202 triangulation.vertices[current_vertex] = line->center(true);
6203
6204 children[0]->set_bounding_object_indices(
6205 {line->vertex_index(0), current_vertex});
6206 children[1]->set_bounding_object_indices(
6207 {current_vertex, line->vertex_index(1)});
6208
6209 const auto manifold_id = line->manifold_id();
6210 const auto boundary_id = line->boundary_id();
6211 for (const auto &child : children)
6212 {
6213 child->set_used_flag();
6214 child->clear_children();
6215 child->clear_user_data();
6216 child->clear_user_flag();
6217 child->set_boundary_id_internal(boundary_id);
6218 child->set_manifold_id(manifold_id);
6219 }
6220
6221 line->clear_user_flag();
6222 }
6223 }
6224
6225 // QUADS
6226 {
6228 quad = triangulation.begin_quad(),
6229 endq = triangulation.end_quad();
6230
6231 for (; quad != endq; ++quad)
6232 {
6233 if (quad->user_flag_set() == false)
6234 continue;
6235
6236 const auto reference_face_type = quad->reference_cell();
6237
6238 // 1) create new lines (property is set later)
6239 // maximum of 4 new lines (4 quadrilateral, 3 triangle)
6240 std::array<raw_line_iterator, 4> new_lines;
6242 {
6243 for (unsigned int l = 0; l < 2; ++l)
6244 {
6245 auto next_unused_line =
6246 triangulation.faces->lines
6248 new_lines[2 * l] = next_unused_line;
6249 new_lines[2 * l + 1] = ++next_unused_line;
6250 }
6251 }
6253 {
6254 for (unsigned int l = 0; l < 3; ++l)
6255 new_lines[l] =
6256 triangulation.faces->lines
6258 }
6259 else
6260 {
6262 }
6263
6264#ifdef DEBUG
6265 for (const unsigned int line : quad->line_indices())
6267#endif
6268
6269 // 2) create new quads (properties are set below). Both triangles
6270 // and quads are divided in four.
6271 std::array<raw_quad_iterator, 4> new_quads;
6272 for (unsigned int q = 0; q < 2; ++q)
6273 {
6274 auto next_unused_quad =
6275 triangulation.faces->quads
6277
6279 new_quads[2 * q + 1] = ++next_unused_quad;
6280
6281 quad->set_children(2 * q, new_quads[2 * q]->index());
6282 }
6283 quad->set_refinement_case(RefinementCase<2>::cut_xy);
6284
6285#ifdef DEBUG
6286 for (const auto &quad : new_quads)
6287 AssertIsNotUsed(quad);
6288#endif
6289
6290 // 3) set vertex indices and set new vertex
6291
6292 // Maximum of 9 vertices per refined quad (9 for Quadrilateral, 6
6293 // for Triangle)
6294 std::array<unsigned int, 9> vertex_indices = {};
6295 unsigned int k = 0;
6296 for (const auto i : quad->vertex_indices())
6297 vertex_indices[k++] = quad->vertex_index(i);
6298
6299 for (const auto i : quad->line_indices())
6300 vertex_indices[k++] = quad->line(i)->child(0)->vertex_index(1);
6301
6303 {
6306 triangulation.vertices_used);
6308
6309 triangulation.vertices[current_vertex] =
6310 quad->center(true, true);
6311 }
6312
6313 // 4) set new lines on quads and their properties
6314 std::array<raw_line_iterator, 12> lines;
6315 unsigned int n_lines = 0;
6316 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6317 for (unsigned int c = 0; c < 2; ++c)
6318 lines[n_lines++] = quad->line(l)->child(
6319 child_line_index(c, quad->line_orientation(l)));
6320
6321 for (unsigned int l = 0; l < quad->n_lines(); ++l)
6322 lines[n_lines++] = new_lines[l];
6323
6324 std::array<int, 12> line_indices;
6325 for (unsigned int i = 0; i < n_lines; ++i)
6326 line_indices[i] = lines[i]->index();
6327
6329 line_vertices_quad{{{{0, 4}},
6330 {{4, 2}},
6331 {{1, 5}},
6332 {{5, 3}},
6333 {{0, 6}},
6334 {{6, 1}},
6335 {{2, 7}},
6336 {{7, 3}},
6337 {{6, 8}},
6338 {{8, 7}},
6339 {{4, 8}},
6340 {{8, 5}}}};
6341
6343 quad_lines_quad{{{{0, 8, 4, 10}},
6344 {{8, 2, 5, 11}},
6345 {{1, 9, 10, 6}},
6346 {{9, 3, 11, 7}}}};
6347
6349 line_vertices_tri{{{{0, 3}},
6350 {{3, 1}},
6351 {{1, 4}},
6352 {{4, 2}},
6353 {{2, 5}},
6354 {{5, 0}},
6355 {{3, 4}},
6356 {{4, 5}},
6357 {{3, 5}},
6358 {{X, X}},
6359 {{X, X}},
6360 {{X, X}}}};
6361
6363 quad_lines_tri{{{{0, 8, 5, X}},
6364 {{1, 2, 6, X}},
6365 {{7, 3, 4, X}},
6366 {{6, 7, 8, X}}}};
6367
6370 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6371 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6372 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6373 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6374
6375 const auto &line_vertices =
6379 const auto &quad_lines =
6383
6384 for (unsigned int i = 0, j = 2 * quad->n_lines();
6385 i < quad->n_lines();
6386 ++i, ++j)
6387 {
6388 auto &new_line = new_lines[i];
6389 new_line->set_bounding_object_indices(
6390 {vertex_indices[line_vertices[j][0]],
6391 vertex_indices[line_vertices[j][1]]});
6392 new_line->set_used_flag();
6393 new_line->clear_user_flag();
6394 new_line->clear_user_data();
6395 new_line->clear_children();
6396 new_line->set_boundary_id_internal(quad->boundary_id());
6397 new_line->set_manifold_id(quad->manifold_id());
6398 }
6399
6400 // 5) set properties of quads
6401 for (unsigned int i = 0; i < new_quads.size(); ++i)
6402 {
6403 auto &new_quad = new_quads[i];
6404
6405 // TODO: we assume here that all children have the same type
6406 // as the parent
6407 triangulation.faces->set_quad_type(new_quad->index(),
6409
6411 new_quad->set_bounding_object_indices(
6412 {line_indices[quad_lines[i][0]],
6413 line_indices[quad_lines[i][1]],
6414 line_indices[quad_lines[i][2]]});
6416 new_quad->set_bounding_object_indices(
6417 {line_indices[quad_lines[i][0]],
6418 line_indices[quad_lines[i][1]],
6419 line_indices[quad_lines[i][2]],
6420 line_indices[quad_lines[i][3]]});
6421 else
6423
6424 new_quad->set_used_flag();
6425 new_quad->clear_user_flag();
6426 new_quad->clear_user_data();
6427 new_quad->clear_children();
6428 new_quad->set_boundary_id_internal(quad->boundary_id());
6429 new_quad->set_manifold_id(quad->manifold_id());
6430
6431#ifdef DEBUG
6432 std::set<unsigned int> s;
6433#endif
6434
6435 // ... and fix orientation of lines of face for triangles,
6436 // using an expensive algorithm, quadrilaterals are treated
6437 // a few lines below by a cheaper algorithm
6439 {
6440 for (const auto f : new_quad->line_indices())
6441 {
6442 const std::array<unsigned int, 2> vertices_0 = {
6443 {lines[quad_lines[i][f]]->vertex_index(0),
6444 lines[quad_lines[i][f]]->vertex_index(1)}};
6445
6446 const std::array<unsigned int, 2> vertices_1 = {
6449
6450 const auto orientation =
6451 ReferenceCells::Line.get_combined_orientation(
6452 make_array_view(vertices_0),
6453 make_array_view(vertices_1));
6454
6455#ifdef DEBUG
6456 for (const auto i : vertices_0)
6457 s.insert(i);
6458 for (const auto i : vertices_1)
6459 s.insert(i);
6460#endif
6461
6462 new_quad->set_line_orientation(f, orientation);
6463 }
6464#ifdef DEBUG
6465 AssertDimension(s.size(), 3);
6466#endif
6467 }
6468 }
6469
6470 // fix orientation of lines of faces for quadrilaterals with
6471 // cheap algorithm
6473 {
6476 {{{0, 2}}, {{1, 3}}, {{0, 1}}, {{2, 3}}}};
6477
6478 for (unsigned int i = 0; i < 4; ++i)
6479 for (unsigned int j = 0; j < 2; ++j)
6481 ->set_line_orientation(i, quad->line_orientation(i));
6482 }
6483
6484 quad->clear_user_flag();
6485 }
6486 }
6487
6490
6492 triangulation.begin_active_hex(0);
6493 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
6494 ++level)
6495 {
6497 next_unused_hex = triangulation.begin_raw_hex(level + 1);
6498 Assert(hex == triangulation.end() ||
6499 hex->level() >= static_cast<int>(level),
6501
6502 for (; hex != triangulation.end() &&
6503 hex->level() == static_cast<int>(level);
6504 ++hex)
6505 {
6506 if (hex->refine_flag_set() ==
6508 continue;
6509
6510 const auto &reference_cell_type = hex->reference_cell();
6511
6512 const RefinementCase<dim> ref_case = hex->refine_flag_set();
6513 hex->clear_refine_flag();
6514 hex->set_refinement_case(ref_case);
6515
6516 unsigned int n_new_lines = 0;
6517 unsigned int n_new_quads = 0;
6518 unsigned int n_new_hexes = 0;
6519
6521 {
6522 n_new_lines = 6;
6523 n_new_quads = 12;
6524 n_new_hexes = 8;
6525 }
6527 {
6528 n_new_lines = 1;
6529 n_new_quads = 8;
6530 n_new_hexes = 8;
6531 }
6532 else
6534
6535 std::array<raw_line_iterator, 6> new_lines;
6536 for (unsigned int i = 0; i < n_new_lines; ++i)
6537 {
6538 new_lines[i] =
6539 triangulation.faces->lines
6541
6543 new_lines[i]->set_used_flag();
6544 new_lines[i]->clear_user_flag();
6545 new_lines[i]->clear_user_data();
6546 new_lines[i]->clear_children();
6547 new_lines[i]->set_boundary_id_internal(
6549 new_lines[i]->set_manifold_id(hex->manifold_id());
6550 }
6551
6552 std::array<raw_quad_iterator, 12> new_quads;
6553 for (unsigned int i = 0; i < n_new_quads; ++i)
6554 {
6555 new_quads[i] =
6556 triangulation.faces->quads
6558
6559 auto &new_quad = new_quads[i];
6560
6561 // TODO: faces of children have the same type as the faces
6562 // of the parent
6563 triangulation.faces->set_quad_type(
6564 new_quad->index(),
6565 reference_cell_type.face_reference_cell(0));
6566
6568 new_quad->set_used_flag();
6569 new_quad->clear_user_flag();
6570 new_quad->clear_user_data();
6571 new_quad->clear_children();
6572 new_quad->set_boundary_id_internal(
6574 new_quad->set_manifold_id(hex->manifold_id());
6575 for (const auto j : new_quads[i]->line_indices())
6576 new_quad->set_line_orientation(
6578 }
6579
6580 // we always get 8 children per refined cell
6581 std::array<
6583 8>
6584 new_hexes;
6585 {
6586 for (unsigned int i = 0; i < n_new_hexes; ++i)
6587 {
6588 if (i % 2 == 0)
6590 triangulation.levels[level + 1]->cells.next_free_hex(
6591 triangulation, level + 1);
6592 else
6594
6596
6597 auto &new_hex = new_hexes[i];
6598
6599 // children have the same type as the parent
6600 triangulation.levels[new_hex->level()]
6601 ->reference_cell[new_hex->index()] =
6603
6605 new_hex->set_used_flag();
6606 new_hex->clear_user_flag();
6607 new_hex->clear_user_data();
6608 new_hex->clear_children();
6609 new_hex->set_material_id(hex->material_id());
6610 new_hex->set_manifold_id(hex->manifold_id());
6611 new_hex->set_subdomain_id(hex->subdomain_id());
6612
6613 if (i % 2)
6614 new_hex->set_parent(hex->index());
6615
6616 // set the orientation flag to its default state for all
6617 // faces initially. later on go the other way round and
6618 // reset faces that are at the boundary of the mother cube
6619 for (const auto f : new_hex->face_indices())
6620 new_hex->set_combined_face_orientation(
6622 }
6623 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
6624 hex->set_children(2 * i, new_hexes[2 * i]->index());
6625 }
6626
6627 {
6628 // load vertex indices
6629 std::array<unsigned int, 27> vertex_indices = {};
6630
6631 {
6632 unsigned int k = 0;
6633
6634 // avoid a compiler warning by fixing the max number of
6635 // loop iterations to 8
6636 const unsigned int n_vertices =
6637 std::min(hex->n_vertices(), 8u);
6638 for (unsigned int i = 0; i < n_vertices; ++i)
6639 vertex_indices[k++] = hex->vertex_index(i);
6640
6641 const std::array<unsigned int, 12> line_indices =
6642 TriaAccessorImplementation::Implementation::
6643 get_line_indices_of_cell(*hex);
6644
6645 // For the tetrahedron the parent consists of the vertices
6646 // 0,1,2,3, the new vertices 4-9 are defined as the
6647 // midpoints of the edges: 4 -> (0,1), 5 -> (1,2), 6 ->
6648 // (2,0), 7 -> (0,3), 8 -> (1,3), 9 -> (2,3).
6649 // Order is defined by the reference cell, see
6650 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
6651
6652 // Avoid a compiler warning by fixing the max number of loop
6653 // iterations to 12
6654 const unsigned int n_lines = std::min(hex->n_lines(), 12u);
6655 for (unsigned int l = 0; l < n_lines; ++l)
6656 {
6657 raw_line_iterator line(&triangulation,
6658 0,
6659 line_indices[l]);
6660 vertex_indices[k++] = line->child(0)->vertex_index(1);
6661 }
6662
6664 {
6665 for (const unsigned int i : hex->face_indices())
6666 vertex_indices[k++] =
6667 hex->face(i)->child(0)->vertex_index(3);
6668
6669 // Set single new vertex in the center
6672 triangulation.vertices_used);
6674
6675 triangulation.vertices[current_vertex] =
6676 hex->center(true, true);
6677 }
6678 }
6679
6680 unsigned int chosen_line_tetrahedron = 0;
6681 // set up new lines
6683 {
6685 new_line_vertices = {{{{22, 26}},
6686 {{26, 23}},
6687 {{20, 26}},
6688 {{26, 21}},
6689 {{24, 26}},
6690 {{26, 25}}}};
6691 for (unsigned int i = 0; i < n_new_lines; ++i)
6692 new_lines[i]->set_bounding_object_indices(
6695 }
6697 {
6698 // in the tetrahedron case, we have the three
6699 // possibilities (6,8), (5,7), (4,9) -> pick the
6700 // shortest line to guarantee the best possible aspect
6701 // ratios
6702 static constexpr ::ndarray<unsigned int, 3, 2>
6703 new_line_vertices = {{{{6, 8}}, {{5, 7}}, {{4, 9}}}};
6704
6705 // choose line to cut either by refinement case or by
6706 // shortest distance between edge midpoints
6707 std::uint8_t refinement_choice = hex->refine_choice();
6708 if (refinement_choice ==
6709 static_cast<char>(
6711 {
6712 const auto &vertices = triangulation.get_vertices();
6713 double min_distance =
6714 std::numeric_limits<double>::infinity();
6715 for (unsigned int i = 0; i < new_line_vertices.size();
6716 ++i)
6717 {
6718 const double current_distance =
6719 vertices
6721 .distance(
6722 vertices[vertex_indices
6723 [new_line_vertices[i][1]]]);
6725 {
6728 }
6729 }
6730 }
6731 else if (refinement_choice ==
6732 static_cast<char>(
6735 else if (refinement_choice ==
6736 static_cast<char>(
6739 else if (refinement_choice ==
6740 static_cast<char>(
6743 else
6745
6746 hex->set_refinement_case(
6748
6749 new_lines[0]->set_bounding_object_indices(
6754 }
6755
6756 // set up new quads
6757 {
6758 boost::container::small_vector<raw_line_iterator, 30>
6760
6762 {
6763 relevant_lines.resize(30);
6764 for (unsigned int f = 0, k = 0; f < 6; ++f)
6765 for (unsigned int c = 0; c < 4; ++c, ++k)
6766 {
6767 static constexpr ::
6769 temp = {
6770 {{{0, 1}}, {{3, 0}}, {{0, 3}}, {{3, 2}}}};
6771
6772 relevant_lines[k] =
6773 hex->face(f)
6774 ->isotropic_child(
6776 standard_to_real_face_vertex(
6777 temp[c][0],
6778 hex->face_orientation(f),
6779 hex->face_flip(f),
6780 hex->face_rotation(f)))
6781 ->line(GeometryInfo<dim>::
6782 standard_to_real_face_line(
6783 temp[c][1],
6784 hex->face_orientation(f),
6785 hex->face_flip(f),
6786 hex->face_rotation(f)));
6787 }
6788
6789 for (unsigned int i = 0, k = 24; i < 6; ++i, ++k)
6791 }
6793 {
6794 // The order of the lines is defined by the ordering
6795 // of the faces of the reference cell and the ordering
6796 // of the lines within a face.
6797 // Each face is split into 4 child triangles, the
6798 // relevant lines are defined by the vertices of the
6799 // center triangles: 0 -> (4,5), 1 -> (5,6), 2 -> (4,6),
6800 // 3 -> (4,7), 4 -> (7,8), 5 -> (4,8), 6 -> (6,9), 7 ->
6801 // (9,7), 8 -> (6,7), 9 -> (5,8), 10 -> (8,9), 11 ->
6802 // (5,9), Line 12 is determined by
6803 // chosen_line_tetrahedron i.e. (6,8), (5,7) or (4,9)
6804
6805 relevant_lines.resize(13);
6806
6807 unsigned int k = 0;
6808 for (unsigned int f = 0; f < 4; ++f)
6809 for (unsigned int l = 0; l < 3; ++l, ++k)
6810 {
6811 // TODO: add comment
6812 static const std::
6813 array<std::array<unsigned int, 3>, 6>
6814 table = {{{{1, 0, 2}}, // 0
6815 {{0, 1, 2}},
6816 {{0, 2, 1}}, // 2
6817 {{1, 2, 0}},
6818 {{2, 1, 0}}, // 4
6819 {{2, 0, 1}}}};
6820
6821 const auto combined_orientation =
6822 hex->combined_face_orientation(f);
6823 relevant_lines[k] =
6824 hex->face(f)
6825 ->child(3 /*center triangle*/)
6826 ->line(table[combined_orientation][l]);
6827 }
6828
6829 relevant_lines[k++] = new_lines[0];
6830 AssertDimension(k, 13);
6831 }
6832 else
6834
6835 boost::container::small_vector<unsigned int, 30>
6837 for (unsigned int i = 0; i < relevant_line_indices.size();
6838 ++i)
6840
6841 // It is easierst to start at table cell_vertices,
6842 // there the vertices are listed which build up the
6843 // 8 child tets. To build the child tets, 8 new faces are
6844 // needed. The the vertices, which define the lines of these
6845 // new faces are listed in table_tet. Now only the
6846 // corresponding index of the lines and quads have to be
6847 // listed in new_quad_lines_tet and cell_quads_tet.
6848 const auto &new_quad_lines =
6849 hex->reference_cell().new_isotropic_child_face_lines(
6851
6852 // The first 4 define the faces which cut off the
6853 // parent tetrahedron at the edges. the numbers are the
6854 // index of the relevant_lines defined above the last 4
6855 // faces cut apart the remaining octahedron, such that all
6856 // of these contain line number 12. the ordering of the
6857 // faces is arbitrary, the ordering within the faces has to
6858 // follow the righthand convention for triangles
6859 // The table defines the vertices of the lines above
6860 // see relevant_lines for mapping between line indices and
6861 // vertex numbering
6862 const auto &table =
6863 hex->reference_cell()
6864 .new_isotropic_child_face_line_vertices(
6866
6869 {{{0, 2}}, {{2, 0}}, {{3, 3}}, {{1, 1}}}};
6870
6871 for (unsigned int q = 0; q < n_new_quads; ++q)
6872 {
6873 auto &new_quad = new_quads[q];
6874
6875 if (new_quad->n_lines() == 3)
6876 new_quad->set_bounding_object_indices(
6880 else if (new_quad->n_lines() == 4)
6881 new_quad->set_bounding_object_indices(
6886 else
6888
6889 // On hexes, we must only determine a single line
6890 // according to the representative_lines array above
6891 // (this saves expensive operations), for tets we do
6892 // all lines manually
6893 const unsigned int n_compute_lines =
6895 1 :
6896 new_quad->n_lines();
6897 for (unsigned int line = 0; line < n_compute_lines;
6898 ++line)
6899 {
6900 const unsigned int l =
6903 representative_lines[q % 4][0] :
6904 line;
6905
6906 const std::array<unsigned int, 2> vertices_0 = {
6908 ->vertex_index(0),
6910 ->vertex_index(1)}};
6911
6912 const std::array<unsigned int, 2> vertices_1 = {
6913 {vertex_indices[table[q][l][0]],
6914 vertex_indices[table[q][l][1]]}};
6915
6916 const auto orientation =
6917 ReferenceCells::Line.get_combined_orientation(
6918 make_array_view(vertices_0),
6919 make_array_view(vertices_1));
6920
6921 new_quad->set_line_orientation(l, orientation);
6922
6923 // on a hex, inject the status of the current line
6924 // also to the line on the other quad along the
6925 // same direction
6926 if (reference_cell_type ==
6928 new_quads[representative_lines[q % 4][1] + q -
6929 (q % 4)]
6930 ->set_line_orientation(l, orientation);
6931 }
6932 }
6933 }
6934
6935 // set up new hex
6936 {
6937 std::array<int, 36> quad_indices;
6938
6940 {
6941 for (unsigned int i = 0; i < n_new_quads; ++i)
6942 quad_indices[i] = new_quads[i]->index();
6943
6944 for (unsigned int f = 0, k = n_new_quads; f < 6; ++f)
6945 for (unsigned int c = 0; c < 4; ++c, ++k)
6946 quad_indices[k] =
6947 hex->face(f)->isotropic_child_index(
6949 c,
6950 hex->face_orientation(f),
6951 hex->face_flip(f),
6952 hex->face_rotation(f)));
6953 }
6955 {
6956 // list of the indices of the surfaces which define the
6957 // 8 new tets. the indices 0-7 are the new quads defined
6958 // above (so 0-3 cut off the corners and 4-7 separate
6959 // the remaining octahedral), the indices between 8-11
6960 // are the children of the first face, from 12-15 of the
6961 // second, etc.
6962 for (unsigned int i = 0; i < n_new_quads; ++i)
6963 quad_indices[i] = new_quads[i]->index();
6964
6965 for (unsigned int f = 0, k = n_new_quads; f < 4; ++f)
6966 for (unsigned int c = 0; c < 4; ++c, ++k)
6967 {
6968 const auto combined_orientation =
6969 hex->combined_face_orientation(f);
6970 quad_indices[k] = hex->face(f)->child_index(
6971 (c == 3) ? 3 :
6973 .standard_to_real_face_vertex(
6974 c, f, combined_orientation));
6975 }
6976 }
6977 else
6978 {
6980 }
6981
6982 // indices of the faces which define the new tets
6983 // the ordering of the tets is arbitrary
6984 // the first 4 determine the tets cutting of the corners
6985 // the last 4 are ordered after their appearance in the
6986 // faces.
6987 // the ordering within the faces is determined by
6988 // convention for the tetrahedron unit cell, see
6989 // cell_vertices_tet below
6990 const auto &cell_quads =
6991 hex->reference_cell().new_isotropic_child_cell_faces(
6993
6994 for (unsigned int c = 0;
6996 ++c)
6997 {
6998 auto &new_hex = new_hexes[c];
6999
7000 if (new_hex->n_faces() == 4)
7001 {
7002 new_hex->set_bounding_object_indices(
7003 {quad_indices[cell_quads[c][0]],
7004 quad_indices[cell_quads[c][1]],
7005 quad_indices[cell_quads[c][2]],
7006 quad_indices[cell_quads[c][3]]});
7007
7008
7009 // for tets, we need to go through the faces and
7010 // figure the orientation out the hard way
7011 for (const auto f : new_hex->face_indices())
7012 {
7013 const auto &face = new_hex->face(f);
7014
7015 Assert(face->n_vertices() == 3,
7017
7018 const std::array<unsigned int, 3> vertices_0 = {
7019 {face->vertex_index(0),
7020 face->vertex_index(1),
7021 face->vertex_index(2)}};
7022
7023 // the 8 child tets are each defined by 4
7024 // vertices the ordering of the tets has to be
7025 // consistent with above the ordering within the
7026 // tets is given by the reference tet i.e.
7027 // looking at the fifth line the first 3
7028 // vertices are given by face 11, the last
7029 // vertex is the remaining of the tet
7030 const auto new_hex_vertices =
7031 hex->reference_cell()
7032 .new_isotropic_child_cell_vertices(
7034
7035 // arrange after vertices of the faces of the
7036 // unit cell
7037 const std::array<unsigned int, 3> vertices_1 = {
7038 {
7042 .face_to_cell_vertices(f, 0, 1)]],
7046 .face_to_cell_vertices(f, 1, 1)]],
7050 .face_to_cell_vertices(f, 2, 1)]],
7051 }};
7052
7053 new_hex->set_combined_face_orientation(
7054 f,
7055 face->reference_cell()
7056 .get_combined_orientation(
7057 make_array_view(vertices_1),
7058 make_array_view(vertices_0)));
7059 }
7060 }
7061 else if (new_hex->n_faces() == 6)
7062 new_hex->set_bounding_object_indices(
7063 {quad_indices[cell_quads[c][0]],
7064 quad_indices[cell_quads[c][1]],
7065 quad_indices[cell_quads[c][2]],
7066 quad_indices[cell_quads[c][3]],
7067 quad_indices[cell_quads[c][4]],
7068 quad_indices[cell_quads[c][5]]});
7069 else
7071 }
7072
7073 // for hexes, we can simply inherit the orientation values
7074 // from the parent on the outer faces; the inner faces can
7075 // be skipped as their orientation is always the default
7076 // one set above
7078 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7079 {{1, 3, 5, 7}},
7080 {{0, 1, 4, 5}},
7081 {{2, 3, 6, 7}},
7082 {{0, 1, 2, 3}},
7083 {{4, 5, 6, 7}}}};
7084 if (hex->n_faces() == 6)
7085 for (const auto f : hex->face_indices())
7086 {
7087 const auto combined_orientation =
7088 hex->combined_face_orientation(f);
7089 for (unsigned int c = 0; c < 4; ++c)
7091 ->set_combined_face_orientation(
7093 }
7094 }
7095 }
7096
7097 if (check_for_distorted_cells &&
7099 cells_with_distorted_children.distorted_cells.push_back(hex);
7100
7101 triangulation.signals.post_refinement_on_cell(hex);
7102 }
7103 }
7104
7105 triangulation.faces->quads.clear_user_data();
7106
7108 }
7109
7114 template <int spacedim>
7117 const bool check_for_distorted_cells)
7118 {
7119 const unsigned int dim = 3;
7120
7121 {
7122 bool flag_isotropic_mesh = true;
7124 cell = triangulation.begin(),
7125 endc = triangulation.end();
7126 for (; cell != endc; ++cell)
7127 if (cell->used())
7128 if (triangulation.get_anisotropic_refinement_flag() ||
7129 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7130 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7131 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7132 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7133 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7134 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7135 {
7136 flag_isotropic_mesh = false;
7137 break;
7138 }
7139
7142 check_for_distorted_cells);
7143 }
7144
7145 // this function probably also works for spacedim>3 but it
7146 // isn't tested. it will probably be necessary to pull new
7147 // vertices onto the manifold just as we do for the other
7148 // functions above.
7149 Assert(spacedim == 3, ExcNotImplemented());
7150
7151 // Check whether a new level is needed. We have to check for
7152 // this on the highest level only
7153 for (const auto &cell : triangulation.active_cell_iterators_on_level(
7154 triangulation.levels.size() - 1))
7155 if (cell->refine_flag_set())
7156 {
7157 triangulation.levels.push_back(
7158 std::make_unique<
7160 break;
7161 }
7162
7163
7164 // first clear user flags for quads and lines; we're going to
7165 // use them to flag which lines and quads need refinement
7166 triangulation.faces->quads.clear_user_data();
7167
7169 triangulation.begin_line();
7170 line != triangulation.end_line();
7171 ++line)
7172 line->clear_user_flag();
7174 triangulation.begin_quad();
7175 quad != triangulation.end_quad();
7176 ++quad)
7177 quad->clear_user_flag();
7178
7179 // create an array of face refine cases. User indices of faces
7180 // will be set to values corresponding with indices in this
7181 // array.
7182 const RefinementCase<dim - 1> face_refinement_cases[4] = {
7183 RefinementCase<dim - 1>::no_refinement,
7184 RefinementCase<dim - 1>::cut_x,
7185 RefinementCase<dim - 1>::cut_y,
7186 RefinementCase<dim - 1>::cut_xy};
7187
7188 // check how much space is needed on every level. We need not
7189 // check the highest level since either
7190 // - on the highest level no cells are flagged for refinement
7191 // - there are, but prepare_refinement added another empty
7192 // level which then is the highest level
7193
7194 // variables to hold the number of newly to be created
7195 // vertices, lines and quads. as these are stored globally,
7196 // declare them outside the loop over al levels. we need lines
7197 // and quads in pairs for refinement of old ones and lines and
7198 // quads, that can be stored as single ones, as they are newly
7199 // created in the inside of an existing cell
7200 unsigned int needed_vertices = 0;
7201 unsigned int needed_lines_single = 0;
7202 unsigned int needed_quads_single = 0;
7203 unsigned int needed_lines_pair = 0;
7204 unsigned int needed_quads_pair = 0;
7205 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
7206 {
7207 // count number of flagged cells on this level and compute
7208 // how many new vertices and new lines will be needed
7209 unsigned int new_cells = 0;
7210
7211 for (const auto &acell :
7212 triangulation.active_cell_iterators_on_level(level))
7213 if (acell->refine_flag_set())
7214 {
7215 RefinementCase<dim> ref_case = acell->refine_flag_set();
7216
7217 // now for interior vertices, lines and quads, which
7218 // are needed in any case
7222 {
7224 new_cells += 2;
7225 triangulation.anisotropic_refinement = true;
7226 }
7230 {
7233 new_cells += 4;
7234 triangulation.anisotropic_refinement = true;
7235 }
7237 {
7240 needed_quads_single += 12;
7241 new_cells += 8;
7242 }
7243 else
7244 {
7245 // we should never get here
7247 }
7248
7249 // mark all faces for refinement; checking locally
7250 // if and how the neighbor would like to refine
7251 // these is difficult so we only flag them and after
7252 // visiting all cells, we decide which faces need
7253 // which refinement;
7254 for (const unsigned int face :
7256 {
7258 aface = acell->face(face);
7259 // get the RefineCase this faces has for the
7260 // given RefineCase of the cell
7261 RefinementCase<dim - 1> face_ref_case =
7263 ref_case,
7264 face,
7265 acell->face_orientation(face),
7266 acell->face_flip(face),
7267 acell->face_rotation(face));
7268 // only do something, if this face has to be
7269 // refined
7270 if (face_ref_case)
7271 {
7272 if (face_ref_case ==
7274 {
7275 if (aface->n_active_descendants() < 4)
7276 // we use user_flags to denote needed
7277 // isotropic refinement
7278 aface->set_user_flag();
7279 }
7280 else if (aface->refinement_case() != face_ref_case)
7281 // we use user_indices to denote needed
7282 // anisotropic refinement. note, that we
7283 // can have at most one anisotropic
7284 // refinement case for this face, as
7285 // otherwise prepare_refinement() would
7286 // have changed one of the cells to yield
7287 // isotropic refinement at this
7288 // face. therefore we set the user_index
7289 // uniquely
7290 {
7291 Assert(aface->refinement_case() ==
7293 dim - 1>::isotropic_refinement ||
7294 aface->refinement_case() ==
7297 aface->set_user_index(face_ref_case);
7298 }
7299 }
7300 } // for all faces
7301
7302 // flag all lines, that have to be refined
7303 for (unsigned int line = 0;
7305 ++line)
7307 line) &&
7308 !acell->line(line)->has_children())
7309 acell->line(line)->set_user_flag();
7310
7311 } // if refine_flag set and for all cells on this level
7312
7313
7314 // count number of used cells on the next higher level
7315 const unsigned int used_cells =
7316 std::count(triangulation.levels[level + 1]->cells.used.begin(),
7317 triangulation.levels[level + 1]->cells.used.end(),
7318 true);
7319
7320
7321 // reserve space for the used_cells cells already existing
7322 // on the next higher level as well as for the
7323 // 8*flagged_cells that will be created on that level
7324 reserve_space(*triangulation.levels[level + 1],
7326 spacedim);
7327 // reserve space for 8*flagged_cells new hexes on the next
7328 // higher level
7329 reserve_space(triangulation.levels[level + 1]->cells, new_cells);
7330 } // for all levels
7331 // now count the quads and lines which were flagged for
7332 // refinement
7334 triangulation.begin_quad();
7335 quad != triangulation.end_quad();
7336 ++quad)
7337 {
7338 if (quad->user_flag_set())
7339 {
7340 // isotropic refinement: 1 interior vertex, 4 quads
7341 // and 4 interior lines. we store the interior lines
7342 // in pairs in case the face is already or will be
7343 // refined anisotropically
7344 needed_quads_pair += 4;
7345 needed_lines_pair += 4;
7346 needed_vertices += 1;
7347 }
7348 if (quad->user_index())
7349 {
7350 // anisotropic refinement: 1 interior
7351 // line and two quads
7352 needed_quads_pair += 2;
7354 // there is a kind of complicated situation here which
7355 // requires our attention. if the quad is refined
7356 // isotropcally, two of the interior lines will get a
7357 // new mother line - the interior line of our
7358 // anisotropically refined quad. if those two lines
7359 // are not consecutive, we cannot do so and have to
7360 // replace them by two lines that are consecutive. we
7361 // try to avoid that situation, but it may happen
7362 // nevertheless through repeated refinement and
7363 // coarsening. thus we have to check here, as we will
7364 // need some additional space to store those new lines
7365 // in case we need them...
7366 if (quad->has_children())
7367 {
7368 Assert(quad->refinement_case() ==
7371 if ((face_refinement_cases[quad->user_index()] ==
7373 (quad->child(0)->line_index(1) + 1 !=
7374 quad->child(2)->line_index(1))) ||
7375 (face_refinement_cases[quad->user_index()] ==
7377 (quad->child(0)->line_index(3) + 1 !=
7378 quad->child(1)->line_index(3))))
7379 needed_lines_pair += 2;
7380 }
7381 }
7382 }
7383
7385 triangulation.begin_line();
7386 line != triangulation.end_line();
7387 ++line)
7388 if (line->user_flag_set())
7389 {
7390 needed_lines_pair += 2;
7391 needed_vertices += 1;
7392 }
7393
7394 // reserve space for needed_lines new lines stored in pairs
7395 reserve_space(triangulation.faces->lines,
7398 // reserve space for needed_quads new quads stored in pairs
7402 reserve_space(triangulation.faces->quads,
7405
7406
7407 // add to needed vertices how many vertices are already in use
7408 needed_vertices += std::count(triangulation.vertices_used.begin(),
7409 triangulation.vertices_used.end(),
7410 true);
7411 // if we need more vertices: create them, if not: leave the
7412 // array as is, since shrinking is not really possible because
7413 // some of the vertices at the end may be in use
7414 if (needed_vertices > triangulation.vertices.size())
7415 {
7416 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
7417 triangulation.vertices_used.resize(needed_vertices, false);
7418 }
7419
7420
7421 //-----------------------------------------
7422 // Before we start with the actual refinement, we do some
7423 // sanity checks if in debug mode. especially, we try to catch
7424 // the notorious problem with lines being twice refined,
7425 // i.e. there are cells adjacent at one line ("around the
7426 // edge", but not at a face), with two cells differing by more
7427 // than one refinement level
7428 //
7429 // this check is very simple to implement here, since we have
7430 // all lines flagged if they shall be refined
7431#ifdef DEBUG
7432 for (const auto &cell : triangulation.active_cell_iterators())
7433 if (!cell->refine_flag_set())
7434 for (unsigned int line = 0;
7436 ++line)
7437 if (cell->line(line)->has_children())
7438 for (unsigned int c = 0; c < 2; ++c)
7439 Assert(cell->line(line)->child(c)->user_flag_set() == false,
7441#endif
7442
7443 //-----------------------------------------
7444 // Do refinement on every level
7445 //
7446 // To make life a bit easier, we first refine those lines and
7447 // quads that were flagged for refinement and then compose the
7448 // newly to be created cells.
7449 //
7450 // index of next unused vertex
7451 unsigned int next_unused_vertex = 0;
7452
7453 // first for lines
7454 {
7455 // only active objects can be refined further
7457 line = triangulation.begin_active_line(),
7458 endl = triangulation.end_line();
7460 next_unused_line = triangulation.begin_raw_line();
7461
7462 for (; line != endl; ++line)
7463 if (line->user_flag_set())
7464 {
7465 // this line needs to be refined
7466
7467 // find the next unused vertex and set it
7468 // appropriately
7469 while (triangulation.vertices_used[next_unused_vertex] == true)
7471 Assert(
7472 next_unused_vertex < triangulation.vertices.size(),
7473 ExcMessage(
7474 "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."));
7475 triangulation.vertices_used[next_unused_vertex] = true;
7476
7477 triangulation.vertices[next_unused_vertex] = line->center(true);
7478
7479 // now that we created the right point, make up the
7480 // two child lines (++ takes care of the end of the
7481 // vector)
7483 triangulation.faces->lines.template next_free_pair_object<1>(
7487
7488 // now we found two consecutive unused lines, such
7489 // that the children of a line will be consecutive.
7490 // then set the child pointer of the present line
7491 line->set_children(0, next_unused_line->index());
7492
7493 // set the two new lines
7495 children[2] = {next_unused_line, ++next_unused_line};
7496
7497 // some tests; if any of the iterators should be
7498 // invalid, then already dereferencing will fail
7499 AssertIsNotUsed(children[0]);
7500 AssertIsNotUsed(children[1]);
7501
7502 children[0]->set_bounding_object_indices(
7503 {line->vertex_index(0), next_unused_vertex});
7504 children[1]->set_bounding_object_indices(
7505 {next_unused_vertex, line->vertex_index(1)});
7506
7507 children[0]->set_used_flag();
7508 children[1]->set_used_flag();
7509 children[0]->clear_children();
7510 children[1]->clear_children();
7511 children[0]->clear_user_data();
7512 children[1]->clear_user_data();
7513 children[0]->clear_user_flag();
7514 children[1]->clear_user_flag();
7515
7516 children[0]->set_boundary_id_internal(line->boundary_id());
7517 children[1]->set_boundary_id_internal(line->boundary_id());
7518
7519 children[0]->set_manifold_id(line->manifold_id());
7520 children[1]->set_manifold_id(line->manifold_id());
7521
7522 // finally clear flag
7523 // indicating the need
7524 // for refinement
7525 line->clear_user_flag();
7526 }
7527 }
7528
7529
7530 //-------------------------------------
7531 // now refine marked quads
7532 //-------------------------------------
7533
7534 // here we encounter several cases:
7535
7536 // a) the quad is unrefined and shall be refined isotropically
7537
7538 // b) the quad is unrefined and shall be refined
7539 // anisotropically
7540
7541 // c) the quad is unrefined and shall be refined both
7542 // anisotropically and isotropically (this is reduced to case
7543 // b) and then case b) for the children again)
7544
7545 // d) the quad is refined anisotropically and shall be refined
7546 // isotropically (this is reduced to case b) for the
7547 // anisotropic children)
7548
7549 // e) the quad is refined isotropically and shall be refined
7550 // anisotropically (this is transformed to case c), however we
7551 // might have to renumber/rename children...)
7552
7553 // we need a loop in cases c) and d), as the anisotropic
7554 // children might have a lower index than the mother quad
7555 for (unsigned int loop = 0; loop < 2; ++loop)
7556 {
7557 // usually, only active objects can be refined
7558 // further. however, in cases d) and e) that is not true,
7559 // so we have to use 'normal' iterators here
7561 quad = triangulation.begin_quad(),
7562 endq = triangulation.end_quad();
7564 next_unused_line = triangulation.begin_raw_line();
7566 next_unused_quad = triangulation.begin_raw_quad();
7567
7568 for (; quad != endq; ++quad)
7569 {
7570 if (quad->user_index())
7571 {
7573 face_refinement_cases[quad->user_index()];
7574 // there is one unlikely event here, where we
7575 // already have refind the face: if the face was
7576 // refined anisotropically and we want to refine
7577 // it isotropically, both children are flagged for
7578 // anisotropic refinement. however, if those
7579 // children were already flagged for anisotropic
7580 // refinement, they might already be processed and
7581 // refined.
7582 if (aniso_quad_ref_case == quad->refinement_case())
7583 continue;
7584
7585 Assert(quad->refinement_case() ==
7587 quad->refinement_case() ==
7590
7591 // this quad needs to be refined anisotropically
7592 Assert(quad->user_index() ==
7594 quad->user_index() ==
7597
7598 // make the new line interior to the quad
7600 new_line;
7601
7602 new_line =
7603 triangulation.faces->lines
7606
7607 // first collect the
7608 // indices of the vertices:
7609 // *--1--*
7610 // | | |
7611 // | | | cut_x
7612 // | | |
7613 // *--0--*
7614 //
7615 // *-----*
7616 // | |
7617 // 0-----1 cut_y
7618 // | |
7619 // *-----*
7620 unsigned int vertex_indices[2];
7622 {
7623 vertex_indices[0] =
7624 quad->line(2)->child(0)->vertex_index(1);
7625 vertex_indices[1] =
7626 quad->line(3)->child(0)->vertex_index(1);
7627 }
7628 else
7629 {
7630 vertex_indices[0] =
7631 quad->line(0)->child(0)->vertex_index(1);
7632 vertex_indices[1] =
7633 quad->line(1)->child(0)->vertex_index(1);
7634 }
7635
7636 new_line->set_bounding_object_indices(
7638 new_line->set_used_flag();
7639 new_line->clear_user_flag();
7640 new_line->clear_user_data();
7641 new_line->clear_children();
7642 new_line->set_boundary_id_internal(quad->boundary_id());
7643 new_line->set_manifold_id(quad->manifold_id());
7644
7645 // find some space (consecutive) for the two newly
7646 // to be created quads.
7648 new_quads[2];
7649
7651 triangulation.faces->quads
7655
7659
7661 {
7662 new_quads[0]->set_bounding_object_indices(
7663 {static_cast<int>(quad->line_index(0)),
7664 new_line->index(),
7665 quad->line(2)
7666 ->child(
7667 child_line_index(0, quad->line_orientation(2)))
7668 ->index(),
7669 quad->line(3)
7670 ->child(
7671 child_line_index(0, quad->line_orientation(3)))
7672 ->index()});
7673 new_quads[1]->set_bounding_object_indices(
7674 {new_line->index(),
7675 static_cast<int>(quad->line_index(1)),
7676 quad->line(2)
7677 ->child(
7678 child_line_index(1, quad->line_orientation(2)))
7679 ->index(),
7680 quad->line(3)
7681 ->child(
7682 child_line_index(1, quad->line_orientation(3)))
7683 ->index()});
7684 }
7685 else
7686 {
7687 new_quads[0]->set_bounding_object_indices(
7688 {quad->line(0)
7689 ->child(
7690 child_line_index(0, quad->line_orientation(0)))
7691 ->index(),
7692 quad->line(1)
7693 ->child(
7694 child_line_index(0, quad->line_orientation(1)))
7695 ->index(),
7696 static_cast<int>(quad->line_index(2)),
7697 new_line->index()});
7698 new_quads[1]->set_bounding_object_indices(
7699 {quad->line(0)
7700 ->child(
7701 child_line_index(1, quad->line_orientation(0)))
7702 ->index(),
7703 quad->line(1)
7704 ->child(
7705 child_line_index(1, quad->line_orientation(1)))
7706 ->index(),
7707 new_line->index(),
7708 static_cast<int>(quad->line_index(3))});
7709 }
7710
7711 for (const auto &new_quad : new_quads)
7712 {
7713 new_quad->set_used_flag();
7714 new_quad->clear_user_flag();
7715 new_quad->clear_user_data();
7716 new_quad->clear_children();
7717 new_quad->set_boundary_id_internal(quad->boundary_id());
7718 new_quad->set_manifold_id(quad->manifold_id());
7719 // set all line orientations to true, change
7720 // this after the loop, as we have to consider
7721 // different lines for each child
7722 for (unsigned int j = 0;
7724 ++j)
7725 new_quad->set_line_orientation(
7727 }
7728 // now set the line orientation of children of
7729 // outer lines correctly, the lines in the
7730 // interior of the refined quad are automatically
7731 // oriented conforming to the standard
7732 new_quads[0]->set_line_orientation(
7733 0, quad->line_orientation(0));
7734 new_quads[0]->set_line_orientation(
7735 2, quad->line_orientation(2));
7736 new_quads[1]->set_line_orientation(
7737 1, quad->line_orientation(1));
7738 new_quads[1]->set_line_orientation(
7739 3, quad->line_orientation(3));
7741 {
7742 new_quads[0]->set_line_orientation(
7743 3, quad->line_orientation(3));
7744 new_quads[1]->set_line_orientation(
7745 2, quad->line_orientation(2));
7746 }
7747 else
7748 {
7749 new_quads[0]->set_line_orientation(
7750 1, quad->line_orientation(1));
7751 new_quads[1]->set_line_orientation(
7752 0, quad->line_orientation(0));
7753 }
7754
7755 // test, whether this face is refined
7756 // isotropically already. if so, set the correct
7757 // children pointers.
7758 if (quad->refinement_case() ==
7759 RefinementCase<dim - 1>::cut_xy)
7760 {
7761 // we will put a new refinemnt level of
7762 // anisotropic refinement between the
7763 // unrefined and isotropically refined quad
7764 // ending up with the same fine quads but
7765 // introducing anisotropically refined ones as
7766 // children of the unrefined quad and mother
7767 // cells of the original fine ones.
7768
7769 // this process includes the creation of a new
7770 // middle line which we will assign as the
7771 // mother line of two of the existing inner
7772 // lines. If those inner lines are not
7773 // consecutive in memory, we won't find them
7774 // later on, so we have to create new ones
7775 // instead and replace all occurrences of the
7776 // old ones with those new ones. As this is
7777 // kind of ugly, we hope we don't have to do
7778 // it often...
7780 old_child[2];
7781 if (aniso_quad_ref_case ==
7783 {
7784 old_child[0] = quad->child(0)->line(1);
7785 old_child[1] = quad->child(2)->line(1);
7786 }
7787 else
7788 {
7792
7793 old_child[0] = quad->child(0)->line(3);
7794 old_child[1] = quad->child(1)->line(3);
7795 }
7796
7797 if (old_child[0]->index() + 1 != old_child[1]->index())
7798 {
7799 // this is exactly the ugly case we talked
7800 // about. so, no complaining, lets get
7801 // two new lines and copy all info
7802 typename Triangulation<dim,
7803 spacedim>::raw_line_iterator
7804 new_child[2];
7805
7806 new_child[0] = new_child[1] =
7807 triangulation.faces->lines
7808 .template next_free_pair_object<1>(
7810 ++new_child[1];
7811
7812 new_child[0]->set_used_flag();
7813 new_child[1]->set_used_flag();
7814
7815 const int old_index_0 = old_child[0]->index(),
7816 old_index_1 = old_child[1]->index(),
7817 new_index_0 = new_child[0]->index(),
7818 new_index_1 = new_child[1]->index();
7819
7820 // loop over all quads and replace the old
7821 // lines
7822 for (unsigned int q = 0;
7823 q < triangulation.faces->quads.n_objects();
7824 ++q)
7825 for (unsigned int l = 0;
7827 ++l)
7828 {
7829 const int this_index =
7830 triangulation.faces->quads
7831 .get_bounding_object_indices(q)[l];
7832 if (this_index == old_index_0)
7833 triangulation.faces->quads
7834 .get_bounding_object_indices(q)[l] =
7836 else if (this_index == old_index_1)
7837 triangulation.faces->quads
7838 .get_bounding_object_indices(q)[l] =
7840 }
7841 // now we have to copy all information of
7842 // the two lines
7843 for (unsigned int i = 0; i < 2; ++i)
7844 {
7845 Assert(!old_child[i]->has_children(),
7847
7848 new_child[i]->set_bounding_object_indices(
7849 {old_child[i]->vertex_index(0),
7850 old_child[i]->vertex_index(1)});
7851 new_child[i]->set_boundary_id_internal(
7852 old_child[i]->boundary_id());
7853 new_child[i]->set_manifold_id(
7854 old_child[i]->manifold_id());
7855 new_child[i]->set_user_index(
7856 old_child[i]->user_index());
7857 if (old_child[i]->user_flag_set())
7858 new_child[i]->set_user_flag();
7859 else
7860 new_child[i]->clear_user_flag();
7861
7862 new_child[i]->clear_children();
7863
7864 old_child[i]->clear_user_flag();
7865 old_child[i]->clear_user_index();
7866 old_child[i]->clear_used_flag();
7867 }
7868 }
7869 // now that we cared about the lines, go on
7870 // with the quads themselves, where we might
7871 // encounter similar situations...
7872 if (aniso_quad_ref_case ==
7874 {
7875 new_line->set_children(
7876 0, quad->child(0)->line_index(1));
7877 Assert(new_line->child(1) ==
7878 quad->child(2)->line(1),
7880 // now evereything is quite
7881 // complicated. we have the children
7882 // numbered according to
7883 //
7884 // *---*---*
7885 // |n+2|n+3|
7886 // *---*---*
7887 // | n |n+1|
7888 // *---*---*
7889 //
7890 // from the original isotropic
7891 // refinement. we have to reorder them as
7892 //
7893 // *---*---*
7894 // |n+1|n+3|
7895 // *---*---*
7896 // | n |n+2|
7897 // *---*---*
7898 //
7899 // such that n and n+1 are consecutive
7900 // children of m and n+2 and n+3 are
7901 // consecutive children of m+1, where m
7902 // and m+1 are given as in
7903 //
7904 // *---*---*
7905 // | | |
7906 // | m |m+1|
7907 // | | |
7908 // *---*---*
7909 //
7910 // this is a bit ugly, of course: loop
7911 // over all cells on all levels and look
7912 // for faces n+1 (switch_1) and n+2
7913 // (switch_2).
7914 const typename Triangulation<dim, spacedim>::
7915 quad_iterator switch_1 = quad->child(1),
7916 switch_2 = quad->child(2);
7917 const int switch_1_index = switch_1->index();
7918 const int switch_2_index = switch_2->index();
7919 for (unsigned int l = 0;
7920 l < triangulation.levels.size();
7921 ++l)
7922 for (unsigned int h = 0;
7923 h <
7924 triangulation.levels[l]->cells.n_objects();
7925 ++h)
7926 for (const unsigned int q :
7928 {
7929 const int face_index =
7930 triangulation.levels[l]
7931 ->cells.get_bounding_object_indices(
7932 h)[q];
7933 if (face_index == switch_1_index)
7934 triangulation.levels[l]
7935 ->cells.get_bounding_object_indices(
7936 h)[q] = switch_2_index;
7937 else if (face_index == switch_2_index)
7938 triangulation.levels[l]
7939 ->cells.get_bounding_object_indices(
7940 h)[q] = switch_1_index;
7941 }
7942 // now we have to copy all information of
7943 // the two quads
7944 const unsigned int switch_1_lines[4] = {
7945 switch_1->line_index(0),
7946 switch_1->line_index(1),
7947 switch_1->line_index(2),
7948 switch_1->line_index(3)};
7951 switch_1->line_orientation(0),
7952 switch_1->line_orientation(1),
7953 switch_1->line_orientation(2),
7954 switch_1->line_orientation(3)};
7956 switch_1->boundary_id();
7957 const unsigned int switch_1_user_index =
7958 switch_1->user_index();
7959 const bool switch_1_user_flag =
7960 switch_1->user_flag_set();
7961 const RefinementCase<dim - 1>
7963 switch_1->refinement_case();
7964 const int switch_1_first_child_pair =
7966 switch_1->child_index(0) :
7967 -1);
7968 const int switch_1_second_child_pair =
7970 RefinementCase<dim - 1>::cut_xy ?
7971 switch_1->child_index(2) :
7972 -1);
7973
7974 switch_1->set_bounding_object_indices(
7975 {switch_2->line_index(0),
7976 switch_2->line_index(1),
7977 switch_2->line_index(2),
7978 switch_2->line_index(3)});
7979 switch_1->set_line_orientation(
7980 0, switch_2->line_orientation(0));
7981 switch_1->set_line_orientation(
7982 1, switch_2->line_orientation(1));
7983 switch_1->set_line_orientation(
7984 2, switch_2->line_orientation(2));
7985 switch_1->set_line_orientation(
7986 3, switch_2->line_orientation(3));
7987 switch_1->set_boundary_id_internal(
7988 switch_2->boundary_id());
7989 switch_1->set_manifold_id(switch_2->manifold_id());
7990 switch_1->set_user_index(switch_2->user_index());
7991 if (switch_2->user_flag_set())
7992 switch_1->set_user_flag();
7993 else
7994 switch_1->clear_user_flag();
7995 switch_1->clear_refinement_case();
7996 switch_1->set_refinement_case(
7997 switch_2->refinement_case());
7998 switch_1->clear_children();
7999 if (switch_2->refinement_case())
8000 switch_1->set_children(0,
8001 switch_2->child_index(0));
8002 if (switch_2->refinement_case() ==
8003 RefinementCase<dim - 1>::cut_xy)
8004 switch_1->set_children(2,
8005 switch_2->child_index(2));
8006
8007 switch_2->set_bounding_object_indices(
8008 {switch_1_lines[0],
8009 switch_1_lines[1],
8010 switch_1_lines[2],
8011 switch_1_lines[3]});
8012 switch_2->set_line_orientation(
8014 switch_2->set_line_orientation(
8016 switch_2->set_line_orientation(
8018 switch_2->set_line_orientation(
8020 switch_2->set_boundary_id_internal(
8022 switch_2->set_manifold_id(switch_1->manifold_id());
8023 switch_2->set_user_index(switch_1_user_index);
8025 switch_2->set_user_flag();
8026 else
8027 switch_2->clear_user_flag();
8028 switch_2->clear_refinement_case();
8029 switch_2->set_refinement_case(
8031 switch_2->clear_children();
8032 switch_2->set_children(0,
8034 switch_2->set_children(2,
8036
8037 new_quads[0]->set_refinement_case(
8039 new_quads[0]->set_children(0, quad->child_index(0));
8040 new_quads[1]->set_refinement_case(
8042 new_quads[1]->set_children(0, quad->child_index(2));
8043 }
8044 else
8045 {
8046 new_quads[0]->set_refinement_case(
8048 new_quads[0]->set_children(0, quad->child_index(0));
8049 new_quads[1]->set_refinement_case(
8051 new_quads[1]->set_children(0, quad->child_index(2));
8052 new_line->set_children(
8053 0, quad->child(0)->line_index(3));
8054 Assert(new_line->child(1) ==
8055 quad->child(1)->line(3),
8057 }
8058 quad->clear_children();
8059 }
8060
8061 // note these quads as children to the present one
8062 quad->set_children(0, new_quads[0]->index());
8063
8064 quad->set_refinement_case(aniso_quad_ref_case);
8065
8066 // finally clear flag indicating the need for
8067 // refinement
8068 quad->clear_user_data();
8069 } // if (anisotropic refinement)
8070
8071 if (quad->user_flag_set())
8072 {
8073 // this quad needs to be refined isotropically
8074
8075 // first of all: we only get here in the first run
8076 // of the loop
8077 Assert(loop == 0, ExcInternalError());
8078
8079 // find the next unused vertex. we'll need this in
8080 // any case
8081 while (triangulation.vertices_used[next_unused_vertex] ==
8082 true)
8084 Assert(
8085 next_unused_vertex < triangulation.vertices.size(),
8086 ExcMessage(
8087 "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."));
8088
8089 // now: if the quad is refined anisotropically
8090 // already, set the anisotropic refinement flag
8091 // for both children. Additionally, we have to
8092 // refine the inner line, as it is an outer line
8093 // of the two (anisotropic) children
8094 const RefinementCase<dim - 1> quad_ref_case =
8095 quad->refinement_case();
8096
8099 {
8100 // set the 'opposite' refine case for children
8101 quad->child(0)->set_user_index(
8103 quad->child(1)->set_user_index(
8105 // refine the inner line
8109 middle_line = quad->child(0)->line(1);
8110 else
8111 middle_line = quad->child(0)->line(3);
8112
8113 // if the face has been refined
8114 // anisotropically in the last refinement step
8115 // it might be, that it is flagged already and
8116 // that the middle line is thus refined
8117 // already. if not create children.
8118 if (!middle_line->has_children())
8119 {
8120 // set the middle vertex
8121 // appropriately. double refinement of
8122 // quads can only happen in the interior
8123 // of the domain, so we need not care
8124 // about boundary quads here
8126 middle_line->center(true);
8127 triangulation.vertices_used[next_unused_vertex] =
8128 true;
8129
8130 // now search a slot for the two
8131 // child lines
8133 triangulation.faces->lines
8134 .template next_free_pair_object<1>(
8136
8137 // set the child pointer of the present
8138 // line
8139 middle_line->set_children(
8140 0, next_unused_line->index());
8141
8142 // set the two new lines
8143 const typename Triangulation<dim, spacedim>::
8144 raw_line_iterator children[2] = {
8146
8147 // some tests; if any of the iterators
8148 // should be invalid, then already
8149 // dereferencing will fail
8150 AssertIsNotUsed(children[0]);
8151 AssertIsNotUsed(children[1]);
8152
8153 children[0]->set_bounding_object_indices(
8154 {middle_line->vertex_index(0),
8156 children[1]->set_bounding_object_indices(
8158 middle_line->vertex_index(1)});
8159
8160 children[0]->set_used_flag();
8161 children[1]->set_used_flag();
8162 children[0]->clear_children();
8163 children[1]->clear_children();
8164 children[0]->clear_user_data();
8165 children[1]->clear_user_data();
8166 children[0]->clear_user_flag();
8167 children[1]->clear_user_flag();
8168
8169 children[0]->set_boundary_id_internal(
8170 middle_line->boundary_id());
8171 children[1]->set_boundary_id_internal(
8172 middle_line->boundary_id());
8173
8174 children[0]->set_manifold_id(
8175 middle_line->manifold_id());
8176 children[1]->set_manifold_id(
8177 middle_line->manifold_id());
8178 }
8179 // now remove the flag from the quad and go to
8180 // the next quad, the actual refinement of the
8181 // quad takes place later on in this pass of
8182 // the loop or in the next one
8183 quad->clear_user_flag();
8184 continue;
8185 } // if (several refinement cases)
8186
8187 // if we got here, we have an unrefined quad and
8188 // have to do the usual work like in an purely
8189 // isotropic refinement
8193
8194 // set the middle vertex appropriately: it might be that
8195 // the quad itself is not at the boundary, but that one of
8196 // its lines actually is. in this case, the newly created
8197 // vertices at the centers of the lines are not
8198 // necessarily the mean values of the adjacent vertices,
8199 // so do not compute the new vertex as the mean value of
8200 // the 4 vertices of the face, but rather as a weighted
8201 // mean value of the 8 vertices which we already have (the
8202 // four old ones, and the four ones inserted as middle
8203 // points for the four lines). summing up some more points
8204 // is generally cheaper than first asking whether one of
8205 // the lines is at the boundary
8206 //
8207 // note that the exact weights are chosen such as to
8208 // minimize the distortion of the four new quads from the
8209 // optimal shape. their description uses the formulas
8210 // underlying the TransfiniteInterpolationManifold
8211 // implementation
8213 quad->center(true, true);
8214 triangulation.vertices_used[next_unused_vertex] = true;
8215
8216 // now that we created the right point, make up
8217 // the four lines interior to the quad (++ takes
8218 // care of the end of the vector)
8220 new_lines[4];
8221
8222 for (unsigned int i = 0; i < 4; ++i)
8223 {
8224 if (i % 2 == 0)
8225 // search a free pair of lines for 0. and
8226 // 2. line, so that two of them end up
8227 // together, which is necessary if later on
8228 // we want to refine the quad
8229 // anisotropically and the two lines end up
8230 // as children of new line
8232 triangulation.faces->lines
8234
8237
8239 }
8240
8241 // set the data of the four lines. first collect
8242 // the indices of the five vertices:
8243 //
8244 // *--3--*
8245 // | | |
8246 // 0--4--1
8247 // | | |
8248 // *--2--*
8249 //
8250 // the lines are numbered as follows:
8251 //
8252 // *--*--*
8253 // | 1 |
8254 // *2-*-3*
8255 // | 0 |
8256 // *--*--*
8257
8258 const unsigned int vertex_indices[5] = {
8259 quad->line(0)->child(0)->vertex_index(1),
8260 quad->line(1)->child(0)->vertex_index(1),
8261 quad->line(2)->child(0)->vertex_index(1),
8262 quad->line(3)->child(0)->vertex_index(1),
8264
8265 new_lines[0]->set_bounding_object_indices(
8267 new_lines[1]->set_bounding_object_indices(
8269 new_lines[2]->set_bounding_object_indices(
8271 new_lines[3]->set_bounding_object_indices(
8273
8274 for (const auto &new_line : new_lines)
8275 {
8276 new_line->set_used_flag();
8277 new_line->clear_user_flag();
8278 new_line->clear_user_data();
8279 new_line->clear_children();
8280 new_line->set_boundary_id_internal(quad->boundary_id());
8281 new_line->set_manifold_id(quad->manifold_id());
8282 }
8283
8284 // now for the quads. again, first collect some
8285 // data about the indices of the lines, with the
8286 // following numbering:
8287 //
8288 // .-6-.-7-.
8289 // 1 9 3
8290 // .-10.11-.
8291 // 0 8 2
8292 // .-4-.-5-.
8293
8294 const int line_indices[12] = {
8295 quad->line(0)
8296 ->child(child_line_index(0, quad->line_orientation(0)))
8297 ->index(),
8298 quad->line(0)
8299 ->child(child_line_index(1, quad->line_orientation(0)))
8300 ->index(),
8301 quad->line(1)
8302 ->child(child_line_index(0, quad->line_orientation(1)))
8303 ->index(),
8304 quad->line(1)
8305 ->child(child_line_index(1, quad->line_orientation(1)))
8306 ->index(),
8307 quad->line(2)
8308 ->child(child_line_index(0, quad->line_orientation(2)))
8309 ->index(),
8310 quad->line(2)
8311 ->child(child_line_index(1, quad->line_orientation(2)))
8312 ->index(),
8313 quad->line(3)
8314 ->child(child_line_index(0, quad->line_orientation(3)))
8315 ->index(),
8316 quad->line(3)
8317 ->child(child_line_index(1, quad->line_orientation(3)))
8318 ->index(),
8319 new_lines[0]->index(),
8320 new_lines[1]->index(),
8321 new_lines[2]->index(),
8322 new_lines[3]->index()};
8323
8324 // find some space (consecutive)
8325 // for the first two newly to be
8326 // created quads.
8328 new_quads[4];
8329
8331 triangulation.faces->quads
8333
8336
8340
8342 triangulation.faces->quads
8346
8350
8351 // note these quads as children to the present one
8352 quad->set_children(0, new_quads[0]->index());
8353 quad->set_children(2, new_quads[2]->index());
8354 quad->set_refinement_case(RefinementCase<2>::cut_xy);
8355
8356 new_quads[0]->set_bounding_object_indices(
8357 {line_indices[0],
8358 line_indices[8],
8359 line_indices[4],
8360 line_indices[10]});
8361 new_quads[1]->set_bounding_object_indices(
8362 {line_indices[8],
8363 line_indices[2],
8364 line_indices[5],
8365 line_indices[11]});
8366 new_quads[2]->set_bounding_object_indices(
8367 {line_indices[1],
8368 line_indices[9],
8369 line_indices[10],
8370 line_indices[6]});
8371 new_quads[3]->set_bounding_object_indices(
8372 {line_indices[9],
8373 line_indices[3],
8374 line_indices[11],
8375 line_indices[7]});
8376 for (const auto &new_quad : new_quads)
8377 {
8378 new_quad->set_used_flag();
8379 new_quad->clear_user_flag();
8380 new_quad->clear_user_data();
8381 new_quad->clear_children();
8382 new_quad->set_boundary_id_internal(quad->boundary_id());
8383 new_quad->set_manifold_id(quad->manifold_id());
8384 // set all line orientations to true, change
8385 // this after the loop, as we have to consider
8386 // different lines for each child
8387 for (unsigned int j = 0;
8389 ++j)
8390 new_quad->set_line_orientation(
8392 }
8393 // now set the line orientation of children of
8394 // outer lines correctly, the lines in the
8395 // interior of the refined quad are automatically
8396 // oriented conforming to the standard
8397 new_quads[0]->set_line_orientation(
8398 0, quad->line_orientation(0));
8399 new_quads[0]->set_line_orientation(
8400 2, quad->line_orientation(2));
8401 new_quads[1]->set_line_orientation(
8402 1, quad->line_orientation(1));
8403 new_quads[1]->set_line_orientation(
8404 2, quad->line_orientation(2));
8405 new_quads[2]->set_line_orientation(
8406 0, quad->line_orientation(0));
8407 new_quads[2]->set_line_orientation(
8408 3, quad->line_orientation(3));
8409 new_quads[3]->set_line_orientation(
8410 1, quad->line_orientation(1));
8411 new_quads[3]->set_line_orientation(
8412 3, quad->line_orientation(3));
8413
8414 // finally clear flag indicating the need for
8415 // refinement
8416 quad->clear_user_flag();
8417 } // if (isotropic refinement)
8418 } // for all quads
8419 } // looped two times over all quads, all quads refined now
8420
8421 //---------------------------------
8422 // Now, finally, set up the new
8423 // cells
8424 //---------------------------------
8425
8428
8429 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
8430 ++level)
8431 {
8432 // only active objects can be refined further; remember
8433 // that we won't operate on the finest level, so
8434 // triangulation.begin_*(level+1) is allowed
8436 hex = triangulation.begin_active_hex(level),
8437 endh = triangulation.begin_active_hex(level + 1);
8439 next_unused_hex = triangulation.begin_raw_hex(level + 1);
8440
8441 for (; hex != endh; ++hex)
8442 if (hex->refine_flag_set())
8443 {
8444 // this hex needs to be refined
8445
8446 // clear flag indicating the need for refinement. do
8447 // it here already, since we can't do it anymore
8448 // once the cell has children
8449 const RefinementCase<dim> ref_case = hex->refine_flag_set();
8450 hex->clear_refine_flag();
8451 hex->set_refinement_case(ref_case);
8452
8453 // depending on the refine case we might have to
8454 // create additional vertices, lines and quads
8455 // interior of the hex before the actual children
8456 // can be set up.
8457
8458 // in a first step: reserve the needed space for
8459 // lines, quads and hexes and initialize them
8460 // correctly
8461
8462 unsigned int n_new_lines = 0;
8463 unsigned int n_new_quads = 0;
8464 unsigned int n_new_hexes = 0;
8465 switch (ref_case)
8466 {
8470 n_new_lines = 0;
8471 n_new_quads = 1;
8472 n_new_hexes = 2;
8473 break;
8477 n_new_lines = 1;
8478 n_new_quads = 4;
8479 n_new_hexes = 4;
8480 break;
8482 n_new_lines = 6;
8483 n_new_quads = 12;
8484 n_new_hexes = 8;
8485 break;
8486 default:
8488 break;
8489 }
8490
8491 // find some space for the newly to be created
8492 // interior lines and initialize them.
8493 std::vector<
8496 for (unsigned int i = 0; i < n_new_lines; ++i)
8497 {
8498 new_lines[i] =
8499 triangulation.faces->lines
8501
8503 new_lines[i]->set_used_flag();
8504 new_lines[i]->clear_user_flag();
8505 new_lines[i]->clear_user_data();
8506 new_lines[i]->clear_children();
8507 // interior line
8508 new_lines[i]->set_boundary_id_internal(
8510 // they inherit geometry description of the hex they
8511 // belong to
8512 new_lines[i]->set_manifold_id(hex->manifold_id());
8513 }
8514
8515 // find some space for the newly to be created
8516 // interior quads and initialize them.
8517 std::vector<
8520 for (unsigned int i = 0; i < n_new_quads; ++i)
8521 {
8522 new_quads[i] =
8523 triangulation.faces->quads
8525
8527 new_quads[i]->set_used_flag();
8528 new_quads[i]->clear_user_flag();
8529 new_quads[i]->clear_user_data();
8530 new_quads[i]->clear_children();
8531 // interior quad
8532 new_quads[i]->set_boundary_id_internal(
8534 // they inherit geometry description of the hex they
8535 // belong to
8536 new_quads[i]->set_manifold_id(hex->manifold_id());
8537 // set all line orientation flags to true by
8538 // default, change this afterwards, if necessary
8539 for (unsigned int j = 0;
8541 ++j)
8542 new_quads[i]->set_line_orientation(
8544 }
8545
8546 types::subdomain_id subdomainid = hex->subdomain_id();
8547
8548 // find some space for the newly to be created hexes
8549 // and initialize them.
8550 std::vector<
8553 for (unsigned int i = 0; i < n_new_hexes; ++i)
8554 {
8555 if (i % 2 == 0)
8557 triangulation.levels[level + 1]->cells.next_free_hex(
8558 triangulation, level + 1);
8559 else
8561
8563
8565 new_hexes[i]->set_used_flag();
8566 new_hexes[i]->clear_user_flag();
8567 new_hexes[i]->clear_user_data();
8568 new_hexes[i]->clear_children();
8569 // inherit material
8570 // properties
8571 new_hexes[i]->set_material_id(hex->material_id());
8572 new_hexes[i]->set_manifold_id(hex->manifold_id());
8573 new_hexes[i]->set_subdomain_id(subdomainid);
8574
8575 if (i % 2)
8576 new_hexes[i]->set_parent(hex->index());
8577 // set the face_orientation flag to true for all
8578 // faces initially, as this is the default value
8579 // which is true for all faces interior to the
8580 // hex. later on go the other way round and
8581 // reset faces that are at the boundary of the
8582 // mother cube
8583 //
8584 // the same is true for the face_flip and
8585 // face_rotation flags. however, the latter two
8586 // are set to false by default as this is the
8587 // standard value
8588 for (const unsigned int f :
8590 new_hexes[i]->set_combined_face_orientation(
8592 }
8593 // note these hexes as children to the present cell
8594 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
8595 hex->set_children(2 * i, new_hexes[2 * i]->index());
8596
8597 // we have to take into account whether the
8598 // different faces are oriented correctly or in the
8599 // opposite direction, so store that up front
8600
8601 // face_orientation
8602 const bool f_or[6] = {hex->face_orientation(0),
8603 hex->face_orientation(1),
8604 hex->face_orientation(2),
8605 hex->face_orientation(3),
8606 hex->face_orientation(4),
8607 hex->face_orientation(5)};
8608
8609 // face_flip
8610 const bool f_fl[6] = {hex->face_flip(0),
8611 hex->face_flip(1),
8612 hex->face_flip(2),
8613 hex->face_flip(3),
8614 hex->face_flip(4),
8615 hex->face_flip(5)};
8616
8617 // face_rotation
8618 const bool f_ro[6] = {hex->face_rotation(0),
8619 hex->face_rotation(1),
8620 hex->face_rotation(2),
8621 hex->face_rotation(3),
8622 hex->face_rotation(4),
8623 hex->face_rotation(5)};
8624
8625 // combined orientation
8627 hex->combined_face_orientation(0),
8628 hex->combined_face_orientation(1),
8629 hex->combined_face_orientation(2),
8630 hex->combined_face_orientation(3),
8631 hex->combined_face_orientation(4),
8632 hex->combined_face_orientation(5)};
8633
8634 // little helper table, indicating, whether the
8635 // child with index 0 or with index 1 can be found
8636 // at the standard origin of an anisotropically
8637 // refined quads in real orientation index 1:
8638 // (RefineCase - 1) index 2: face_flip
8639
8640 // index 3: face rotation
8641 // note: face orientation has no influence
8642 const unsigned int child_at_origin[2][2][2] = {
8643 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
8644 // face_rotation=false and true
8645 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
8646 // face_rotation=false and true
8647 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
8648 // face_rotation=false and true
8649 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
8650 // face_rotation=false and true
8651
8652 //-------------------------------------
8653 //
8654 // in the following we will do the same thing for
8655 // each refinement case: create a new vertex (if
8656 // needed), create new interior lines (if needed),
8657 // create new interior quads and afterwards build
8658 // the children hexes out of these and the existing
8659 // subfaces of the outer quads (which have been
8660 // created above). However, even if the steps are
8661 // quite similar, the actual work strongly depends
8662 // on the actual refinement case. therefore, we use
8663 // separate blocks of code for each of these cases,
8664 // which hopefully increases the readability to some
8665 // extend.
8666
8667 switch (ref_case)
8668 {
8670 {
8671 //----------------------------
8672 //
8673 // RefinementCase<dim>::cut_x
8674 //
8675 // the refined cube will look
8676 // like this:
8677 //
8678 // *----*----*
8679 // / / /|
8680 // / / / |
8681 // / / / |
8682 // *----*----* |
8683 // | | | |
8684 // | | | *
8685 // | | | /
8686 // | | | /
8687 // | | |/
8688 // *----*----*
8689 //
8690 // again, first collect some data about the
8691 // indices of the lines, with the following
8692 // numbering:
8693
8694 // face 2: front plane
8695 // (note: x,y exchanged)
8696 // *---*---*
8697 // | | |
8698 // | 0 |
8699 // | | |
8700 // *---*---*
8701 // m0
8702 // face 3: back plane
8703 // (note: x,y exchanged)
8704 // m1
8705 // *---*---*
8706 // | | |
8707 // | 1 |
8708 // | | |
8709 // *---*---*
8710 // face 4: bottom plane
8711 // *---*---*
8712 // / / /
8713 // / 2 /
8714 // / / /
8715 // *---*---*
8716 // m0
8717 // face 5: top plane
8718 // m1
8719 // *---*---*
8720 // / / /
8721 // / 3 /
8722 // / / /
8723 // *---*---*
8724
8725 // set up a list of line iterators first. from
8726 // this, construct lists of line_indices and
8727 // line orientations later on
8728 const typename Triangulation<dim, spacedim>::
8729 raw_line_iterator lines[4] = {
8730 hex->face(2)->child(0)->line(
8731 (hex->face(2)->refinement_case() ==
8733 1 :
8734 3), // 0
8735 hex->face(3)->child(0)->line(
8736 (hex->face(3)->refinement_case() ==
8738 1 :
8739 3), // 1
8740 hex->face(4)->child(0)->line(
8741 (hex->face(4)->refinement_case() ==
8743 1 :
8744 3), // 2
8745 hex->face(5)->child(0)->line(
8746 (hex->face(5)->refinement_case() ==
8748 1 :
8749 3) // 3
8750 };
8751
8752 unsigned int line_indices[4];
8753 for (unsigned int i = 0; i < 4; ++i)
8754 line_indices[i] = lines[i]->index();
8755
8756 // the orientation of lines for the inner quads
8757 // is quite tricky. as these lines are newly
8758 // created ones and thus have no parents, they
8759 // cannot inherit this property. set up an array
8760 // and fill it with the respective values
8761 types::geometric_orientation line_orientation[4]{};
8762
8763 // the middle vertex marked as m0 above is the
8764 // start vertex for lines 0 and 2 in standard
8765 // orientation, whereas m1 is the end vertex of
8766 // lines 1 and 3 in standard orientation
8767 const unsigned int middle_vertices[2] = {
8768 hex->line(2)->child(0)->vertex_index(1),
8769 hex->line(7)->child(0)->vertex_index(1)};
8770
8771 for (unsigned int i = 0; i < 4; ++i)
8772 if (lines[i]->vertex_index(i % 2) ==
8773 middle_vertices[i % 2])
8774 line_orientation[i] =
8776 else
8777 {
8778 // it must be the other way round then
8779 Assert(lines[i]->vertex_index((i + 1) % 2) ==
8780 middle_vertices[i % 2],
8782 line_orientation[i] =
8784 }
8785
8786 // set up the new quad, line numbering is as
8787 // indicated above
8788 new_quads[0]->set_bounding_object_indices(
8789 {line_indices[0],
8790 line_indices[1],
8791 line_indices[2],
8792 line_indices[3]});
8793
8794 new_quads[0]->set_line_orientation(
8795 0, line_orientation[0]);
8796 new_quads[0]->set_line_orientation(
8797 1, line_orientation[1]);
8798 new_quads[0]->set_line_orientation(
8799 2, line_orientation[2]);
8800 new_quads[0]->set_line_orientation(
8801 3, line_orientation[3]);
8802
8803 // the quads are numbered as follows:
8804 //
8805 // planes in the interior of the old hex:
8806 //
8807 // *
8808 // /|
8809 // / | x
8810 // / | *-------* *---------*
8811 // * | | | / /
8812 // | 0 | | | / /
8813 // | * | | / /
8814 // | / *-------*y *---------*x
8815 // | /
8816 // |/
8817 // *
8818 //
8819 // children of the faces of the old hex
8820 //
8821 // *---*---* *---*---*
8822 // /| | | / / /|
8823 // / | | | / 9 / 10/ |
8824 // / | 5 | 6 | / / / |
8825 // * | | | *---*---* |
8826 // | 1 *---*---* | | | 2 *
8827 // | / / / | | | /
8828 // | / 7 / 8 / | 3 | 4 | /
8829 // |/ / / | | |/
8830 // *---*---* *---*---*
8831 //
8832 // note that we have to take care of the
8833 // orientation of faces.
8834 const int quad_indices[11] = {
8835 new_quads[0]->index(), // 0
8836
8837 hex->face(0)->index(), // 1
8838
8839 hex->face(1)->index(), // 2
8840
8841 hex->face(2)->child_index(
8842 child_at_origin[hex->face(2)->refinement_case() -
8843 1][f_fl[2]][f_ro[2]]), // 3
8844 hex->face(2)->child_index(
8845 1 -
8846 child_at_origin[hex->face(2)->refinement_case() -
8847 1][f_fl[2]][f_ro[2]]),
8848
8849 hex->face(3)->child_index(
8850 child_at_origin[hex->face(3)->refinement_case() -
8851 1][f_fl[3]][f_ro[3]]), // 5
8852 hex->face(3)->child_index(
8853 1 -
8854 child_at_origin[hex->face(3)->refinement_case() -
8855 1][f_fl[3]][f_ro[3]]),
8856
8857 hex->face(4)->child_index(
8858 child_at_origin[hex->face(4)->refinement_case() -
8859 1][f_fl[4]][f_ro[4]]), // 7
8860 hex->face(4)->child_index(
8861 1 -
8862 child_at_origin[hex->face(4)->refinement_case() -
8863 1][f_fl[4]][f_ro[4]]),
8864
8865 hex->face(5)->child_index(
8866 child_at_origin[hex->face(5)->refinement_case() -
8867 1][f_fl[5]][f_ro[5]]), // 9
8868 hex->face(5)->child_index(
8869 1 -
8870 child_at_origin[hex->face(5)->refinement_case() -
8871 1][f_fl[5]][f_ro[5]])
8872
8873 };
8874
8875 new_hexes[0]->set_bounding_object_indices(
8876 {quad_indices[1],
8877 quad_indices[0],
8878 quad_indices[3],
8879 quad_indices[5],
8880 quad_indices[7],
8881 quad_indices[9]});
8882 new_hexes[1]->set_bounding_object_indices(
8883 {quad_indices[0],
8884 quad_indices[2],
8885 quad_indices[4],
8886 quad_indices[6],
8887 quad_indices[8],
8888 quad_indices[10]});
8889 break;
8890 }
8891
8893 {
8894 //----------------------------
8895 //
8896 // RefinementCase<dim>::cut_y
8897 //
8898 // the refined cube will look like this:
8899 //
8900 // *---------*
8901 // / /|
8902 // *---------* |
8903 // / /| |
8904 // *---------* | |
8905 // | | | |
8906 // | | | *
8907 // | | |/
8908 // | | *
8909 // | |/
8910 // *---------*
8911 //
8912 // again, first collect some data about the
8913 // indices of the lines, with the following
8914 // numbering:
8915
8916 // face 0: left plane
8917 // *
8918 // /|
8919 // * |
8920 // /| |
8921 // * | |
8922 // | 0 |
8923 // | | *
8924 // | |/
8925 // | *m0
8926 // |/
8927 // *
8928 // face 1: right plane
8929 // *
8930 // /|
8931 // m1* |
8932 // /| |
8933 // * | |
8934 // | 1 |
8935 // | | *
8936 // | |/
8937 // | *
8938 // |/
8939 // *
8940 // face 4: bottom plane
8941 // *-------*
8942 // / /
8943 // m0*---2---*
8944 // / /
8945 // *-------*
8946 // face 5: top plane
8947 // *-------*
8948 // / /
8949 // *---3---*m1
8950 // / /
8951 // *-------*
8952
8953 // set up a list of line iterators first. from
8954 // this, construct lists of line_indices and
8955 // line orientations later on
8956 const typename Triangulation<dim, spacedim>::
8957 raw_line_iterator lines[4] = {
8958 hex->face(0)->child(0)->line(
8959 (hex->face(0)->refinement_case() ==
8961 1 :
8962 3), // 0
8963 hex->face(1)->child(0)->line(
8964 (hex->face(1)->refinement_case() ==
8966 1 :
8967 3), // 1
8968 hex->face(4)->child(0)->line(
8969 (hex->face(4)->refinement_case() ==
8971 1 :
8972 3), // 2
8973 hex->face(5)->child(0)->line(
8974 (hex->face(5)->refinement_case() ==
8976 1 :
8977 3) // 3
8978 };
8979
8980 unsigned int line_indices[4];
8981 for (unsigned int i = 0; i < 4; ++i)
8982 line_indices[i] = lines[i]->index();
8983
8984 // the orientation of lines for the inner quads
8985 // is quite tricky. as these lines are newly
8986 // created ones and thus have no parents, they
8987 // cannot inherit this property. set up an array
8988 // and fill it with the respective values
8989 types::geometric_orientation line_orientation[4]{};
8990
8991 // the middle vertex marked as m0 above is the
8992 // start vertex for lines 0 and 2 in standard
8993 // orientation, whereas m1 is the end vertex of
8994 // lines 1 and 3 in standard orientation
8995 const unsigned int middle_vertices[2] = {
8996 hex->line(0)->child(0)->vertex_index(1),
8997 hex->line(5)->child(0)->vertex_index(1)};
8998
8999 for (unsigned int i = 0; i < 4; ++i)
9000 if (lines[i]->vertex_index(i % 2) ==
9001 middle_vertices[i % 2])
9002 line_orientation[i] =
9004 else
9005 {
9006 // it must be the other way round then
9007 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9008 middle_vertices[i % 2],
9010 line_orientation[i] =
9012 }
9013
9014 // set up the new quad, line numbering is as
9015 // indicated above
9016 new_quads[0]->set_bounding_object_indices(
9017 {line_indices[2],
9018 line_indices[3],
9019 line_indices[0],
9020 line_indices[1]});
9021
9022 new_quads[0]->set_line_orientation(
9023 0, line_orientation[2]);
9024 new_quads[0]->set_line_orientation(
9025 1, line_orientation[3]);
9026 new_quads[0]->set_line_orientation(
9027 2, line_orientation[0]);
9028 new_quads[0]->set_line_orientation(
9029 3, line_orientation[1]);
9030
9031 // the quads are numbered as follows:
9032 //
9033 // planes in the interior of the old hex:
9034 //
9035 // *
9036 // /|
9037 // / | x
9038 // / | *-------* *---------*
9039 // * | | | / /
9040 // | | | 0 | / /
9041 // | * | | / /
9042 // | / *-------*y *---------*x
9043 // | /
9044 // |/
9045 // *
9046 //
9047 // children of the faces of the old hex
9048 //
9049 // *-------* *-------*
9050 // /| | / 10 /|
9051 // * | | *-------* |
9052 // /| | 6 | / 9 /| |
9053 // * |2| | *-------* |4|
9054 // | | *-------* | | | *
9055 // |1|/ 8 / | |3|/
9056 // | *-------* | 5 | *
9057 // |/ 7 / | |/
9058 // *-------* *-------*
9059 //
9060 // note that we have to take care of the
9061 // orientation of faces.
9062 const int quad_indices[11] = {
9063 new_quads[0]->index(), // 0
9064
9065 hex->face(0)->child_index(
9066 child_at_origin[hex->face(0)->refinement_case() -
9067 1][f_fl[0]][f_ro[0]]), // 1
9068 hex->face(0)->child_index(
9069 1 -
9070 child_at_origin[hex->face(0)->refinement_case() -
9071 1][f_fl[0]][f_ro[0]]),
9072
9073 hex->face(1)->child_index(
9074 child_at_origin[hex->face(1)->refinement_case() -
9075 1][f_fl[1]][f_ro[1]]), // 3
9076 hex->face(1)->child_index(
9077 1 -
9078 child_at_origin[hex->face(1)->refinement_case() -
9079 1][f_fl[1]][f_ro[1]]),
9080
9081 hex->face(2)->index(), // 5
9082
9083 hex->face(3)->index(), // 6
9084
9085 hex->face(4)->child_index(
9086 child_at_origin[hex->face(4)->refinement_case() -
9087 1][f_fl[4]][f_ro[4]]), // 7
9088 hex->face(4)->child_index(
9089 1 -
9090 child_at_origin[hex->face(4)->refinement_case() -
9091 1][f_fl[4]][f_ro[4]]),
9092
9093 hex->face(5)->child_index(
9094 child_at_origin[hex->face(5)->refinement_case() -
9095 1][f_fl[5]][f_ro[5]]), // 9
9096 hex->face(5)->child_index(
9097 1 -
9098 child_at_origin[hex->face(5)->refinement_case() -
9099 1][f_fl[5]][f_ro[5]])
9100
9101 };
9102
9103 new_hexes[0]->set_bounding_object_indices(
9104 {quad_indices[1],
9105 quad_indices[3],
9106 quad_indices[5],
9107 quad_indices[0],
9108 quad_indices[7],
9109 quad_indices[9]});
9110 new_hexes[1]->set_bounding_object_indices(
9111 {quad_indices[2],
9112 quad_indices[4],
9113 quad_indices[0],
9114 quad_indices[6],
9115 quad_indices[8],
9116 quad_indices[10]});
9117 break;
9118 }
9119
9121 {
9122 //----------------------------
9123 //
9124 // RefinementCase<dim>::cut_z
9125 //
9126 // the refined cube will look like this:
9127 //
9128 // *---------*
9129 // / /|
9130 // / / |
9131 // / / *
9132 // *---------* /|
9133 // | | / |
9134 // | |/ *
9135 // *---------* /
9136 // | | /
9137 // | |/
9138 // *---------*
9139 //
9140 // again, first collect some data about the
9141 // indices of the lines, with the following
9142 // numbering:
9143
9144 // face 0: left plane
9145 // *
9146 // /|
9147 // / |
9148 // / *
9149 // * /|
9150 // | 0 |
9151 // |/ *
9152 // m0* /
9153 // | /
9154 // |/
9155 // *
9156 // face 1: right plane
9157 // *
9158 // /|
9159 // / |
9160 // / *m1
9161 // * /|
9162 // | 1 |
9163 // |/ *
9164 // * /
9165 // | /
9166 // |/
9167 // *
9168 // face 2: front plane
9169 // (note: x,y exchanged)
9170 // *-------*
9171 // | |
9172 // m0*---2---*
9173 // | |
9174 // *-------*
9175 // face 3: back plane
9176 // (note: x,y exchanged)
9177 // *-------*
9178 // | |
9179 // *---3---*m1
9180 // | |
9181 // *-------*
9182
9183 // set up a list of line iterators first. from
9184 // this, construct lists of line_indices and
9185 // line orientations later on
9186 const typename Triangulation<dim, spacedim>::
9187 raw_line_iterator lines[4] = {
9188 hex->face(0)->child(0)->line(
9189 (hex->face(0)->refinement_case() ==
9191 1 :
9192 3), // 0
9193 hex->face(1)->child(0)->line(
9194 (hex->face(1)->refinement_case() ==
9196 1 :
9197 3), // 1
9198 hex->face(2)->child(0)->line(
9199 (hex->face(2)->refinement_case() ==
9201 1 :
9202 3), // 2
9203 hex->face(3)->child(0)->line(
9204 (hex->face(3)->refinement_case() ==
9206 1 :
9207 3) // 3
9208 };
9209
9210 unsigned int line_indices[4];
9211 for (unsigned int i = 0; i < 4; ++i)
9212 line_indices[i] = lines[i]->index();
9213
9214 // the orientation of lines for the inner quads
9215 // is quite tricky. as these lines are newly
9216 // created ones and thus have no parents, they
9217 // cannot inherit this property. set up an array
9218 // and fill it with the respective values
9219 types::geometric_orientation line_orientation[4]{};
9220
9221 // the middle vertex marked as m0 above is the
9222 // start vertex for lines 0 and 2 in standard
9223 // orientation, whereas m1 is the end vertex of
9224 // lines 1 and 3 in standard orientation
9225 const unsigned int middle_vertices[2] = {
9227 middle_vertex_index<dim, spacedim>(hex->line(11))};
9228
9229 for (unsigned int i = 0; i < 4; ++i)
9230 if (lines[i]->vertex_index(i % 2) ==
9231 middle_vertices[i % 2])
9232 line_orientation[i] =
9234 else
9235 {
9236 // it must be the other way round then
9237 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9238 middle_vertices[i % 2],
9240 line_orientation[i] =
9242 }
9243
9244 // set up the new quad, line numbering is as
9245 // indicated above
9246 new_quads[0]->set_bounding_object_indices(
9247 {line_indices[0],
9248 line_indices[1],
9249 line_indices[2],
9250 line_indices[3]});
9251
9252 new_quads[0]->set_line_orientation(
9253 0, line_orientation[0]);
9254 new_quads[0]->set_line_orientation(
9255 1, line_orientation[1]);
9256 new_quads[0]->set_line_orientation(
9257 2, line_orientation[2]);
9258 new_quads[0]->set_line_orientation(
9259 3, line_orientation[3]);
9260
9261 // the quads are numbered as follows:
9262 //
9263 // planes in the interior of the old hex:
9264 //
9265 // *
9266 // /|
9267 // / | x
9268 // / | *-------* *---------*
9269 // * | | | / /
9270 // | | | | / 0 /
9271 // | * | | / /
9272 // | / *-------*y *---------*x
9273 // | /
9274 // |/
9275 // *
9276 //
9277 // children of the faces of the old hex
9278 //
9279 // *---*---* *-------*
9280 // /| 8 | / /|
9281 // / | | / 10 / |
9282 // / *-------* / / *
9283 // * 2/| | *-------* 4/|
9284 // | / | 7 | | 6 | / |
9285 // |/1 *-------* | |/3 *
9286 // * / / *-------* /
9287 // | / 9 / | | /
9288 // |/ / | 5 |/
9289 // *-------* *---*---*
9290 //
9291 // note that we have to take care of the
9292 // orientation of faces.
9293 const int quad_indices[11] = {
9294 new_quads[0]->index(), // 0
9295
9296 hex->face(0)->child_index(
9297 child_at_origin[hex->face(0)->refinement_case() -
9298 1][f_fl[0]][f_ro[0]]), // 1
9299 hex->face(0)->child_index(
9300 1 -
9301 child_at_origin[hex->face(0)->refinement_case() -
9302 1][f_fl[0]][f_ro[0]]),
9303
9304 hex->face(1)->child_index(
9305 child_at_origin[hex->face(1)->refinement_case() -
9306 1][f_fl[1]][f_ro[1]]), // 3
9307 hex->face(1)->child_index(
9308 1 -
9309 child_at_origin[hex->face(1)->refinement_case() -
9310 1][f_fl[1]][f_ro[1]]),
9311
9312 hex->face(2)->child_index(
9313 child_at_origin[hex->face(2)->refinement_case() -
9314 1][f_fl[2]][f_ro[2]]), // 5
9315 hex->face(2)->child_index(
9316 1 -
9317 child_at_origin[hex->face(2)->refinement_case() -
9318 1][f_fl[2]][f_ro[2]]),
9319
9320 hex->face(3)->child_index(
9321 child_at_origin[hex->face(3)->refinement_case() -
9322 1][f_fl[3]][f_ro[3]]), // 7
9323 hex->face(3)->child_index(
9324 1 -
9325 child_at_origin[hex->face(3)->refinement_case() -
9326 1][f_fl[3]][f_ro[3]]),
9327
9328 hex->face(4)->index(), // 9
9329
9330 hex->face(5)->index() // 10
9331 };
9332
9333 new_hexes[0]->set_bounding_object_indices(
9334 {quad_indices[1],
9335 quad_indices[3],
9336 quad_indices[5],
9337 quad_indices[7],
9338 quad_indices[9],
9339 quad_indices[0]});
9340 new_hexes[1]->set_bounding_object_indices(
9341 {quad_indices[2],
9342 quad_indices[4],
9343 quad_indices[6],
9344 quad_indices[8],
9345 quad_indices[0],
9346 quad_indices[10]});
9347 break;
9348 }
9349
9351 {
9352 //----------------------------
9353 //
9354 // RefinementCase<dim>::cut_xy
9355 //
9356 // the refined cube will look like this:
9357 //
9358 // *----*----*
9359 // / / /|
9360 // *----*----* |
9361 // / / /| |
9362 // *----*----* | |
9363 // | | | | |
9364 // | | | | *
9365 // | | | |/
9366 // | | | *
9367 // | | |/
9368 // *----*----*
9369 //
9370
9371 // first, create the new internal line
9372 new_lines[0]->set_bounding_object_indices(
9374 middle_vertex_index<dim, spacedim>(hex->face(5))});
9375
9376 // again, first collect some data about the
9377 // indices of the lines, with the following
9378 // numbering:
9379
9380 // face 0: left plane
9381 // *
9382 // /|
9383 // * |
9384 // /| |
9385 // * | |
9386 // | 0 |
9387 // | | *
9388 // | |/
9389 // | *
9390 // |/
9391 // *
9392 // face 1: right plane
9393 // *
9394 // /|
9395 // * |
9396 // /| |
9397 // * | |
9398 // | 1 |
9399 // | | *
9400 // | |/
9401 // | *
9402 // |/
9403 // *
9404 // face 2: front plane
9405 // (note: x,y exchanged)
9406 // *---*---*
9407 // | | |
9408 // | 2 |
9409 // | | |
9410 // *-------*
9411 // face 3: back plane
9412 // (note: x,y exchanged)
9413 // *---*---*
9414 // | | |
9415 // | 3 |
9416 // | | |
9417 // *---*---*
9418 // face 4: bottom plane
9419 // *---*---*
9420 // / 5 /
9421 // *-6-*-7-*
9422 // / 4 /
9423 // *---*---*
9424 // face 5: top plane
9425 // *---*---*
9426 // / 9 /
9427 // *10-*-11*
9428 // / 8 /
9429 // *---*---*
9430 // middle planes
9431 // *-------* *---*---*
9432 // / / | | |
9433 // / / | 12 |
9434 // / / | | |
9435 // *-------* *---*---*
9436
9437 // set up a list of line iterators first. from
9438 // this, construct lists of line_indices and
9439 // line orientations later on
9440 const typename Triangulation<
9441 dim,
9442 spacedim>::raw_line_iterator lines[13] = {
9443 hex->face(0)->child(0)->line(
9444 (hex->face(0)->refinement_case() ==
9446 1 :
9447 3), // 0
9448 hex->face(1)->child(0)->line(
9449 (hex->face(1)->refinement_case() ==
9451 1 :
9452 3), // 1
9453 hex->face(2)->child(0)->line(
9454 (hex->face(2)->refinement_case() ==
9456 1 :
9457 3), // 2
9458 hex->face(3)->child(0)->line(
9459 (hex->face(3)->refinement_case() ==
9461 1 :
9462 3), // 3
9463
9464 hex->face(4)
9465 ->isotropic_child(
9467 0, f_or[4], f_fl[4], f_ro[4]))
9468 ->line(
9470 1, f_or[4], f_fl[4], f_ro[4])), // 4
9471 hex->face(4)
9472 ->isotropic_child(
9474 3, f_or[4], f_fl[4], f_ro[4]))
9475 ->line(
9477 0, f_or[4], f_fl[4], f_ro[4])), // 5
9478 hex->face(4)
9479 ->isotropic_child(
9481 0, f_or[4], f_fl[4], f_ro[4]))
9482 ->line(
9484 3, f_or[4], f_fl[4], f_ro[4])), // 6
9485 hex->face(4)
9486 ->isotropic_child(
9488 3, f_or[4], f_fl[4], f_ro[4]))
9489 ->line(
9491 2, f_or[4], f_fl[4], f_ro[4])), // 7
9492
9493 hex->face(5)
9494 ->isotropic_child(
9496 0, f_or[5], f_fl[5], f_ro[5]))
9497 ->line(
9499 1, f_or[5], f_fl[5], f_ro[5])), // 8
9500 hex->face(5)
9501 ->isotropic_child(
9503 3, f_or[5], f_fl[5], f_ro[5]))
9504 ->line(
9506 0, f_or[5], f_fl[5], f_ro[5])), // 9
9507 hex->face(5)
9508 ->isotropic_child(
9510 0, f_or[5], f_fl[5], f_ro[5]))
9511 ->line(
9513 3, f_or[5], f_fl[5], f_ro[5])), // 10
9514 hex->face(5)
9515 ->isotropic_child(
9517 3, f_or[5], f_fl[5], f_ro[5]))
9518 ->line(
9520 2, f_or[5], f_fl[5], f_ro[5])), // 11
9521
9522 new_lines[0] // 12
9523 };
9524
9525 unsigned int line_indices[13];
9526 for (unsigned int i = 0; i < 13; ++i)
9527 line_indices[i] = lines[i]->index();
9528
9529 // the orientation of lines for the inner quads
9530 // is quite tricky. as these lines are newly
9531 // created ones and thus have no parents, they
9532 // cannot inherit this property. set up an array
9533 // and fill it with the respective values
9534 types::geometric_orientation line_orientation[13]{};
9535
9536 // the middle vertices of the lines of our
9537 // bottom face
9538 const unsigned int middle_vertices[4] = {
9539 hex->line(0)->child(0)->vertex_index(1),
9540 hex->line(1)->child(0)->vertex_index(1),
9541 hex->line(2)->child(0)->vertex_index(1),
9542 hex->line(3)->child(0)->vertex_index(1),
9543 };
9544
9545 // note: for lines 0 to 3 the orientation of the
9546 // line is 'true', if vertex 0 is on the bottom
9547 // face
9548 for (unsigned int i = 0; i < 4; ++i)
9549 if (lines[i]->vertex_index(0) == middle_vertices[i])
9550 line_orientation[i] =
9552 else
9553 {
9554 // it must be the other way round then
9555 Assert(lines[i]->vertex_index(1) ==
9556 middle_vertices[i],
9558 line_orientation[i] =
9560 }
9561
9562 // note: for lines 4 to 11 (inner lines of the
9563 // outer quads) the following holds: the second
9564 // vertex of the even lines in standard
9565 // orientation is the vertex in the middle of
9566 // the quad, whereas for odd lines the first
9567 // vertex is the same middle vertex.
9568 for (unsigned int i = 4; i < 12; ++i)
9569 if (lines[i]->vertex_index((i + 1) % 2) ==
9571 hex->face(3 + i / 4)))
9572 line_orientation[i] =
9574 else
9575 {
9576 // it must be the other way round then
9577 Assert(lines[i]->vertex_index(i % 2) ==
9579 hex->face(3 + i / 4))),
9581 line_orientation[i] =
9583 }
9584 // for the last line the line orientation is
9585 // always true, since it was just constructed
9586 // that way
9587 line_orientation[12] =
9589
9590 // set up the 4 quads, numbered as follows (left
9591 // quad numbering, right line numbering
9592 // extracted from above)
9593 //
9594 // * *
9595 // /| 9|
9596 // * | * |
9597 // y/| | 8| 3
9598 // * |1| * | |
9599 // | | |x | 12|
9600 // |0| * | | *
9601 // | |/ 2 |5
9602 // | * | *
9603 // |/ |4
9604 // * *
9605 //
9606 // x
9607 // *---*---* *10-*-11*
9608 // | | | | | |
9609 // | 2 | 3 | 0 12 1
9610 // | | | | | |
9611 // *---*---*y *-6-*-7-*
9612
9613 new_quads[0]->set_bounding_object_indices(
9614 {line_indices[2],
9615 line_indices[12],
9616 line_indices[4],
9617 line_indices[8]});
9618 new_quads[1]->set_bounding_object_indices(
9619 {line_indices[12],
9620 line_indices[3],
9621 line_indices[5],
9622 line_indices[9]});
9623 new_quads[2]->set_bounding_object_indices(
9624 {line_indices[6],
9625 line_indices[10],
9626 line_indices[0],
9627 line_indices[12]});
9628 new_quads[3]->set_bounding_object_indices(
9629 {line_indices[7],
9630 line_indices[11],
9631 line_indices[12],
9632 line_indices[1]});
9633
9634 new_quads[0]->set_line_orientation(
9635 0, line_orientation[2]);
9636 new_quads[0]->set_line_orientation(
9637 2, line_orientation[4]);
9638 new_quads[0]->set_line_orientation(
9639 3, line_orientation[8]);
9640
9641 new_quads[1]->set_line_orientation(
9642 1, line_orientation[3]);
9643 new_quads[1]->set_line_orientation(
9644 2, line_orientation[5]);
9645 new_quads[1]->set_line_orientation(
9646 3, line_orientation[9]);
9647
9648 new_quads[2]->set_line_orientation(
9649 0, line_orientation[6]);
9650 new_quads[2]->set_line_orientation(
9651 1, line_orientation[10]);
9652 new_quads[2]->set_line_orientation(
9653 2, line_orientation[0]);
9654
9655 new_quads[3]->set_line_orientation(
9656 0, line_orientation[7]);
9657 new_quads[3]->set_line_orientation(
9658 1, line_orientation[11]);
9659 new_quads[3]->set_line_orientation(
9660 3, line_orientation[1]);
9661
9662 // the quads are numbered as follows:
9663 //
9664 // planes in the interior of the old hex:
9665 //
9666 // *
9667 // /|
9668 // * | x
9669 // /| | *---*---* *---------*
9670 // * |1| | | | / /
9671 // | | | | 2 | 3 | / /
9672 // |0| * | | | / /
9673 // | |/ *---*---*y *---------*x
9674 // | *
9675 // |/
9676 // *
9677 //
9678 // children of the faces of the old hex
9679 //
9680 // *---*---* *---*---*
9681 // /| | | /18 / 19/|
9682 // * |10 | 11| /---/---* |
9683 // /| | | | /16 / 17/| |
9684 // * |5| | | *---*---* |7|
9685 // | | *---*---* | | | | *
9686 // |4|/14 / 15/ | | |6|/
9687 // | *---/---/ | 8 | 9 | *
9688 // |/12 / 13/ | | |/
9689 // *---*---* *---*---*
9690 //
9691 // note that we have to take care of the
9692 // orientation of faces.
9693 const int quad_indices[20] = {
9694 new_quads[0]->index(), // 0
9695 new_quads[1]->index(),
9696 new_quads[2]->index(),
9697 new_quads[3]->index(),
9698
9699 hex->face(0)->child_index(
9700 child_at_origin[hex->face(0)->refinement_case() -
9701 1][f_fl[0]][f_ro[0]]), // 4
9702 hex->face(0)->child_index(
9703 1 -
9704 child_at_origin[hex->face(0)->refinement_case() -
9705 1][f_fl[0]][f_ro[0]]),
9706
9707 hex->face(1)->child_index(
9708 child_at_origin[hex->face(1)->refinement_case() -
9709 1][f_fl[1]][f_ro[1]]), // 6
9710 hex->face(1)->child_index(
9711 1 -
9712 child_at_origin[hex->face(1)->refinement_case() -
9713 1][f_fl[1]][f_ro[1]]),
9714
9715 hex->face(2)->child_index(
9716 child_at_origin[hex->face(2)->refinement_case() -
9717 1][f_fl[2]][f_ro[2]]), // 8
9718 hex->face(2)->child_index(
9719 1 -
9720 child_at_origin[hex->face(2)->refinement_case() -
9721 1][f_fl[2]][f_ro[2]]),
9722
9723 hex->face(3)->child_index(
9724 child_at_origin[hex->face(3)->refinement_case() -
9725 1][f_fl[3]][f_ro[3]]), // 10
9726 hex->face(3)->child_index(
9727 1 -
9728 child_at_origin[hex->face(3)->refinement_case() -
9729 1][f_fl[3]][f_ro[3]]),
9730
9731 hex->face(4)->isotropic_child_index(
9733 0, f_or[4], f_fl[4], f_ro[4])), // 12
9734 hex->face(4)->isotropic_child_index(
9736 1, f_or[4], f_fl[4], f_ro[4])),
9737 hex->face(4)->isotropic_child_index(
9739 2, f_or[4], f_fl[4], f_ro[4])),
9740 hex->face(4)->isotropic_child_index(
9742 3, f_or[4], f_fl[4], f_ro[4])),
9743
9744 hex->face(5)->isotropic_child_index(
9746 0, f_or[5], f_fl[5], f_ro[5])), // 16
9747 hex->face(5)->isotropic_child_index(
9749 1, f_or[5], f_fl[5], f_ro[5])),
9750 hex->face(5)->isotropic_child_index(
9752 2, f_or[5], f_fl[5], f_ro[5])),
9753 hex->face(5)->isotropic_child_index(
9755 3, f_or[5], f_fl[5], f_ro[5]))};
9756
9757 new_hexes[0]->set_bounding_object_indices(
9758 {quad_indices[4],
9759 quad_indices[0],
9760 quad_indices[8],
9761 quad_indices[2],
9762 quad_indices[12],
9763 quad_indices[16]});
9764 new_hexes[1]->set_bounding_object_indices(
9765 {quad_indices[0],
9766 quad_indices[6],
9767 quad_indices[9],
9768 quad_indices[3],
9769 quad_indices[13],
9770 quad_indices[17]});
9771 new_hexes[2]->set_bounding_object_indices(
9772 {quad_indices[5],
9773 quad_indices[1],
9774 quad_indices[2],
9775 quad_indices[10],
9776 quad_indices[14],
9777 quad_indices[18]});
9778 new_hexes[3]->set_bounding_object_indices(
9779 {quad_indices[1],
9780 quad_indices[7],
9781 quad_indices[3],
9782 quad_indices[11],
9783 quad_indices[15],
9784 quad_indices[19]});
9785 break;
9786 }
9787
9789 {
9790 //----------------------------
9791 //
9792 // RefinementCase<dim>::cut_xz
9793 //
9794 // the refined cube will look like this:
9795 //
9796 // *----*----*
9797 // / / /|
9798 // / / / |
9799 // / / / *
9800 // *----*----* /|
9801 // | | | / |
9802 // | | |/ *
9803 // *----*----* /
9804 // | | | /
9805 // | | |/
9806 // *----*----*
9807 //
9808
9809 // first, create the new internal line
9810 new_lines[0]->set_bounding_object_indices(
9812 middle_vertex_index<dim, spacedim>(hex->face(3))});
9813
9814 // again, first collect some data about the
9815 // indices of the lines, with the following
9816 // numbering:
9817
9818 // face 0: left plane
9819 // *
9820 // /|
9821 // / |
9822 // / *
9823 // * /|
9824 // | 0 |
9825 // |/ *
9826 // * /
9827 // | /
9828 // |/
9829 // *
9830 // face 1: right plane
9831 // *
9832 // /|
9833 // / |
9834 // / *
9835 // * /|
9836 // | 1 |
9837 // |/ *
9838 // * /
9839 // | /
9840 // |/
9841 // *
9842 // face 2: front plane
9843 // (note: x,y exchanged)
9844 // *---*---*
9845 // | 5 |
9846 // *-6-*-7-*
9847 // | 4 |
9848 // *---*---*
9849 // face 3: back plane
9850 // (note: x,y exchanged)
9851 // *---*---*
9852 // | 9 |
9853 // *10-*-11*
9854 // | 8 |
9855 // *---*---*
9856 // face 4: bottom plane
9857 // *---*---*
9858 // / / /
9859 // / 2 /
9860 // / / /
9861 // *---*---*
9862 // face 5: top plane
9863 // *---*---*
9864 // / / /
9865 // / 3 /
9866 // / / /
9867 // *---*---*
9868 // middle planes
9869 // *---*---* *-------*
9870 // / / / | |
9871 // / 12 / | |
9872 // / / / | |
9873 // *---*---* *-------*
9874
9875 // set up a list of line iterators first. from
9876 // this, construct lists of line_indices and
9877 // line orientations later on
9878 const typename Triangulation<
9879 dim,
9880 spacedim>::raw_line_iterator lines[13] = {
9881 hex->face(0)->child(0)->line(
9882 (hex->face(0)->refinement_case() ==
9884 1 :
9885 3), // 0
9886 hex->face(1)->child(0)->line(
9887 (hex->face(1)->refinement_case() ==
9889 1 :
9890 3), // 1
9891 hex->face(4)->child(0)->line(
9892 (hex->face(4)->refinement_case() ==
9894 1 :
9895 3), // 2
9896 hex->face(5)->child(0)->line(
9897 (hex->face(5)->refinement_case() ==
9899 1 :
9900 3), // 3
9901
9902 hex->face(2)
9903 ->isotropic_child(
9905 0, f_or[2], f_fl[2], f_ro[2]))
9906 ->line(
9908 3, f_or[2], f_fl[2], f_ro[2])), // 4
9909 hex->face(2)
9910 ->isotropic_child(
9912 3, f_or[2], f_fl[2], f_ro[2]))
9913 ->line(
9915 2, f_or[2], f_fl[2], f_ro[2])), // 5
9916 hex->face(2)
9917 ->isotropic_child(
9919 0, f_or[2], f_fl[2], f_ro[2]))
9920 ->line(
9922 1, f_or[2], f_fl[2], f_ro[2])), // 6
9923 hex->face(2)
9924 ->isotropic_child(
9926 3, f_or[2], f_fl[2], f_ro[2]))
9927 ->line(
9929 0, f_or[2], f_fl[2], f_ro[2])), // 7
9930
9931 hex->face(3)
9932 ->isotropic_child(
9934 0, f_or[3], f_fl[3], f_ro[3]))
9935 ->line(
9937 3, f_or[3], f_fl[3], f_ro[3])), // 8
9938 hex->face(3)
9939 ->isotropic_child(
9941 3, f_or[3], f_fl[3], f_ro[3]))
9942 ->line(
9944 2, f_or[3], f_fl[3], f_ro[3])), // 9
9945 hex->face(3)
9946 ->isotropic_child(
9948 0, f_or[3], f_fl[3], f_ro[3]))
9949 ->line(
9951 1, f_or[3], f_fl[3], f_ro[3])), // 10
9952 hex->face(3)
9953 ->isotropic_child(
9955 3, f_or[3], f_fl[3], f_ro[3]))
9956 ->line(
9958 0, f_or[3], f_fl[3], f_ro[3])), // 11
9959
9960 new_lines[0] // 12
9961 };
9962
9963 unsigned int line_indices[13];
9964 for (unsigned int i = 0; i < 13; ++i)
9965 line_indices[i] = lines[i]->index();
9966
9967 // the orientation of lines for the inner quads
9968 // is quite tricky. as these lines are newly
9969 // created ones and thus have no parents, they
9970 // cannot inherit this property. set up an array
9971 // and fill it with the respective values
9972 types::geometric_orientation line_orientation[13]{};
9973
9974 // the middle vertices of the
9975 // lines of our front face
9976 const unsigned int middle_vertices[4] = {
9977 hex->line(8)->child(0)->vertex_index(1),
9978 hex->line(9)->child(0)->vertex_index(1),
9979 hex->line(2)->child(0)->vertex_index(1),
9980 hex->line(6)->child(0)->vertex_index(1),
9981 };
9982
9983 // note: for lines 0 to 3 the orientation of the
9984 // line is 'true', if vertex 0 is on the front
9985 for (unsigned int i = 0; i < 4; ++i)
9986 if (lines[i]->vertex_index(0) == middle_vertices[i])
9987 line_orientation[i] =
9989 else
9990 {
9991 // it must be the other way round then
9992 Assert(lines[i]->vertex_index(1) ==
9993 middle_vertices[i],
9995 line_orientation[i] =
9997 }
9998
9999 // note: for lines 4 to 11 (inner lines of the
10000 // outer quads) the following holds: the second
10001 // vertex of the even lines in standard
10002 // orientation is the vertex in the middle of
10003 // the quad, whereas for odd lines the first
10004 // vertex is the same middle vertex.
10005 for (unsigned int i = 4; i < 12; ++i)
10006 if (lines[i]->vertex_index((i + 1) % 2) ==
10008 hex->face(1 + i / 4)))
10009 line_orientation[i] =
10011 else
10012 {
10013 // it must be the other way
10014 // round then
10015 Assert(lines[i]->vertex_index(i % 2) ==
10017 hex->face(1 + i / 4))),
10019 line_orientation[i] =
10021 }
10022 // for the last line the line orientation is
10023 // always true, since it was just constructed
10024 // that way
10025 line_orientation[12] =
10027
10028 // set up the 4 quads, numbered as follows (left
10029 // quad numbering, right line numbering
10030 // extracted from above), the drawings denote
10031 // middle planes
10032 //
10033 // * *
10034 // /| /|
10035 // / | 3 9
10036 // y/ * / *
10037 // * 3/| * /|
10038 // | / |x 5 12|8
10039 // |/ * |/ *
10040 // * 2/ * /
10041 // | / 4 2
10042 // |/ |/
10043 // * *
10044 //
10045 // y
10046 // *----*----* *-10-*-11-*
10047 // / / / / / /
10048 // / 0 / 1 / 0 12 1
10049 // / / / / / /
10050 // *----*----*x *--6-*--7-*
10051
10052 new_quads[0]->set_bounding_object_indices(
10053 {line_indices[0],
10054 line_indices[12],
10055 line_indices[6],
10056 line_indices[10]});
10057 new_quads[1]->set_bounding_object_indices(
10058 {line_indices[12],
10059 line_indices[1],
10060 line_indices[7],
10061 line_indices[11]});
10062 new_quads[2]->set_bounding_object_indices(
10063 {line_indices[4],
10064 line_indices[8],
10065 line_indices[2],
10066 line_indices[12]});
10067 new_quads[3]->set_bounding_object_indices(
10068 {line_indices[5],
10069 line_indices[9],
10070 line_indices[12],
10071 line_indices[3]});
10072
10073 new_quads[0]->set_line_orientation(
10074 0, line_orientation[0]);
10075 new_quads[0]->set_line_orientation(
10076 2, line_orientation[6]);
10077 new_quads[0]->set_line_orientation(
10078 3, line_orientation[10]);
10079
10080 new_quads[1]->set_line_orientation(
10081 1, line_orientation[1]);
10082 new_quads[1]->set_line_orientation(
10083 2, line_orientation[7]);
10084 new_quads[1]->set_line_orientation(
10085 3, line_orientation[11]);
10086
10087 new_quads[2]->set_line_orientation(
10088 0, line_orientation[4]);
10089 new_quads[2]->set_line_orientation(
10090 1, line_orientation[8]);
10091 new_quads[2]->set_line_orientation(
10092 2, line_orientation[2]);
10093
10094 new_quads[3]->set_line_orientation(
10095 0, line_orientation[5]);
10096 new_quads[3]->set_line_orientation(
10097 1, line_orientation[9]);
10098 new_quads[3]->set_line_orientation(
10099 3, line_orientation[3]);
10100
10101 // the quads are numbered as follows:
10102 //
10103 // planes in the interior of the old hex:
10104 //
10105 // *
10106 // /|
10107 // / | x
10108 // /3 * *-------* *----*----*
10109 // * /| | | / / /
10110 // | / | | | / 0 / 1 /
10111 // |/ * | | / / /
10112 // * 2/ *-------*y *----*----*x
10113 // | /
10114 // |/
10115 // *
10116 //
10117 // children of the faces
10118 // of the old hex
10119 // *---*---* *---*---*
10120 // /|13 | 15| / / /|
10121 // / | | | /18 / 19/ |
10122 // / *---*---* / / / *
10123 // * 5/| | | *---*---* 7/|
10124 // | / |12 | 14| | 9 | 11| / |
10125 // |/4 *---*---* | | |/6 *
10126 // * / / / *---*---* /
10127 // | /16 / 17/ | | | /
10128 // |/ / / | 8 | 10|/
10129 // *---*---* *---*---*
10130 //
10131 // note that we have to take care of the
10132 // orientation of faces.
10133 const int quad_indices[20] = {
10134 new_quads[0]->index(), // 0
10135 new_quads[1]->index(),
10136 new_quads[2]->index(),
10137 new_quads[3]->index(),
10138
10139 hex->face(0)->child_index(
10140 child_at_origin[hex->face(0)->refinement_case() -
10141 1][f_fl[0]][f_ro[0]]), // 4
10142 hex->face(0)->child_index(
10143 1 -
10144 child_at_origin[hex->face(0)->refinement_case() -
10145 1][f_fl[0]][f_ro[0]]),
10146
10147 hex->face(1)->child_index(
10148 child_at_origin[hex->face(1)->refinement_case() -
10149 1][f_fl[1]][f_ro[1]]), // 6
10150 hex->face(1)->child_index(
10151 1 -
10152 child_at_origin[hex->face(1)->refinement_case() -
10153 1][f_fl[1]][f_ro[1]]),
10154
10155 hex->face(2)->isotropic_child_index(
10157 0, f_or[2], f_fl[2], f_ro[2])), // 8
10158 hex->face(2)->isotropic_child_index(
10160 1, f_or[2], f_fl[2], f_ro[2])),
10161 hex->face(2)->isotropic_child_index(
10163 2, f_or[2], f_fl[2], f_ro[2])),
10164 hex->face(2)->isotropic_child_index(
10166 3, f_or[2], f_fl[2], f_ro[2])),
10167
10168 hex->face(3)->isotropic_child_index(
10170 0, f_or[3], f_fl[3], f_ro[3])), // 12
10171 hex->face(3)->isotropic_child_index(
10173 1, f_or[3], f_fl[3], f_ro[3])),
10174 hex->face(3)->isotropic_child_index(
10176 2, f_or[3], f_fl[3], f_ro[3])),
10177 hex->face(3)->isotropic_child_index(
10179 3, f_or[3], f_fl[3], f_ro[3])),
10180
10181 hex->face(4)->child_index(
10182 child_at_origin[hex->face(4)->refinement_case() -
10183 1][f_fl[4]][f_ro[4]]), // 16
10184 hex->face(4)->child_index(
10185 1 -
10186 child_at_origin[hex->face(4)->refinement_case() -
10187 1][f_fl[4]][f_ro[4]]),
10188
10189 hex->face(5)->child_index(
10190 child_at_origin[hex->face(5)->refinement_case() -
10191 1][f_fl[5]][f_ro[5]]), // 18
10192 hex->face(5)->child_index(
10193 1 -
10194 child_at_origin[hex->face(5)->refinement_case() -
10195 1][f_fl[5]][f_ro[5]])};
10196
10197 // due to the exchange of x and y for the front
10198 // and back face, we order the children
10199 // according to
10200 //
10201 // *---*---*
10202 // | 1 | 3 |
10203 // *---*---*
10204 // | 0 | 2 |
10205 // *---*---*
10206 new_hexes[0]->set_bounding_object_indices(
10207 {quad_indices[4],
10208 quad_indices[2],
10209 quad_indices[8],
10210 quad_indices[12],
10211 quad_indices[16],
10212 quad_indices[0]});
10213 new_hexes[1]->set_bounding_object_indices(
10214 {quad_indices[5],
10215 quad_indices[3],
10216 quad_indices[9],
10217 quad_indices[13],
10218 quad_indices[0],
10219 quad_indices[18]});
10220 new_hexes[2]->set_bounding_object_indices(
10221 {quad_indices[2],
10222 quad_indices[6],
10223 quad_indices[10],
10224 quad_indices[14],
10225 quad_indices[17],
10226 quad_indices[1]});
10227 new_hexes[3]->set_bounding_object_indices(
10228 {quad_indices[3],
10229 quad_indices[7],
10230 quad_indices[11],
10231 quad_indices[15],
10232 quad_indices[1],
10233 quad_indices[19]});
10234 break;
10235 }
10236
10238 {
10239 //----------------------------
10240 //
10241 // RefinementCase<dim>::cut_yz
10242 //
10243 // the refined cube will look like this:
10244 //
10245 // *---------*
10246 // / /|
10247 // *---------* |
10248 // / /| |
10249 // *---------* |/|
10250 // | | * |
10251 // | |/| *
10252 // *---------* |/
10253 // | | *
10254 // | |/
10255 // *---------*
10256 //
10257
10258 // first, create the new
10259 // internal line
10260 new_lines[0]->set_bounding_object_indices(
10261
10263 middle_vertex_index<dim, spacedim>(hex->face(1))});
10264
10265 // again, first collect some data about the
10266 // indices of the lines, with the following
10267 // numbering: (note that face 0 and 1 each are
10268 // shown twice for better readability)
10269
10270 // face 0: left plane
10271 // * *
10272 // /| /|
10273 // * | * |
10274 // /| * /| *
10275 // * 5/| * |7|
10276 // | * | | * |
10277 // |/| * |6| *
10278 // * 4/ * |/
10279 // | * | *
10280 // |/ |/
10281 // * *
10282 // face 1: right plane
10283 // * *
10284 // /| /|
10285 // * | * |
10286 // /| * /| *
10287 // * 9/| * |11
10288 // | * | | * |
10289 // |/| * |10 *
10290 // * 8/ * |/
10291 // | * | *
10292 // |/ |/
10293 // * *
10294 // face 2: front plane
10295 // (note: x,y exchanged)
10296 // *-------*
10297 // | |
10298 // *---0---*
10299 // | |
10300 // *-------*
10301 // face 3: back plane
10302 // (note: x,y exchanged)
10303 // *-------*
10304 // | |
10305 // *---1---*
10306 // | |
10307 // *-------*
10308 // face 4: bottom plane
10309 // *-------*
10310 // / /
10311 // *---2---*
10312 // / /
10313 // *-------*
10314 // face 5: top plane
10315 // *-------*
10316 // / /
10317 // *---3---*
10318 // / /
10319 // *-------*
10320 // middle planes
10321 // *-------* *-------*
10322 // / / | |
10323 // *---12--* | |
10324 // / / | |
10325 // *-------* *-------*
10326
10327 // set up a list of line iterators first. from
10328 // this, construct lists of line_indices and
10329 // line orientations later on
10330 const typename Triangulation<
10331 dim,
10332 spacedim>::raw_line_iterator lines[13] = {
10333 hex->face(2)->child(0)->line(
10334 (hex->face(2)->refinement_case() ==
10336 1 :
10337 3), // 0
10338 hex->face(3)->child(0)->line(
10339 (hex->face(3)->refinement_case() ==
10341 1 :
10342 3), // 1
10343 hex->face(4)->child(0)->line(
10344 (hex->face(4)->refinement_case() ==
10346 1 :
10347 3), // 2
10348 hex->face(5)->child(0)->line(
10349 (hex->face(5)->refinement_case() ==
10351 1 :
10352 3), // 3
10353
10354 hex->face(0)
10355 ->isotropic_child(
10357 0, f_or[0], f_fl[0], f_ro[0]))
10358 ->line(
10360 1, f_or[0], f_fl[0], f_ro[0])), // 4
10361 hex->face(0)
10362 ->isotropic_child(
10364 3, f_or[0], f_fl[0], f_ro[0]))
10365 ->line(
10367 0, f_or[0], f_fl[0], f_ro[0])), // 5
10368 hex->face(0)
10369 ->isotropic_child(
10371 0, f_or[0], f_fl[0], f_ro[0]))
10372 ->line(
10374 3, f_or[0], f_fl[0], f_ro[0])), // 6
10375 hex->face(0)
10376 ->isotropic_child(
10378 3, f_or[0], f_fl[0], f_ro[0]))
10379 ->line(
10381 2, f_or[0], f_fl[0], f_ro[0])), // 7
10382
10383 hex->face(1)
10384 ->isotropic_child(
10386 0, f_or[1], f_fl[1], f_ro[1]))
10387 ->line(
10389 1, f_or[1], f_fl[1], f_ro[1])), // 8
10390 hex->face(1)
10391 ->isotropic_child(
10393 3, f_or[1], f_fl[1], f_ro[1]))
10394 ->line(
10396 0, f_or[1], f_fl[1], f_ro[1])), // 9
10397 hex->face(1)
10398 ->isotropic_child(
10400 0, f_or[1], f_fl[1], f_ro[1]))
10401 ->line(
10403 3, f_or[1], f_fl[1], f_ro[1])), // 10
10404 hex->face(1)
10405 ->isotropic_child(
10407 3, f_or[1], f_fl[1], f_ro[1]))
10408 ->line(
10410 2, f_or[1], f_fl[1], f_ro[1])), // 11
10411
10412 new_lines[0] // 12
10413 };
10414
10415 unsigned int line_indices[13];
10416
10417 for (unsigned int i = 0; i < 13; ++i)
10418 line_indices[i] = lines[i]->index();
10419
10420 // the orientation of lines for the inner quads
10421 // is quite tricky. as these lines are newly
10422 // created ones and thus have no parents, they
10423 // cannot inherit this property. set up an array
10424 // and fill it with the respective values
10425 types::geometric_orientation line_orientation[13]{};
10426
10427 // the middle vertices of the lines of our front
10428 // face
10429 const unsigned int middle_vertices[4] = {
10430 hex->line(8)->child(0)->vertex_index(1),
10431 hex->line(10)->child(0)->vertex_index(1),
10432 hex->line(0)->child(0)->vertex_index(1),
10433 hex->line(4)->child(0)->vertex_index(1),
10434 };
10435
10436 // note: for lines 0 to 3 the orientation of the
10437 // line is 'true', if vertex 0 is on the front
10438 for (unsigned int i = 0; i < 4; ++i)
10439 if (lines[i]->vertex_index(0) == middle_vertices[i])
10440 line_orientation[i] =
10442 else
10443 {
10444 // it must be the other way round then
10445 Assert(lines[i]->vertex_index(1) ==
10446 middle_vertices[i],
10448 line_orientation[i] =
10450 }
10451
10452 // note: for lines 4 to 11 (inner lines of the
10453 // outer quads) the following holds: the second
10454 // vertex of the even lines in standard
10455 // orientation is the vertex in the middle of
10456 // the quad, whereas for odd lines the first
10457 // vertex is the same middle vertex.
10458 for (unsigned int i = 4; i < 12; ++i)
10459 if (lines[i]->vertex_index((i + 1) % 2) ==
10461 hex->face(i / 4 - 1)))
10462 line_orientation[i] =
10464 else
10465 {
10466 // it must be the other way round then
10467 Assert(lines[i]->vertex_index(i % 2) ==
10469 hex->face(i / 4 - 1))),
10471 line_orientation[i] =
10473 }
10474 // for the last line the line orientation is always
10475 // the default, since it was just constructed that way
10476 line_orientation[12] =
10478
10479 // set up the 4 quads, numbered as follows (left
10480 // quad numbering, right line numbering
10481 // extracted from above)
10482 //
10483 // x
10484 // *-------* *---3---*
10485 // | 3 | 5 9
10486 // *-------* *---12--*
10487 // | 2 | 4 8
10488 // *-------*y *---2---*
10489 //
10490 // y
10491 // *---------* *----1----*
10492 // / 1 / 7 11
10493 // *---------* *----12---*
10494 // / 0 / 6 10
10495 // *---------*x *----0----*
10496
10497 new_quads[0]->set_bounding_object_indices(
10498 {line_indices[6],
10499 line_indices[10],
10500 line_indices[0],
10501 line_indices[12]});
10502 new_quads[1]->set_bounding_object_indices(
10503 {line_indices[7],
10504 line_indices[11],
10505 line_indices[12],
10506 line_indices[1]});
10507 new_quads[2]->set_bounding_object_indices(
10508 {line_indices[2],
10509 line_indices[12],
10510 line_indices[4],
10511 line_indices[8]});
10512 new_quads[3]->set_bounding_object_indices(
10513 {line_indices[12],
10514 line_indices[3],
10515 line_indices[5],
10516 line_indices[9]});
10517
10518 new_quads[0]->set_line_orientation(
10519 0, line_orientation[6]);
10520 new_quads[0]->set_line_orientation(
10521 1, line_orientation[10]);
10522 new_quads[0]->set_line_orientation(
10523 2, line_orientation[0]);
10524
10525 new_quads[1]->set_line_orientation(
10526 0, line_orientation[7]);
10527 new_quads[1]->set_line_orientation(
10528 1, line_orientation[11]);
10529 new_quads[1]->set_line_orientation(
10530 3, line_orientation[1]);
10531
10532 new_quads[2]->set_line_orientation(
10533 0, line_orientation[2]);
10534 new_quads[2]->set_line_orientation(
10535 2, line_orientation[4]);
10536 new_quads[2]->set_line_orientation(
10537 3, line_orientation[8]);
10538
10539 new_quads[3]->set_line_orientation(
10540 1, line_orientation[3]);
10541 new_quads[3]->set_line_orientation(
10542 2, line_orientation[5]);
10543 new_quads[3]->set_line_orientation(
10544 3, line_orientation[9]);
10545
10546 // the quads are numbered as follows:
10547 //
10548 // planes in the interior of the old hex:
10549 //
10550 // *
10551 // /|
10552 // / | x
10553 // / | *-------* *---------*
10554 // * | | 3 | / 1 /
10555 // | | *-------* *---------*
10556 // | * | 2 | / 0 /
10557 // | / *-------*y *---------*x
10558 // | /
10559 // |/
10560 // *
10561 //
10562 // children of the faces
10563 // of the old hex
10564 // *-------* *-------*
10565 // /| | / 19 /|
10566 // * | 15 | *-------* |
10567 // /|7*-------* / 18 /|11
10568 // * |/| | *-------* |/|
10569 // |6* | 14 | | 10* |
10570 // |/|5*-------* | 13 |/|9*
10571 // * |/ 17 / *-------* |/
10572 // |4*-------* | |8*
10573 // |/ 16 / | 12 |/
10574 // *-------* *-------*
10575 //
10576 // note that we have to take care of the
10577 // orientation of faces.
10578 const int quad_indices[20] = {
10579 new_quads[0]->index(), // 0
10580 new_quads[1]->index(),
10581 new_quads[2]->index(),
10582 new_quads[3]->index(),
10583
10584 hex->face(0)->isotropic_child_index(
10586 0, f_or[0], f_fl[0], f_ro[0])), // 4
10587 hex->face(0)->isotropic_child_index(
10589 1, f_or[0], f_fl[0], f_ro[0])),
10590 hex->face(0)->isotropic_child_index(
10592 2, f_or[0], f_fl[0], f_ro[0])),
10593 hex->face(0)->isotropic_child_index(
10595 3, f_or[0], f_fl[0], f_ro[0])),
10596
10597 hex->face(1)->isotropic_child_index(
10599 0, f_or[1], f_fl[1], f_ro[1])), // 8
10600 hex->face(1)->isotropic_child_index(
10602 1, f_or[1], f_fl[1], f_ro[1])),
10603 hex->face(1)->isotropic_child_index(
10605 2, f_or[1], f_fl[1], f_ro[1])),
10606 hex->face(1)->isotropic_child_index(
10608 3, f_or[1], f_fl[1], f_ro[1])),
10609
10610 hex->face(2)->child_index(
10611 child_at_origin[hex->face(2)->refinement_case() -
10612 1][f_fl[2]][f_ro[2]]), // 12
10613 hex->face(2)->child_index(
10614 1 -
10615 child_at_origin[hex->face(2)->refinement_case() -
10616 1][f_fl[2]][f_ro[2]]),
10617
10618 hex->face(3)->child_index(
10619 child_at_origin[hex->face(3)->refinement_case() -
10620 1][f_fl[3]][f_ro[3]]), // 14
10621 hex->face(3)->child_index(
10622 1 -
10623 child_at_origin[hex->face(3)->refinement_case() -
10624 1][f_fl[3]][f_ro[3]]),
10625
10626 hex->face(4)->child_index(
10627 child_at_origin[hex->face(4)->refinement_case() -
10628 1][f_fl[4]][f_ro[4]]), // 16
10629 hex->face(4)->child_index(
10630 1 -
10631 child_at_origin[hex->face(4)->refinement_case() -
10632 1][f_fl[4]][f_ro[4]]),
10633
10634 hex->face(5)->child_index(
10635 child_at_origin[hex->face(5)->refinement_case() -
10636 1][f_fl[5]][f_ro[5]]), // 18
10637 hex->face(5)->child_index(
10638 1 -
10639 child_at_origin[hex->face(5)->refinement_case() -
10640 1][f_fl[5]][f_ro[5]])};
10641
10642 new_hexes[0]->set_bounding_object_indices(
10643 {quad_indices[4],
10644 quad_indices[8],
10645 quad_indices[12],
10646 quad_indices[2],
10647 quad_indices[16],
10648 quad_indices[0]});
10649 new_hexes[1]->set_bounding_object_indices(
10650 {quad_indices[5],
10651 quad_indices[9],
10652 quad_indices[2],
10653 quad_indices[14],
10654 quad_indices[17],
10655 quad_indices[1]});
10656 new_hexes[2]->set_bounding_object_indices(
10657 {quad_indices[6],
10658 quad_indices[10],
10659 quad_indices[13],
10660 quad_indices[3],
10661 quad_indices[0],
10662 quad_indices[18]});
10663 new_hexes[3]->set_bounding_object_indices(
10664 {quad_indices[7],
10665 quad_indices[11],
10666 quad_indices[3],
10667 quad_indices[15],
10668 quad_indices[1],
10669 quad_indices[19]});
10670 break;
10671 }
10672
10674 {
10675 //----------------------------
10676 //
10677 // RefinementCase<dim>::cut_xyz
10678 // isotropic refinement
10679 //
10680 // the refined cube will look
10681 // like this:
10682 //
10683 // *----*----*
10684 // / / /|
10685 // *----*----* |
10686 // / / /| *
10687 // *----*----* |/|
10688 // | | | * |
10689 // | | |/| *
10690 // *----*----* |/
10691 // | | | *
10692 // | | |/
10693 // *----*----*
10694 //
10695
10696 // find the next unused vertex and set it
10697 // appropriately
10698 while (
10699 triangulation.vertices_used[next_unused_vertex] ==
10700 true)
10702 Assert(
10703 next_unused_vertex < triangulation.vertices.size(),
10704 ExcMessage(
10705 "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."));
10706 triangulation.vertices_used[next_unused_vertex] =
10707 true;
10708
10709 // the new vertex is definitely in the interior,
10710 // so we need not worry about the
10711 // boundary. However we need to worry about
10712 // Manifolds. Let the cell compute its own
10713 // center, by querying the underlying manifold
10714 // object.
10716 hex->center(true, true);
10717
10718 // set the data of the six lines. first collect
10719 // the indices of the seven vertices (consider
10720 // the two planes to be crossed to form the
10721 // planes cutting the hex in two vertically and
10722 // horizontally)
10723 //
10724 // *--3--* *--5--*
10725 // / / / | | |
10726 // 0--6--1 0--6--1
10727 // / / / | | |
10728 // *--2--* *--4--*
10729 // the lines are numbered
10730 // as follows:
10731 // *--*--* *--*--*
10732 // / 1 / | 5 |
10733 // *2-*-3* *2-*-3*
10734 // / 0 / | 4 |
10735 // *--*--* *--*--*
10736 //
10737 const unsigned int vertex_indices[7] = {
10745
10746 new_lines[0]->set_bounding_object_indices(
10748 new_lines[1]->set_bounding_object_indices(
10750 new_lines[2]->set_bounding_object_indices(
10752 new_lines[3]->set_bounding_object_indices(
10754 new_lines[4]->set_bounding_object_indices(
10756 new_lines[5]->set_bounding_object_indices(
10758
10759 // again, first collect some data about the
10760 // indices of the lines, with the following
10761 // numbering: (note that face 0 and 1 each are
10762 // shown twice for better readability)
10763
10764 // face 0: left plane
10765 // * *
10766 // /| /|
10767 // * | * |
10768 // /| * /| *
10769 // * 1/| * |3|
10770 // | * | | * |
10771 // |/| * |2| *
10772 // * 0/ * |/
10773 // | * | *
10774 // |/ |/
10775 // * *
10776 // face 1: right plane
10777 // * *
10778 // /| /|
10779 // * | * |
10780 // /| * /| *
10781 // * 5/| * |7|
10782 // | * | | * |
10783 // |/| * |6| *
10784 // * 4/ * |/
10785 // | * | *
10786 // |/ |/
10787 // * *
10788 // face 2: front plane
10789 // (note: x,y exchanged)
10790 // *---*---*
10791 // | 11 |
10792 // *-8-*-9-*
10793 // | 10 |
10794 // *---*---*
10795 // face 3: back plane
10796 // (note: x,y exchanged)
10797 // *---*---*
10798 // | 15 |
10799 // *12-*-13*
10800 // | 14 |
10801 // *---*---*
10802 // face 4: bottom plane
10803 // *---*---*
10804 // / 17 /
10805 // *18-*-19*
10806 // / 16 /
10807 // *---*---*
10808 // face 5: top plane
10809 // *---*---*
10810 // / 21 /
10811 // *22-*-23*
10812 // / 20 /
10813 // *---*---*
10814 // middle planes
10815 // *---*---* *---*---*
10816 // / 25 / | 29 |
10817 // *26-*-27* *26-*-27*
10818 // / 24 / | 28 |
10819 // *---*---* *---*---*
10820
10821 // set up a list of line iterators first. from
10822 // this, construct lists of line_indices and
10823 // line orientations later on
10824 const typename Triangulation<
10825 dim,
10826 spacedim>::raw_line_iterator lines[30] = {
10827 hex->face(0)
10828 ->isotropic_child(
10830 0, f_or[0], f_fl[0], f_ro[0]))
10831 ->line(
10833 1, f_or[0], f_fl[0], f_ro[0])), // 0
10834 hex->face(0)
10835 ->isotropic_child(
10837 3, f_or[0], f_fl[0], f_ro[0]))
10838 ->line(
10840 0, f_or[0], f_fl[0], f_ro[0])), // 1
10841 hex->face(0)
10842 ->isotropic_child(
10844 0, f_or[0], f_fl[0], f_ro[0]))
10845 ->line(
10847 3, f_or[0], f_fl[0], f_ro[0])), // 2
10848 hex->face(0)
10849 ->isotropic_child(
10851 3, f_or[0], f_fl[0], f_ro[0]))
10852 ->line(
10854 2, f_or[0], f_fl[0], f_ro[0])), // 3
10855
10856 hex->face(1)
10857 ->isotropic_child(
10859 0, f_or[1], f_fl[1], f_ro[1]))
10860 ->line(
10862 1, f_or[1], f_fl[1], f_ro[1])), // 4
10863 hex->face(1)
10864 ->isotropic_child(
10866 3, f_or[1], f_fl[1], f_ro[1]))
10867 ->line(
10869 0, f_or[1], f_fl[1], f_ro[1])), // 5
10870 hex->face(1)
10871 ->isotropic_child(
10873 0, f_or[1], f_fl[1], f_ro[1]))
10874 ->line(
10876 3, f_or[1], f_fl[1], f_ro[1])), // 6
10877 hex->face(1)
10878 ->isotropic_child(
10880 3, f_or[1], f_fl[1], f_ro[1]))
10881 ->line(
10883 2, f_or[1], f_fl[1], f_ro[1])), // 7
10884
10885 hex->face(2)
10886 ->isotropic_child(
10888 0, f_or[2], f_fl[2], f_ro[2]))
10889 ->line(
10891 1, f_or[2], f_fl[2], f_ro[2])), // 8
10892 hex->face(2)
10893 ->isotropic_child(
10895 3, f_or[2], f_fl[2], f_ro[2]))
10896 ->line(
10898 0, f_or[2], f_fl[2], f_ro[2])), // 9
10899 hex->face(2)
10900 ->isotropic_child(
10902 0, f_or[2], f_fl[2], f_ro[2]))
10903 ->line(
10905 3, f_or[2], f_fl[2], f_ro[2])), // 10
10906 hex->face(2)
10907 ->isotropic_child(
10909 3, f_or[2], f_fl[2], f_ro[2]))
10910 ->line(
10912 2, f_or[2], f_fl[2], f_ro[2])), // 11
10913
10914 hex->face(3)
10915 ->isotropic_child(
10917 0, f_or[3], f_fl[3], f_ro[3]))
10918 ->line(
10920 1, f_or[3], f_fl[3], f_ro[3])), // 12
10921 hex->face(3)
10922 ->isotropic_child(
10924 3, f_or[3], f_fl[3], f_ro[3]))
10925 ->line(
10927 0, f_or[3], f_fl[3], f_ro[3])), // 13
10928 hex->face(3)
10929 ->isotropic_child(
10931 0, f_or[3], f_fl[3], f_ro[3]))
10932 ->line(
10934 3, f_or[3], f_fl[3], f_ro[3])), // 14
10935 hex->face(3)
10936 ->isotropic_child(
10938 3, f_or[3], f_fl[3], f_ro[3]))
10939 ->line(
10941 2, f_or[3], f_fl[3], f_ro[3])), // 15
10942
10943 hex->face(4)
10944 ->isotropic_child(
10946 0, f_or[4], f_fl[4], f_ro[4]))
10947 ->line(
10949 1, f_or[4], f_fl[4], f_ro[4])), // 16
10950 hex->face(4)
10951 ->isotropic_child(
10953 3, f_or[4], f_fl[4], f_ro[4]))
10954 ->line(
10956 0, f_or[4], f_fl[4], f_ro[4])), // 17
10957 hex->face(4)
10958 ->isotropic_child(
10960 0, f_or[4], f_fl[4], f_ro[4]))
10961 ->line(
10963 3, f_or[4], f_fl[4], f_ro[4])), // 18
10964 hex->face(4)
10965 ->isotropic_child(
10967 3, f_or[4], f_fl[4], f_ro[4]))
10968 ->line(
10970 2, f_or[4], f_fl[4], f_ro[4])), // 19
10971
10972 hex->face(5)
10973 ->isotropic_child(
10975 0, f_or[5], f_fl[5], f_ro[5]))
10976 ->line(
10978 1, f_or[5], f_fl[5], f_ro[5])), // 20
10979 hex->face(5)
10980 ->isotropic_child(
10982 3, f_or[5], f_fl[5], f_ro[5]))
10983 ->line(
10985 0, f_or[5], f_fl[5], f_ro[5])), // 21
10986 hex->face(5)
10987 ->isotropic_child(
10989 0, f_or[5], f_fl[5], f_ro[5]))
10990 ->line(
10992 3, f_or[5], f_fl[5], f_ro[5])), // 22
10993 hex->face(5)
10994 ->isotropic_child(
10996 3, f_or[5], f_fl[5], f_ro[5]))
10997 ->line(
10999 2, f_or[5], f_fl[5], f_ro[5])), // 23
11000
11001 new_lines[0], // 24
11002 new_lines[1], // 25
11003 new_lines[2], // 26
11004 new_lines[3], // 27
11005 new_lines[4], // 28
11006 new_lines[5] // 29
11007 };
11008
11009 unsigned int line_indices[30];
11010 for (unsigned int i = 0; i < 30; ++i)
11011 line_indices[i] = lines[i]->index();
11012
11013 // the orientation of lines for the inner quads
11014 // is quite tricky. as these lines are newly
11015 // created ones and thus have no parents, they
11016 // cannot inherit this property. set up an array
11017 // and fill it with the respective values
11018 types::geometric_orientation line_orientation[30]{};
11019
11020 // note: for the first 24 lines (inner lines of
11021 // the outer quads) the following holds: the
11022 // second vertex of the even lines in standard
11023 // orientation is the vertex in the middle of
11024 // the quad, whereas for odd lines the first
11025 // vertex is the same middle vertex.
11026 for (unsigned int i = 0; i < 24; ++i)
11027 if (lines[i]->vertex_index((i + 1) % 2) ==
11028 vertex_indices[i / 4])
11029 line_orientation[i] =
11031 else
11032 {
11033 // it must be the other way
11034 // round then
11035 Assert(lines[i]->vertex_index(i % 2) ==
11036 vertex_indices[i / 4],
11038 line_orientation[i] =
11040 }
11041 // for the last 6 lines the line orientation is
11042 // always true, since they were just constructed
11043 // that way
11044 for (unsigned int i = 24; i < 30; ++i)
11045 line_orientation[i] =
11047
11048 // set up the 12 quads, numbered as follows
11049 // (left quad numbering, right line numbering
11050 // extracted from above)
11051 //
11052 // * *
11053 // /| 21|
11054 // * | * 15
11055 // y/|3* 20| *
11056 // * |/| * |/|
11057 // |2* |x 11 * 14
11058 // |/|1* |/| *
11059 // * |/ * |17
11060 // |0* 10 *
11061 // |/ |16
11062 // * *
11063 //
11064 // x
11065 // *---*---* *22-*-23*
11066 // | 5 | 7 | 1 29 5
11067 // *---*---* *26-*-27*
11068 // | 4 | 6 | 0 28 4
11069 // *---*---*y *18-*-19*
11070 //
11071 // y
11072 // *----*----* *-12-*-13-*
11073 // / 10 / 11 / 3 25 7
11074 // *----*----* *-26-*-27-*
11075 // / 8 / 9 / 2 24 6
11076 // *----*----*x *--8-*--9-*
11077
11078 new_quads[0]->set_bounding_object_indices(
11079 {line_indices[10],
11080 line_indices[28],
11081 line_indices[16],
11082 line_indices[24]});
11083 new_quads[1]->set_bounding_object_indices(
11084 {line_indices[28],
11085 line_indices[14],
11086 line_indices[17],
11087 line_indices[25]});
11088 new_quads[2]->set_bounding_object_indices(
11089 {line_indices[11],
11090 line_indices[29],
11091 line_indices[24],
11092 line_indices[20]});
11093 new_quads[3]->set_bounding_object_indices(
11094 {line_indices[29],
11095 line_indices[15],
11096 line_indices[25],
11097 line_indices[21]});
11098 new_quads[4]->set_bounding_object_indices(
11099 {line_indices[18],
11100 line_indices[26],
11101 line_indices[0],
11102 line_indices[28]});
11103 new_quads[5]->set_bounding_object_indices(
11104 {line_indices[26],
11105 line_indices[22],
11106 line_indices[1],
11107 line_indices[29]});
11108 new_quads[6]->set_bounding_object_indices(
11109 {line_indices[19],
11110 line_indices[27],
11111 line_indices[28],
11112 line_indices[4]});
11113 new_quads[7]->set_bounding_object_indices(
11114 {line_indices[27],
11115 line_indices[23],
11116 line_indices[29],
11117 line_indices[5]});
11118 new_quads[8]->set_bounding_object_indices(
11119 {line_indices[2],
11120 line_indices[24],
11121 line_indices[8],
11122 line_indices[26]});
11123 new_quads[9]->set_bounding_object_indices(
11124 {line_indices[24],
11125 line_indices[6],
11126 line_indices[9],
11127 line_indices[27]});
11128 new_quads[10]->set_bounding_object_indices(
11129 {line_indices[3],
11130 line_indices[25],
11131 line_indices[26],
11132 line_indices[12]});
11133 new_quads[11]->set_bounding_object_indices(
11134 {line_indices[25],
11135 line_indices[7],
11136 line_indices[27],
11137 line_indices[13]});
11138
11139 // now reset the line_orientation flags of outer
11140 // lines as they cannot be set in a loop (at
11141 // least not easily)
11142 new_quads[0]->set_line_orientation(
11143 0, line_orientation[10]);
11144 new_quads[0]->set_line_orientation(
11145 2, line_orientation[16]);
11146
11147 new_quads[1]->set_line_orientation(
11148 1, line_orientation[14]);
11149 new_quads[1]->set_line_orientation(
11150 2, line_orientation[17]);
11151
11152 new_quads[2]->set_line_orientation(
11153 0, line_orientation[11]);
11154 new_quads[2]->set_line_orientation(
11155 3, line_orientation[20]);
11156
11157 new_quads[3]->set_line_orientation(
11158 1, line_orientation[15]);
11159 new_quads[3]->set_line_orientation(
11160 3, line_orientation[21]);
11161
11162 new_quads[4]->set_line_orientation(
11163 0, line_orientation[18]);
11164 new_quads[4]->set_line_orientation(
11165 2, line_orientation[0]);
11166
11167 new_quads[5]->set_line_orientation(
11168 1, line_orientation[22]);
11169 new_quads[5]->set_line_orientation(
11170 2, line_orientation[1]);
11171
11172 new_quads[6]->set_line_orientation(
11173 0, line_orientation[19]);
11174 new_quads[6]->set_line_orientation(
11175 3, line_orientation[4]);
11176
11177 new_quads[7]->set_line_orientation(
11178 1, line_orientation[23]);
11179 new_quads[7]->set_line_orientation(
11180 3, line_orientation[5]);
11181
11182 new_quads[8]->set_line_orientation(
11183 0, line_orientation[2]);
11184 new_quads[8]->set_line_orientation(
11185 2, line_orientation[8]);
11186
11187 new_quads[9]->set_line_orientation(
11188 1, line_orientation[6]);
11189 new_quads[9]->set_line_orientation(
11190 2, line_orientation[9]);
11191
11192 new_quads[10]->set_line_orientation(
11193 0, line_orientation[3]);
11194 new_quads[10]->set_line_orientation(
11195 3, line_orientation[12]);
11196
11197 new_quads[11]->set_line_orientation(
11198 1, line_orientation[7]);
11199 new_quads[11]->set_line_orientation(
11200 3, line_orientation[13]);
11201
11202 //-------------------------------
11203 // create the eight new hexes
11204 //
11205 // again first collect some data. here, we need
11206 // the indices of a whole lotta quads.
11207
11208 // the quads are numbered as follows:
11209 //
11210 // planes in the interior of the old hex:
11211 //
11212 // *
11213 // /|
11214 // * |
11215 // /|3* *---*---* *----*----*
11216 // * |/| | 5 | 7 | / 10 / 11 /
11217 // |2* | *---*---* *----*----*
11218 // |/|1* | 4 | 6 | / 8 / 9 /
11219 // * |/ *---*---*y *----*----*x
11220 // |0*
11221 // |/
11222 // *
11223 //
11224 // children of the faces
11225 // of the old hex
11226 // *-------* *-------*
11227 // /|25 27| /34 35/|
11228 // 15| | / /19
11229 // / | | /32 33/ |
11230 // * |24 26| *-------*18 |
11231 // 1413*-------* |21 23| 17*
11232 // | /30 31/ | | /
11233 // 12/ / | |16
11234 // |/28 29/ |20 22|/
11235 // *-------* *-------*
11236 //
11237 // note that we have to
11238 // take care of the
11239 // orientation of
11240 // faces.
11241 const int quad_indices[36] = {
11242 new_quads[0]->index(), // 0
11243 new_quads[1]->index(),
11244 new_quads[2]->index(),
11245 new_quads[3]->index(),
11246 new_quads[4]->index(),
11247 new_quads[5]->index(),
11248 new_quads[6]->index(),
11249 new_quads[7]->index(),
11250 new_quads[8]->index(),
11251 new_quads[9]->index(),
11252 new_quads[10]->index(),
11253 new_quads[11]->index(), // 11
11254
11255 hex->face(0)->isotropic_child_index(
11257 0, f_or[0], f_fl[0], f_ro[0])), // 12
11258 hex->face(0)->isotropic_child_index(
11260 1, f_or[0], f_fl[0], f_ro[0])),
11261 hex->face(0)->isotropic_child_index(
11263 2, f_or[0], f_fl[0], f_ro[0])),
11264 hex->face(0)->isotropic_child_index(
11266 3, f_or[0], f_fl[0], f_ro[0])),
11267
11268 hex->face(1)->isotropic_child_index(
11270 0, f_or[1], f_fl[1], f_ro[1])), // 16
11271 hex->face(1)->isotropic_child_index(
11273 1, f_or[1], f_fl[1], f_ro[1])),
11274 hex->face(1)->isotropic_child_index(
11276 2, f_or[1], f_fl[1], f_ro[1])),
11277 hex->face(1)->isotropic_child_index(
11279 3, f_or[1], f_fl[1], f_ro[1])),
11280
11281 hex->face(2)->isotropic_child_index(
11283 0, f_or[2], f_fl[2], f_ro[2])), // 20
11284 hex->face(2)->isotropic_child_index(
11286 1, f_or[2], f_fl[2], f_ro[2])),
11287 hex->face(2)->isotropic_child_index(
11289 2, f_or[2], f_fl[2], f_ro[2])),
11290 hex->face(2)->isotropic_child_index(
11292 3, f_or[2], f_fl[2], f_ro[2])),
11293
11294 hex->face(3)->isotropic_child_index(
11296 0, f_or[3], f_fl[3], f_ro[3])), // 24
11297 hex->face(3)->isotropic_child_index(
11299 1, f_or[3], f_fl[3], f_ro[3])),
11300 hex->face(3)->isotropic_child_index(
11302 2, f_or[3], f_fl[3], f_ro[3])),
11303 hex->face(3)->isotropic_child_index(
11305 3, f_or[3], f_fl[3], f_ro[3])),
11306
11307 hex->face(4)->isotropic_child_index(
11309 0, f_or[4], f_fl[4], f_ro[4])), // 28
11310 hex->face(4)->isotropic_child_index(
11312 1, f_or[4], f_fl[4], f_ro[4])),
11313 hex->face(4)->isotropic_child_index(
11315 2, f_or[4], f_fl[4], f_ro[4])),
11316 hex->face(4)->isotropic_child_index(
11318 3, f_or[4], f_fl[4], f_ro[4])),
11319
11320 hex->face(5)->isotropic_child_index(
11322 0, f_or[5], f_fl[5], f_ro[5])), // 32
11323 hex->face(5)->isotropic_child_index(
11325 1, f_or[5], f_fl[5], f_ro[5])),
11326 hex->face(5)->isotropic_child_index(
11328 2, f_or[5], f_fl[5], f_ro[5])),
11329 hex->face(5)->isotropic_child_index(
11331 3, f_or[5], f_fl[5], f_ro[5]))};
11332
11333 // bottom children
11334 new_hexes[0]->set_bounding_object_indices(
11335 {quad_indices[12],
11336 quad_indices[0],
11337 quad_indices[20],
11338 quad_indices[4],
11339 quad_indices[28],
11340 quad_indices[8]});
11341 new_hexes[1]->set_bounding_object_indices(
11342 {quad_indices[0],
11343 quad_indices[16],
11344 quad_indices[22],
11345 quad_indices[6],
11346 quad_indices[29],
11347 quad_indices[9]});
11348 new_hexes[2]->set_bounding_object_indices(
11349 {quad_indices[13],
11350 quad_indices[1],
11351 quad_indices[4],
11352 quad_indices[24],
11353 quad_indices[30],
11354 quad_indices[10]});
11355 new_hexes[3]->set_bounding_object_indices(
11356 {quad_indices[1],
11357 quad_indices[17],
11358 quad_indices[6],
11359 quad_indices[26],
11360 quad_indices[31],
11361 quad_indices[11]});
11362
11363 // top children
11364 new_hexes[4]->set_bounding_object_indices(
11365 {quad_indices[14],
11366 quad_indices[2],
11367 quad_indices[21],
11368 quad_indices[5],
11369 quad_indices[8],
11370 quad_indices[32]});
11371 new_hexes[5]->set_bounding_object_indices(
11372 {quad_indices[2],
11373 quad_indices[18],
11374 quad_indices[23],
11375 quad_indices[7],
11376 quad_indices[9],
11377 quad_indices[33]});
11378 new_hexes[6]->set_bounding_object_indices(
11379 {quad_indices[15],
11380 quad_indices[3],
11381 quad_indices[5],
11382 quad_indices[25],
11383 quad_indices[10],
11384 quad_indices[34]});
11385 new_hexes[7]->set_bounding_object_indices(
11386 {quad_indices[3],
11387 quad_indices[19],
11388 quad_indices[7],
11389 quad_indices[27],
11390 quad_indices[11],
11391 quad_indices[35]});
11392 break;
11393 }
11394 default:
11395 // all refinement cases have been treated, there
11396 // only remains
11397 // RefinementCase<dim>::no_refinement as
11398 // untreated enumeration value. However, in that
11399 // case we should have aborted much
11400 // earlier. thus we should never get here
11402 break;
11403 } // switch (ref_case)
11404
11405 // and set face orientation flags. note that new
11406 // faces in the interior of the mother cell always
11407 // have a correctly oriented face, but the ones on
11408 // the outer faces will inherit this flag
11409 //
11410 // the flag have been set to true for all faces
11411 // initially, now go the other way round and reset
11412 // faces that are at the boundary of the mother cube
11413 //
11414 // the same is true for the face_flip and
11415 // face_rotation flags. however, the latter two are
11416 // set to false by default as this is the standard
11417 // value
11418
11419 // loop over all faces and all (relevant) subfaces
11420 // of that in order to set the correct values for
11421 // face_orientation, face_flip and face_rotation,
11422 // which are inherited from the corresponding face
11423 // of the mother cube
11424 for (const unsigned int f : GeometryInfo<dim>::face_indices())
11425 for (unsigned int s = 0;
11428 ref_case, f)),
11429 1U);
11430 ++s)
11431 {
11432 const unsigned int current_child =
11434 ref_case,
11435 f,
11436 s,
11437 f_or[f],
11438 f_fl[f],
11439 f_ro[f],
11441 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
11442 new_hexes[current_child]->set_combined_face_orientation(
11443 f, f_co[f]);
11444 }
11445
11446 // now see if we have created cells that are
11447 // distorted and if so add them to our list
11448 if (check_for_distorted_cells &&
11450 cells_with_distorted_children.distorted_cells.push_back(
11451 hex);
11452
11453 // note that the refinement flag was already cleared
11454 // at the beginning of this loop
11455
11456 // inform all listeners that cell refinement is done
11457 triangulation.signals.post_refinement_on_cell(hex);
11458 }
11459 }
11460
11461 // clear user data on quads. we used some of this data to
11462 // indicate anisotropic refinemnt cases on faces. all data
11463 // should be cleared by now, but the information whether we
11464 // used indices or pointers is still present. reset it now to
11465 // enable the user to use whichever they like later on.
11466 triangulation.faces->quads.clear_user_data();
11467
11468 // return the list with distorted children
11470 }
11471
11472
11485 template <int spacedim>
11486 static void
11489
11490
11491
11492 template <int dim, int spacedim>
11493 static void
11496 {
11497 // If the codimension is one, we cannot perform this check
11498 // yet.
11499 if (spacedim > dim)
11500 return;
11501
11502 for (const auto &cell : triangulation.cell_iterators())
11503 if (cell->at_boundary() && cell->refine_flag_set() &&
11504 cell->refine_flag_set() !=
11506 {
11507 // The cell is at the boundary and it is flagged for
11508 // anisotropic refinement. Therefore, we have a closer
11509 // look
11510 const RefinementCase<dim> ref_case = cell->refine_flag_set();
11511 for (const unsigned int face_no :
11513 if (cell->face(face_no)->at_boundary())
11514 {
11515 // this is the critical face at the boundary.
11517 face_no) !=
11519 {
11520 // up to now, we do not want to refine this
11521 // cell along the face under consideration
11522 // here.
11523 const typename Triangulation<dim,
11524 spacedim>::face_iterator
11525 face = cell->face(face_no);
11526 // the new point on the boundary would be this
11527 // one.
11528 const Point<spacedim> new_bound = face->center(true);
11529 // to check it, transform to the unit cell
11530 // with a linear mapping
11531 const Point<dim> new_unit =
11532 cell->reference_cell()
11533 .template get_default_linear_mapping<dim,
11534 spacedim>()
11535 .transform_real_to_unit_cell(cell, new_bound);
11536
11537 // Now, we have to calculate the distance from
11538 // the face in the unit cell.
11539
11540 // take the correct coordinate direction (0
11541 // for faces 0 and 1, 1 for faces 2 and 3, 2
11542 // for faces 4 and 5) and subtract the correct
11543 // boundary value of the face (0 for faces 0,
11544 // 2, and 4; 1 for faces 1, 3 and 5)
11545 const double dist =
11546 std::fabs(new_unit[face_no / 2] - face_no % 2);
11547
11548 // compare this with the empirical value
11549 // allowed. if it is too big, flag the face
11550 // for isotropic refinement
11551 const double allowed = 0.25;
11552
11553 if (dist > allowed)
11554 cell->flag_for_face_refinement(face_no);
11555 } // if flagged for anistropic refinement
11556 } // if (cell->face(face)->at_boundary())
11557 } // for all cells
11558 }
11559
11560
11573 template <int dim, int spacedim>
11574 static void
11576 {
11577 Assert(dim < 3,
11578 ExcMessage("Wrong function called -- there should "
11579 "be a specialization."));
11580 }
11581
11582
11583 template <int spacedim>
11584 static void
11587 {
11588 const unsigned int dim = 3;
11589 using raw_line_iterator =
11591
11592 // variable to store whether the mesh was changed in the
11593 // present loop and in the whole process
11594 bool mesh_changed = false;
11595
11596 do
11597 {
11598 mesh_changed = false;
11599
11600 // for this following, we need to know which cells are
11601 // going to be coarsened, if we had to make a
11602 // decision. the following function sets these flags:
11603 triangulation.fix_coarsen_flags();
11604
11605 // first clear flags on lines, since we need them to determine
11606 // which lines will be refined
11607 triangulation.clear_user_flags_line();
11608
11609 // flag those lines that are refined and will not be
11610 // coarsened and those that will be refined
11611 for (const auto &cell : triangulation.cell_iterators())
11612 if (cell->refine_flag_set())
11613 {
11614 const std::array<unsigned int, 12> line_indices =
11615 TriaAccessorImplementation::Implementation::
11616 get_line_indices_of_cell(*cell);
11617 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11619 cell->refine_flag_set(), l) ==
11621 {
11622 raw_line_iterator line(&triangulation,
11623 0,
11624 line_indices[l]);
11625 // flag a line, that will be refined
11626 line->set_user_flag();
11627 }
11628 }
11629 else if (cell->has_children() &&
11630 !cell->child(0)->coarsen_flag_set())
11631 {
11632 const std::array<unsigned int, 12> line_indices =
11633 TriaAccessorImplementation::Implementation::
11634 get_line_indices_of_cell(*cell);
11635 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11637 cell->refinement_case(), l) ==
11639 {
11640 raw_line_iterator line(&triangulation,
11641 0,
11642 line_indices[l]);
11643 // flag a line, that is refined and will stay so
11644 line->set_user_flag();
11645 }
11646 }
11647 else if (cell->has_children() &&
11648 cell->child(0)->coarsen_flag_set())
11649 cell->set_user_flag();
11650
11651
11652 // now check whether there are cells with lines that are
11653 // more than once refined or that will be more than once
11654 // refined. The first thing should never be the case, in
11655 // the second case we flag the cell for refinement
11657 cell = triangulation.last_active();
11658 cell != triangulation.end();
11659 --cell)
11660 {
11661 const std::array<unsigned int, 12> line_indices =
11662 TriaAccessorImplementation::Implementation::
11663 get_line_indices_of_cell(*cell);
11664 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11665 {
11666 raw_line_iterator line(&triangulation, 0, line_indices[l]);
11667 if (line->has_children())
11668 {
11669 // if this line is refined, its children should
11670 // not have further children
11671 //
11672 // however, if any of the children is flagged
11673 // for further refinement, we need to refine
11674 // this cell also (at least, if the cell is not
11675 // already flagged)
11676 bool offending_line_found = false;
11677
11678 for (unsigned int c = 0; c < 2; ++c)
11679 {
11680 Assert(line->child(c)->has_children() == false,
11682
11683 if (line->child(c)->user_flag_set() &&
11685 cell->refine_flag_set(), l) ==
11687 {
11688 // tag this cell for refinement
11689 cell->clear_coarsen_flag();
11690 // if anisotropic coarsening is allowed:
11691 // extend the refine_flag in the needed
11692 // direction, else set refine_flag
11693 // (isotropic)
11694 if (triangulation.smooth_grid &
11696 allow_anisotropic_smoothing)
11697 cell->flag_for_line_refinement(l);
11698 else
11699 cell->set_refine_flag();
11700
11701 for (unsigned int k = 0; k < cell->n_lines();
11702 ++k)
11704 cell->refine_flag_set(), l) ==
11706 // flag a line, that will be refined
11707 raw_line_iterator(&triangulation,
11708 0,
11709 line_indices[k])
11710 ->set_user_flag();
11711
11712 // note that we have changed the grid
11713 offending_line_found = true;
11714
11715 // it may save us several loop
11716 // iterations if we flag all lines of
11717 // this cell now (and not at the outset
11718 // of the next iteration) for refinement
11719 for (unsigned int k = 0; k < cell->n_lines();
11720 ++k)
11721 {
11722 const auto line =
11723 raw_line_iterator(&triangulation,
11724 0,
11725 line_indices[k]);
11726 if (!line->has_children() &&
11728 line_refinement_case(
11729 cell->refine_flag_set(), k) !=
11731 line->set_user_flag();
11732 }
11733
11734 break;
11735 }
11736 }
11737
11739 {
11740 mesh_changed = true;
11741 break;
11742 }
11743 }
11744 }
11745 }
11746
11747
11748 // there is another thing here: if any of the lines will
11749 // be refined, then we may not coarsen the present cell
11750 // similarly, if any of the lines *is* already refined, we
11751 // may not coarsen the current cell. however, there's a
11752 // catch: if the line is refined, but the cell behind it
11753 // is going to be coarsened, then the situation
11754 // changes. if we forget this second condition, the
11755 // refine_and_coarsen_3d test will start to fail. note
11756 // that to know which cells are going to be coarsened, the
11757 // call for fix_coarsen_flags above is necessary
11759 triangulation.last();
11760 cell != triangulation.end();
11761 --cell)
11762 if (cell->user_flag_set())
11763 {
11764 const std::array<unsigned int, 12> line_indices =
11765 TriaAccessorImplementation::Implementation::
11766 get_line_indices_of_cell(*cell);
11767 for (unsigned int l = 0; l < cell->n_lines(); ++l)
11768 {
11769 raw_line_iterator line(&triangulation,
11770 0,
11771 line_indices[l]);
11772 if (line->has_children() &&
11773 (line->child(0)->user_flag_set() ||
11774 line->child(1)->user_flag_set()))
11775 {
11776 for (unsigned int c = 0; c < cell->n_children(); ++c)
11777 cell->child(c)->clear_coarsen_flag();
11778 cell->clear_user_flag();
11779 for (unsigned int k = 0; k < cell->n_lines(); ++k)
11781 cell->refinement_case(), k) ==
11783 // flag a line, that is refined and will
11784 // stay so
11785 raw_line_iterator(&triangulation,
11786 0,
11787 line_indices[k])
11788 ->set_user_flag();
11789 mesh_changed = true;
11790 break;
11791 }
11792 }
11793 }
11794 }
11795 while (mesh_changed == true);
11796 }
11797
11798
11799
11806 template <int dim, int spacedim>
11807 static bool
11810 {
11811 // in 1d, coarsening is always allowed since we don't enforce
11812 // the 2:1 constraint there
11813 if (dim == 1)
11814 return true;
11815
11816 const RefinementCase<dim> ref_case = cell->refinement_case();
11817 for (const unsigned int n : GeometryInfo<dim>::face_indices())
11818 {
11819 // if the cell is not refined along that face, coarsening
11820 // will not change anything, so do nothing. the same
11821 // applies, if the face is at the boundary
11822 const RefinementCase<dim - 1> face_ref_case =
11823 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
11824 n);
11825
11826 const unsigned int n_subfaces =
11828
11829 if (n_subfaces == 0 || cell->at_boundary(n))
11830 continue;
11831 for (unsigned int c = 0; c < n_subfaces; ++c)
11832 {
11834 child = cell->child(
11836
11838 child_neighbor = child->neighbor(n);
11839 if (!child->neighbor_is_coarser(n))
11840 {
11841 // in 2d, if the child's neighbor is coarser, then it has
11842 // no children. however, in 3d it might be
11843 // otherwise. consider for example, that our face might be
11844 // refined with cut_x, but the neighbor is refined with
11845 // cut_xy at that face. then the neighbor pointers of the
11846 // children of our cell will point to the common neighbor
11847 // cell, not to its children. what we really want to know
11848 // in the following is, whether the neighbor cell is
11849 // refined twice with reference to our cell. that only
11850 // has to be asked, if the child's neighbor is not a
11851 // coarser one. we check whether some of the children on
11852 // the neighbor are not flagged for coarsening, in that
11853 // case we may not coarsen. it is enough to check the
11854 // first child because we have already fixed the coarsen
11855 // flags on finer levels
11856 if (child_neighbor->has_children() &&
11857 !(child_neighbor->child(0)->is_active() &&
11858 child_neighbor->child(0)->coarsen_flag_set()))
11859 return false;
11860
11861 // the same applies, if the neighbors children are not
11862 // refined but will be after refinement
11863 if (child_neighbor->refine_flag_set())
11864 return false;
11865 }
11866 }
11867 }
11868 return true;
11869 }
11870 };
11871
11872
11877 {
11878 template <int spacedim>
11879 static void
11882
11883 template <int dim, int spacedim>
11885 {
11886 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
11887 2 * triangulation.n_raw_faces(),
11888 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
11889
11890 const auto set_entry = [&](const auto &face_index, const auto &cell) {
11891 const std::pair<unsigned int, unsigned int> cell_pair = {
11892 cell->level(), cell->index()};
11893 unsigned int index;
11894
11895 if (adjacent_cells[2 * face_index].first ==
11897 adjacent_cells[2 * face_index].second ==
11899 {
11900 index = 2 * face_index + 0;
11901 }
11902 else
11903 {
11904 Assert(((adjacent_cells[2 * face_index + 1].first ==
11906 (adjacent_cells[2 * face_index + 1].second ==
11909 index = 2 * face_index + 1;
11910 }
11911
11913 };
11914
11915 const auto get_entry =
11916 [&](const auto &face_index,
11917 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
11918 auto test = adjacent_cells[2 * face_index];
11919
11920 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
11921 cell->index()))
11922 test = adjacent_cells[2 * face_index + 1];
11923
11924 if ((test.first != numbers::invalid_unsigned_int) &&
11925 (test.second != numbers::invalid_unsigned_int))
11927 test.first,
11928 test.second);
11929 else
11931 };
11932
11933 for (const auto &cell : triangulation.cell_iterators())
11934 for (const auto &face : cell->face_iterators())
11935 {
11936 set_entry(face->index(), cell);
11937
11938 if (cell->is_active() && face->has_children())
11939 for (unsigned int c = 0; c < face->n_children(); ++c)
11940 set_entry(face->child(c)->index(), cell);
11941 }
11942
11943 for (const auto &cell : triangulation.cell_iterators())
11944 for (auto f : cell->face_indices())
11945 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
11946 }
11947
11948 template <int dim, int spacedim>
11949 static void
11951 Triangulation<dim, spacedim> & /*triangulation*/,
11953 std::vector<unsigned int> & /*line_cell_count*/,
11954 std::vector<unsigned int> & /*quad_cell_count*/)
11955 {
11957 }
11958
11959 template <int dim, int spacedim>
11962 const bool check_for_distorted_cells)
11963 {
11965 triangulation, check_for_distorted_cells);
11966 }
11967
11968 template <int dim, int spacedim>
11969 static void
11971 Triangulation<dim, spacedim> & /*triangulation*/)
11972 {
11973 // nothing to do since anisotropy is not supported
11974 }
11975
11976 template <int dim, int spacedim>
11977 static void
11983
11984 template <int dim, int spacedim>
11985 static bool
11988 {
11990
11991 return false;
11992 }
11993 };
11994
11995
11996 template <int dim, int spacedim>
11999 {
12001 return flat_manifold;
12002 }
12003 } // namespace TriangulationImplementation
12004} // namespace internal
12005
12006#ifndef DOXYGEN
12007
12008template <int dim, int spacedim>
12011
12012
12013
12014template <int dim, int spacedim>
12017 const MeshSmoothing smooth_grid,
12018 const bool check_for_distorted_cells)
12019 : cell_attached_data({0, 0, {}, {}})
12020 , smooth_grid(smooth_grid)
12021 , anisotropic_refinement(false)
12022 , check_for_distorted_cells(check_for_distorted_cells)
12023{
12024 if (dim == 1)
12025 {
12026 vertex_to_boundary_id_map_1d =
12027 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12028 vertex_to_manifold_id_map_1d =
12029 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12030 }
12031
12032 // connect the any_change signal to the other top level signals
12033 signals.create.connect(signals.any_change);
12034 signals.post_refinement.connect(signals.any_change);
12035 signals.clear.connect(signals.any_change);
12036 signals.mesh_movement.connect(signals.any_change);
12037}
12038
12039
12040
12041template <int dim, int spacedim>
12045 : EnableObserverPointer(std::move(tria))
12046 , smooth_grid(tria.smooth_grid)
12047 , reference_cells(std::move(tria.reference_cells))
12048 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12049 , periodic_face_map(std::move(tria.periodic_face_map))
12050 , levels(std::move(tria.levels))
12051 , faces(std::move(tria.faces))
12052 , vertices(std::move(tria.vertices))
12053 , vertices_used(std::move(tria.vertices_used))
12054 , manifolds(std::move(tria.manifolds))
12055 , anisotropic_refinement(tria.anisotropic_refinement)
12056 , check_for_distorted_cells(tria.check_for_distorted_cells)
12057 , number_cache(std::move(tria.number_cache))
12058 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12059 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12060{
12062
12063 if (tria.policy)
12064 this->policy = tria.policy->clone();
12065}
12066
12067
12068template <int dim, int spacedim>
12071 Triangulation<dim, spacedim> &&tria) noexcept
12072{
12073 EnableObserverPointer::operator=(std::move(tria));
12074
12075 smooth_grid = tria.smooth_grid;
12076 reference_cells = std::move(tria.reference_cells);
12077 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12078 periodic_face_map = std::move(tria.periodic_face_map);
12079 levels = std::move(tria.levels);
12080 faces = std::move(tria.faces);
12081 vertices = std::move(tria.vertices);
12082 vertices_used = std::move(tria.vertices_used);
12083 manifolds = std::move(tria.manifolds);
12084 anisotropic_refinement = tria.anisotropic_refinement;
12085 number_cache = tria.number_cache;
12086 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12087 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12088
12090
12091 if (tria.policy)
12092 this->policy = tria.policy->clone();
12093
12094 return *this;
12095}
12096
12097
12098
12099template <int dim, int spacedim>
12102{
12103 // notify listeners that the triangulation is going down...
12104 try
12105 {
12106 signals.clear();
12107 }
12108 catch (...)
12109 {}
12110
12111 levels.clear();
12112
12113 // the vertex_to_boundary_id_map_1d field should be unused except in
12114 // 1d. double check this here, as destruction is a good place to
12115 // ensure that what we've done over the course of the lifetime of
12116 // this object makes sense
12117 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12119
12120 // the vertex_to_manifold_id_map_1d field should be also unused
12121 // except in 1d. check this as well
12122 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12124}
12125
12126
12127
12128template <int dim, int spacedim>
12131{
12132 // notify listeners that the triangulation is going down...
12133 signals.clear();
12134
12135 // ...and then actually clear all content of it
12136 clear_despite_subscriptions();
12137 periodic_face_pairs_level_0.clear();
12138 periodic_face_map.clear();
12139 reference_cells.clear();
12140
12141 cell_attached_data = {0, 0, {}, {}};
12142 data_serializer.clear();
12143}
12144
12145template <int dim, int spacedim>
12148{
12149 return MPI_COMM_SELF;
12150}
12151
12152
12153
12154template <int dim, int spacedim>
12157{
12158 return get_mpi_communicator();
12159}
12160
12161
12162
12163template <int dim, int spacedim>
12165std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12167{
12168 return number_cache.active_cell_index_partitioner;
12169}
12170
12171
12172
12173template <int dim, int spacedim>
12175std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
12176 global_level_cell_index_partitioner(const unsigned int level) const
12177{
12178 AssertIndexRange(level, this->n_levels());
12179
12180 return number_cache.level_cell_index_partitioners[level];
12181}
12182
12183
12184
12185template <int dim, int spacedim>
12188 const MeshSmoothing mesh_smoothing)
12189{
12190 smooth_grid = mesh_smoothing;
12191}
12192
12193
12194
12195template <int dim, int spacedim>
12199{
12200 return smooth_grid;
12201}
12202
12203
12204
12205template <int dim, int spacedim>
12210{
12212
12213 manifolds[m_number] = manifold_object.clone();
12214}
12215
12216
12217
12218template <int dim, int spacedim>
12222{
12224
12225 // delete the entry located at number.
12226 manifolds[m_number] =
12228 spacedim>()
12229 .clone();
12230}
12231
12232
12233template <int dim, int spacedim>
12236{
12237 for (auto &m : manifolds)
12238 m.second = internal::TriangulationImplementation::
12239 get_default_flat_manifold<dim, spacedim>()
12240 .clone();
12241}
12242
12243
12244template <int dim, int spacedim>
12248{
12249 Assert(
12250 n_cells() > 0,
12251 ExcMessage(
12252 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
12253
12254 for (const auto &cell : this->active_cell_iterators())
12255 cell->set_all_manifold_ids(m_number);
12256}
12257
12258
12259template <int dim, int spacedim>
12263{
12264 Assert(
12265 n_cells() > 0,
12266 ExcMessage(
12267 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12268
12269 for (const auto &cell : this->active_cell_iterators())
12270 for (auto f : GeometryInfo<dim>::face_indices())
12271 if (cell->face(f)->at_boundary())
12272 cell->face(f)->set_all_manifold_ids(m_number);
12273}
12274
12275
12276template <int dim, int spacedim>
12281{
12282 Assert(
12283 n_cells() > 0,
12284 ExcMessage(
12285 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
12286
12287 [[maybe_unused]] bool boundary_found = false;
12288
12289 for (const auto &cell : this->active_cell_iterators())
12290 {
12291 // loop on faces
12292 for (auto f : GeometryInfo<dim>::face_indices())
12293 if (cell->face(f)->at_boundary() &&
12294 cell->face(f)->boundary_id() == b_id)
12295 {
12296 boundary_found = true;
12297 cell->face(f)->set_manifold_id(m_number);
12298 }
12299
12300 // loop on edges if dim >= 3
12301 if (dim >= 3)
12302 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
12303 if (cell->line(e)->at_boundary() &&
12304 cell->line(e)->boundary_id() == b_id)
12305 {
12306 boundary_found = true;
12307 cell->line(e)->set_manifold_id(m_number);
12308 }
12309 }
12310
12311 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
12312}
12313
12314
12315
12316template <int dim, int spacedim>
12319 const types::manifold_id m_number) const
12320{
12321 // check if flat manifold has been queried
12323 return internal::TriangulationImplementation::
12324 get_default_flat_manifold<dim, spacedim>();
12325
12326 // look, if there is a manifold stored at
12327 // manifold_id number.
12328 const auto it = manifolds.find(m_number);
12329
12330 if (it != manifolds.end())
12331 {
12332 // if we have found an entry, return it
12333 return *(it->second);
12334 }
12335
12336 Assert(
12337 false,
12338 ExcMessage(
12339 "No manifold of the manifold id " + std::to_string(m_number) +
12340 " has been attached to the triangulation. "
12341 "Please attach the right manifold with Triangulation::set_manifold()."));
12342
12343 return internal::TriangulationImplementation::
12344 get_default_flat_manifold<dim, spacedim>(); // never reached
12345}
12346
12347
12348
12349template <int dim, int spacedim>
12351std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
12352 const
12353{
12354 std::set<types::boundary_id> boundary_ids;
12355 for (const auto &cell : active_cell_iterators())
12356 if (cell->is_locally_owned())
12357 for (const auto &face : cell->face_indices())
12358 if (cell->at_boundary(face))
12359 boundary_ids.insert(cell->face(face)->boundary_id());
12360
12361 return {boundary_ids.begin(), boundary_ids.end()};
12362}
12363
12364
12365
12366template <int dim, int spacedim>
12368std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
12369 const
12370{
12371 std::set<types::manifold_id> m_ids;
12372 for (const auto &cell : active_cell_iterators())
12373 if (cell->is_locally_owned())
12374 {
12375 m_ids.insert(cell->manifold_id());
12376 for (const auto &face : cell->face_iterators())
12377 m_ids.insert(face->manifold_id());
12378 if (dim == 3)
12379 {
12380 const auto line_indices = internal::TriaAccessorImplementation::
12381 Implementation::get_line_indices_of_cell(*cell);
12382 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12383 {
12384 raw_line_iterator line(this, 0, line_indices[l]);
12385 m_ids.insert(line->manifold_id());
12386 }
12387 }
12388 }
12389 return {m_ids.begin(), m_ids.end()};
12390}
12391
12392#endif
12393/*-----------------------------------------------------------------*/
12394
12395#ifndef DOXYGEN
12396
12397template <int dim, int spacedim>
12401{
12402 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12403 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12404 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
12405 (dim == 1 || other_tria.faces != nullptr),
12406 ExcMessage(
12407 "When calling Triangulation::copy_triangulation(), "
12408 "the target triangulation must be empty but the source "
12409 "triangulation (the argument to this function) must contain "
12410 "something. Here, it seems like the source does not "
12411 "contain anything at all."));
12412
12413
12414 // copy normal elements
12415 vertices = other_tria.vertices;
12416 vertices_used = other_tria.vertices_used;
12417 anisotropic_refinement = other_tria.anisotropic_refinement;
12418 smooth_grid = other_tria.smooth_grid;
12419 reference_cells = other_tria.reference_cells;
12420
12421 if (dim > 1)
12422 faces = std::make_unique<internal::TriangulationImplementation::TriaFaces>(
12423 *other_tria.faces);
12424
12425 for (const auto &p : other_tria.manifolds)
12426 set_manifold(p.first, *p.second);
12427
12428
12429 levels.reserve(other_tria.levels.size());
12430 for (unsigned int level = 0; level < other_tria.levels.size(); ++level)
12431 levels.push_back(
12432 std::make_unique<internal::TriangulationImplementation::TriaLevel>(
12433 *other_tria.levels[level]));
12434
12435 number_cache = other_tria.number_cache;
12436
12437 if (dim == 1)
12438 {
12439 vertex_to_boundary_id_map_1d =
12440 std::make_unique<std::map<unsigned int, types::boundary_id>>(
12441 *other_tria.vertex_to_boundary_id_map_1d);
12442
12443 vertex_to_manifold_id_map_1d =
12444 std::make_unique<std::map<unsigned int, types::manifold_id>>(
12445 *other_tria.vertex_to_manifold_id_map_1d);
12446 }
12447
12448 if (other_tria.policy)
12449 this->policy = other_tria.policy->clone();
12450
12451 // periodic faces
12452 this->periodic_face_pairs_level_0.reserve(
12453 other_tria.periodic_face_pairs_level_0.size());
12454
12455 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
12456 {
12457 auto entry = other_entry;
12458 entry.cell[0] =
12459 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
12460 entry.cell[1] =
12461 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
12462 periodic_face_pairs_level_0.emplace_back(entry);
12463 }
12464
12466 other_tria.periodic_face_map)
12467 {
12468 auto first_cell = first_cell_; // make copy since key is const
12469 first_cell.first = cell_iterator(this,
12470 first_cell.first->level(),
12471 first_cell.first->index());
12472 second_cell_and_orientation.first.first =
12473 cell_iterator(this,
12474 second_cell_and_orientation.first.first->level(),
12475 second_cell_and_orientation.first.first->index());
12476
12477 this->periodic_face_map[first_cell] = second_cell_and_orientation;
12478 }
12479
12480 // inform those who are listening on other_tria of the copy operation
12481 other_tria.signals.copy(*this);
12482 // also inform all listeners of the current triangulation that the
12483 // triangulation has been created
12484 signals.create();
12485
12486 // note that we need not copy the
12487 // subscriptor!
12488}
12489
12490
12491
12492template <int dim, int spacedim>
12495{
12496 this->update_reference_cells();
12497
12498 if (this->all_reference_cells_are_hyper_cube())
12499 {
12500 this->policy =
12502 dim,
12503 spacedim,
12505 }
12506 else
12507 {
12508 this->policy =
12510 dim,
12511 spacedim,
12513 }
12514}
12515
12516
12517
12518template <int dim, int spacedim>
12521 const std::vector<Point<spacedim>> &v,
12522 const std::vector<CellData<dim>> &cells,
12523 const SubCellData &subcelldata)
12524{
12525 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
12526 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
12527 // check that no forbidden arrays
12528 // are used
12529 Assert(subcelldata.check_consistency(dim), ExcInternalError());
12530
12531 // try to create a triangulation; if this fails, we still want to
12532 // throw an exception but if we just do so we'll get into trouble
12533 // because sometimes other objects are already attached to it:
12534 try
12535 {
12537 create_triangulation(v, cells, subcelldata, *this);
12538 }
12539 catch (...)
12540 {
12541 clear_despite_subscriptions();
12542 throw;
12543 }
12544
12545 reset_policy();
12546
12547 // update our counts of the various elements of a triangulation, and set
12548 // active_cell_indices of all cells
12549 reset_cell_vertex_indices_cache();
12551 *this, levels.size(), number_cache);
12552 reset_active_cell_indices();
12553 reset_global_cell_indices();
12554
12555 // now verify that there are indeed no distorted cells. as per the
12556 // documentation of this class, we first collect all distorted cells
12557 // and then throw an exception if there are any
12558 if (check_for_distorted_cells)
12559 {
12560 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
12561 // throw the array (and fill the various location fields) if
12562 // there are distorted cells. otherwise, just fall off the end
12563 // of the function
12564 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
12565 }
12566
12567
12568 /*
12569 When the triangulation is a manifold (dim < spacedim) and made of
12570 quadrilaterals, the normal field provided from the map class depends on
12571 the order of the vertices. It may happen that this normal field is
12572 discontinuous. The following code takes care that this is not the case by
12573 setting the cell direction flag on those cell that produce the wrong
12574 orientation.
12575
12576 To determine if 2 neighbors have the same or opposite orientation we use
12577 a truth table. Its entries are indexed by the local indices of the
12578 common face. For example if two elements share a face, and this face is
12579 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
12580 whether the orientation are the same (true) or opposite (false).
12581
12582 Even though there may be a combinatorial/graph theory argument to get this
12583 table in any dimension, I tested by hand all the different possible cases
12584 in 1D and 2D to generate the table.
12585
12586 Assuming that a surface respects the standard orientation for 2d meshes,
12587 the truth tables are symmetric and their true values are the following
12588
12589 - 1D curves: (0,1)
12590 - 2D surface: (0,1),(0,2),(1,3),(2,3)
12591
12592 We store this data using an n_faces x n_faces full matrix, which is
12593 actually much bigger than the minimal data required, but it makes the code
12594 more readable.
12595
12596 */
12597 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
12598 {
12601 switch (dim)
12602 {
12603 case 1:
12604 {
12605 const bool values[][2] = {{false, true}, {true, false}};
12606 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12607 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12608 correct(i, j) = values[i][j];
12609 break;
12610 }
12611 case 2:
12612 {
12613 const bool values[][4] = {{false, true, true, false},
12614 {true, false, false, true},
12615 {true, false, false, true},
12616 {false, true, true, false}};
12617 for (const unsigned int i : GeometryInfo<dim>::face_indices())
12618 for (const unsigned int j : GeometryInfo<dim>::face_indices())
12619 correct(i, j) = (values[i][j]);
12620 break;
12621 }
12622 default:
12624 }
12625
12626
12627 std::list<active_cell_iterator> this_round, next_round;
12628 active_cell_iterator neighbor;
12629
12630 // Start with the first cell and (arbitrarily) decide that its
12631 // direction flag should be 'true':
12632 this_round.push_back(begin_active());
12633 begin_active()->set_direction_flag(true);
12634 begin_active()->set_user_flag();
12635
12636 while (this_round.size() > 0)
12637 {
12638 for (const auto &cell : this_round)
12639 {
12640 for (const unsigned int i : cell->face_indices())
12641 {
12642 if (cell->face(i)->at_boundary() == false)
12643 {
12644 // Consider the i'th neighbor of a cell for
12645 // which we have already set the direction:
12646 neighbor = cell->neighbor(i);
12647
12648 const unsigned int nb_of_nb =
12649 cell->neighbor_of_neighbor(i);
12650
12651 // If we already saw this neighboring cell,
12652 // check that everything is fine:
12653 if (neighbor->user_flag_set())
12654 {
12655 Assert(
12656 !(correct(i, nb_of_nb) ^
12657 (neighbor->direction_flag() ==
12658 cell->direction_flag())),
12659 ExcMessage(
12660 "The triangulation you are trying to create is not orientable."));
12661 }
12662 else
12663 {
12664 // We had not seen this cell yet. Set its
12665 // orientation flag (if necessary), mark it
12666 // as treated via the user flag, and push it
12667 // onto the list of cells to start work from
12668 // the next time around:
12669 if (correct(i, nb_of_nb) ^
12670 (neighbor->direction_flag() ==
12671 cell->direction_flag()))
12672 neighbor->set_direction_flag(
12673 !neighbor->direction_flag());
12674 neighbor->set_user_flag();
12675 next_round.push_back(neighbor);
12676 }
12677 }
12678 }
12679 }
12680
12681 // Before we quit let's check that if the triangulation is
12682 // disconnected that we still get all cells by starting
12683 // again from the first cell we haven't treated yet -- that
12684 // is, the first cell of the next disconnected component we
12685 // had not yet touched.
12686 if (next_round.empty())
12687 for (const auto &cell : this->active_cell_iterators())
12688 if (cell->user_flag_set() == false)
12689 {
12690 next_round.push_back(cell);
12691 cell->set_direction_flag(true);
12692 cell->set_user_flag();
12693 break;
12694 }
12695
12696 // Go on to the next round:
12697 next_round.swap(this_round);
12698 next_round.clear();
12699 }
12700 clear_user_flags();
12701 }
12702
12703 this->update_cell_relations();
12704
12705 // inform all listeners that the triangulation has been created
12706 signals.create();
12707}
12708
12709
12710
12711template <int dim, int spacedim>
12715{
12716 // 1) create coarse grid
12717 create_triangulation(construction_data.coarse_cell_vertices,
12718 construction_data.coarse_cells,
12719 SubCellData());
12720
12721 // create a copy of cell_infos such that we can sort them
12722 auto cell_infos = construction_data.cell_infos;
12723
12724 // sort cell_infos on each level separately
12725 for (auto &cell_info : cell_infos)
12726 std::sort(
12727 cell_info.begin(),
12728 cell_info.end(),
12731 const CellId a_id(a.id);
12732 const CellId b_id(b.id);
12733
12734 const auto a_coarse_cell_index =
12735 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
12736 const auto b_coarse_cell_index =
12737 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
12738
12739 // according to their coarse-cell index and if that is
12740 // same according to their cell id (the result is that
12741 // cells on each level are sorted according to their
12742 // index on that level - what we need in the following
12743 // operations)
12746 else
12747 return a_id < b_id;
12748 });
12749
12750 // 2) create all levels via a sequence of refinements. note that
12751 // we must make sure that we actually have cells on this level,
12752 // which is not clear in a parallel context for some processes
12753 for (unsigned int level = 0;
12754 level < cell_infos.size() && !cell_infos[level].empty();
12755 ++level)
12756 {
12757 // a) set manifold ids here (because new vertices have to be
12758 // positioned correctly during each refinement step)
12759 {
12760 auto cell = this->begin(level);
12761 auto cell_info = cell_infos[level].begin();
12762 for (; cell_info != cell_infos[level].end(); ++cell_info)
12763 {
12764 while (cell_info->id != cell->id().template to_binary<dim>())
12765 ++cell;
12766 if (dim == 2)
12767 for (const auto face : cell->face_indices())
12768 cell->face(face)->set_manifold_id(
12769 cell_info->manifold_line_ids[face]);
12770 else if (dim == 3)
12771 {
12772 for (const auto face : cell->face_indices())
12773 cell->face(face)->set_manifold_id(
12774 cell_info->manifold_quad_ids[face]);
12775
12776 const auto line_indices = internal::TriaAccessorImplementation::
12777 Implementation::get_line_indices_of_cell(*cell);
12778 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12779 {
12780 raw_line_iterator line(this, 0, line_indices[l]);
12781 line->set_manifold_id(cell_info->manifold_line_ids[l]);
12782 }
12783 }
12784
12785 cell->set_manifold_id(cell_info->manifold_id);
12786 }
12787 }
12788
12789 // b) perform refinement on all levels but on the finest
12790 if (level + 1 != cell_infos.size())
12791 {
12792 // find cells that should have children and mark them for
12793 // refinement
12794 auto coarse_cell = this->begin(level);
12795 auto fine_cell_info = cell_infos[level + 1].begin();
12796
12797 // loop over all cells on the next level
12798 for (; fine_cell_info != cell_infos[level + 1].end();
12800 {
12801 // find the parent of that cell
12802 while (
12803 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
12804 ++coarse_cell;
12805
12806 // set parent for refinement
12807 coarse_cell->set_refine_flag();
12808 }
12809
12810 // execute refinement
12811 ::Triangulation<dim,
12812 spacedim>::execute_coarsening_and_refinement();
12813 }
12814 }
12815
12816 // 3) set boundary ids
12817 for (unsigned int level = 0;
12818 level < cell_infos.size() && !cell_infos[level].empty();
12819 ++level)
12820 {
12821 auto cell = this->begin(level);
12822 auto cell_info = cell_infos[level].begin();
12823 for (; cell_info != cell_infos[level].end(); ++cell_info)
12824 {
12825 // find cell that has the correct cell
12826 while (cell_info->id != cell->id().template to_binary<dim>())
12827 ++cell;
12828
12829 // boundary ids
12830 for (auto pair : cell_info->boundary_ids)
12831 if (cell->face(pair.first)->at_boundary())
12832 cell->face(pair.first)->set_boundary_id(pair.second);
12833 }
12834 }
12835
12836 // inform all listeners that the triangulation has been created
12837 signals.create();
12838}
12839
12840
12841template <int dim, int spacedim>
12844{
12845 AssertThrow(dim + 1 == spacedim,
12846 ExcMessage(
12847 "This function can only be called if dim == spacedim-1."));
12848 for (const auto &cell : this->active_cell_iterators())
12849 cell->set_direction_flag(!cell->direction_flag());
12850}
12851
12852
12853
12854template <int dim, int spacedim>
12857{
12858 Assert(n_cells() > 0,
12859 ExcMessage("Error: An empty Triangulation can not be refined."));
12860
12861 for (const auto &cell : this->active_cell_iterators())
12862 {
12863 cell->clear_coarsen_flag();
12864 cell->set_refine_flag();
12865 cell->set_refine_choice();
12866 }
12867}
12868
12869
12870
12871template <int dim, int spacedim>
12874{
12875 Assert(n_cells() > 0,
12876 ExcMessage("Error: An empty Triangulation can not be refined."));
12877
12878 for (unsigned int i = 0; i < times; ++i)
12879 {
12880 set_all_refine_flags();
12881 execute_coarsening_and_refinement();
12882 }
12883}
12884
12885
12886
12887template <int dim, int spacedim>
12890{
12891 for (unsigned int i = 0; i < times; ++i)
12892 {
12893 for (const auto &cell : this->active_cell_iterators())
12894 {
12895 cell->clear_refine_flag();
12896 cell->set_coarsen_flag();
12897 }
12898 execute_coarsening_and_refinement();
12899 }
12900}
12901
12902
12903#endif
12904/*-------------------- refine/coarsen flags -------------------------*/
12905
12906#ifndef DOXYGEN
12907
12908template <int dim, int spacedim>
12910void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
12911{
12912 v.resize(dim * n_active_cells(), false);
12913 std::vector<bool>::iterator i = v.begin();
12914
12915 for (const auto &cell : this->active_cell_iterators())
12916 for (unsigned int j = 0; j < dim; ++j, ++i)
12917 if (cell->refine_flag_set() & (1 << j))
12918 *i = true;
12919
12920 Assert(i == v.end(), ExcInternalError());
12921}
12922
12923
12924
12925template <int dim, int spacedim>
12927void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
12928{
12929 std::vector<bool> v;
12930 save_refine_flags(v);
12931 write_bool_vector(mn_tria_refine_flags_begin,
12932 v,
12934 out);
12935}
12936
12937
12938
12939template <int dim, int spacedim>
12942{
12943 std::vector<bool> v;
12944 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
12945 load_refine_flags(v);
12946}
12947
12948
12949
12950template <int dim, int spacedim>
12952void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
12953{
12954 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
12955
12956 std::vector<bool>::const_iterator i = v.begin();
12957 for (const auto &cell : this->active_cell_iterators())
12958 {
12959 unsigned int ref_case = 0;
12960
12961 for (unsigned int j = 0; j < dim; ++j, ++i)
12962 if (*i == true)
12963 ref_case += 1 << j;
12965 ExcGridReadError());
12966 if (ref_case > 0)
12967 cell->set_refine_flag(RefinementCase<dim>(ref_case));
12968 else
12969 cell->clear_refine_flag();
12970 }
12971
12972 Assert(i == v.end(), ExcInternalError());
12973}
12974
12975
12976
12977template <int dim, int spacedim>
12980 std::vector<bool> &v) const
12981{
12982 v.resize(n_active_cells(), false);
12983 std::vector<bool>::iterator i = v.begin();
12984 for (const auto &cell : this->active_cell_iterators())
12985 {
12986 *i = cell->coarsen_flag_set();
12987 ++i;
12988 }
12989
12990 Assert(i == v.end(), ExcInternalError());
12991}
12992
12993
12994
12995template <int dim, int spacedim>
12997void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
12998{
12999 std::vector<bool> v;
13000 save_coarsen_flags(v);
13001 write_bool_vector(mn_tria_coarsen_flags_begin,
13002 v,
13004 out);
13005}
13006
13007
13008
13009template <int dim, int spacedim>
13012{
13013 std::vector<bool> v;
13014 read_bool_vector(mn_tria_coarsen_flags_begin,
13015 v,
13017 in);
13018 load_coarsen_flags(v);
13019}
13020
13021
13022
13023template <int dim, int spacedim>
13026 const std::vector<bool> &v)
13027{
13028 Assert(v.size() == n_active_cells(), ExcGridReadError());
13029
13030 std::vector<bool>::const_iterator i = v.begin();
13031 for (const auto &cell : this->active_cell_iterators())
13032 {
13033 if (*i == true)
13034 cell->set_coarsen_flag();
13035 else
13036 cell->clear_coarsen_flag();
13037 ++i;
13038 }
13039
13040 Assert(i == v.end(), ExcInternalError());
13041}
13042
13043
13044template <int dim, int spacedim>
13047{
13048 return anisotropic_refinement;
13049}
13050
13051
13052#endif
13053
13054namespace internal
13055{
13056 namespace
13057 {
13058 std::vector<std::vector<bool>>
13060 const std::vector<std::unique_ptr<
13062 {
13063 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13064 for (unsigned int level = 0; level < levels.size(); ++level)
13065 coarsen_flags[level] = levels[level]->coarsen_flags;
13066 return coarsen_flags;
13067 }
13068
13069 std::vector<std::vector<std::uint8_t>>
13071 const std::vector<std::unique_ptr<
13073 {
13074 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13075 for (unsigned int level = 0; level < levels.size(); ++level)
13076 refine_flags[level] = levels[level]->refine_flags;
13077 return refine_flags;
13078 }
13079 } // namespace
13080} // namespace internal
13081
13082
13083/*-------------------- user data/flags -------------------------*/
13084
13085
13086namespace
13087{
13088 // clear user data of cells
13089 void
13090 clear_user_data(std::vector<std::unique_ptr<
13092 {
13093 for (auto &level : levels)
13094 level->cells.clear_user_data();
13095 }
13096
13097
13098 // clear user data of faces
13099 void
13101 {
13102 if (faces->dim == 2)
13103 {
13104 faces->lines.clear_user_data();
13105 }
13106
13107
13108 if (faces->dim == 3)
13109 {
13110 faces->lines.clear_user_data();
13111 faces->quads.clear_user_data();
13112 }
13113 }
13114} // namespace
13115
13116#ifndef DOXYGEN
13117
13118template <int dim, int spacedim>
13121{
13122 // let functions in anonymous namespace do their work
13123 ::clear_user_data(levels);
13124 if (dim > 1)
13125 ::clear_user_data(faces.get());
13126}
13127
13128
13129
13130namespace
13131{
13132 void
13133 clear_user_flags_line(
13134 unsigned int dim,
13135 std::vector<
13136 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13137 &levels,
13139 {
13140 if (dim == 1)
13141 {
13142 for (const auto &level : levels)
13143 level->cells.clear_user_flags();
13144 }
13145 else if (dim == 2 || dim == 3)
13146 {
13147 faces->lines.clear_user_flags();
13148 }
13149 else
13150 {
13152 }
13153 }
13154} // namespace
13155
13156
13157template <int dim, int spacedim>
13160{
13161 ::clear_user_flags_line(dim, levels, faces.get());
13162}
13163
13164
13165
13166namespace
13167{
13168 void
13169 clear_user_flags_quad(
13170 unsigned int dim,
13171 std::vector<
13172 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13173 &levels,
13175 {
13176 if (dim == 1)
13177 {
13178 // nothing to do in 1d
13179 }
13180 else if (dim == 2)
13181 {
13182 for (const auto &level : levels)
13183 level->cells.clear_user_flags();
13184 }
13185 else if (dim == 3)
13186 {
13187 faces->quads.clear_user_flags();
13188 }
13189 else
13190 {
13192 }
13193 }
13194} // namespace
13195
13196
13197template <int dim, int spacedim>
13200{
13201 ::clear_user_flags_quad(dim, levels, faces.get());
13202}
13203
13204
13205
13206namespace
13207{
13208 void
13209 clear_user_flags_hex(
13210 unsigned int dim,
13211 std::vector<
13212 std::unique_ptr<internal::TriangulationImplementation::TriaLevel>>
13213 &levels,
13215 {
13216 if (dim == 1)
13217 {
13218 // nothing to do in 1d
13219 }
13220 else if (dim == 2)
13221 {
13222 // nothing to do in 2d
13223 }
13224 else if (dim == 3)
13225 {
13226 for (const auto &level : levels)
13227 level->cells.clear_user_flags();
13228 }
13229 else
13230 {
13232 }
13233 }
13234} // namespace
13235
13236
13237template <int dim, int spacedim>
13240{
13241 ::clear_user_flags_hex(dim, levels, faces.get());
13242}
13243
13244
13245
13246template <int dim, int spacedim>
13249{
13250 clear_user_flags_line();
13251 clear_user_flags_quad();
13252 clear_user_flags_hex();
13253}
13254
13255
13256
13257template <int dim, int spacedim>
13259void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
13260{
13261 save_user_flags_line(out);
13262
13263 if (dim >= 2)
13264 save_user_flags_quad(out);
13265
13266 if (dim >= 3)
13267 save_user_flags_hex(out);
13268
13269 if (dim >= 4)
13271}
13272
13273
13274
13275template <int dim, int spacedim>
13277void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
13278{
13279 // clear vector and append
13280 // all the stuff later on
13281 v.clear();
13282
13283 std::vector<bool> tmp;
13284
13285 save_user_flags_line(tmp);
13286 v.insert(v.end(), tmp.begin(), tmp.end());
13287
13288 if (dim >= 2)
13289 {
13290 save_user_flags_quad(tmp);
13291 v.insert(v.end(), tmp.begin(), tmp.end());
13292 }
13293
13294 if (dim >= 3)
13295 {
13296 save_user_flags_hex(tmp);
13297 v.insert(v.end(), tmp.begin(), tmp.end());
13298 }
13299
13300 if (dim >= 4)
13302}
13303
13304
13305
13306template <int dim, int spacedim>
13309{
13310 load_user_flags_line(in);
13311
13312 if (dim >= 2)
13313 load_user_flags_quad(in);
13314
13315 if (dim >= 3)
13316 load_user_flags_hex(in);
13317
13318 if (dim >= 4)
13320}
13321
13322
13323
13324template <int dim, int spacedim>
13326void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
13327{
13328 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13329 std::vector<bool> tmp;
13330
13331 // first extract the flags
13332 // belonging to lines
13333 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13334 // and set the lines
13335 load_user_flags_line(tmp);
13336
13337 if (dim >= 2)
13338 {
13339 tmp.clear();
13340 tmp.insert(tmp.end(),
13341 v.begin() + n_lines(),
13342 v.begin() + n_lines() + n_quads());
13343 load_user_flags_quad(tmp);
13344 }
13345
13346 if (dim >= 3)
13347 {
13348 tmp.clear();
13349 tmp.insert(tmp.end(),
13350 v.begin() + n_lines() + n_quads(),
13351 v.begin() + n_lines() + n_quads() + n_hexs());
13352 load_user_flags_hex(tmp);
13353 }
13354
13355 if (dim >= 4)
13357}
13358
13359
13360
13361template <int dim, int spacedim>
13364 std::vector<bool> &v) const
13365{
13366 v.resize(n_lines(), false);
13367 std::vector<bool>::iterator i = v.begin();
13368 line_iterator line = begin_line(), endl = end_line();
13369 for (; line != endl; ++line, ++i)
13370 *i = line->user_flag_set();
13371
13372 Assert(i == v.end(), ExcInternalError());
13373}
13374
13375
13376
13377template <int dim, int spacedim>
13379void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
13380{
13381 std::vector<bool> v;
13382 save_user_flags_line(v);
13383 write_bool_vector(mn_tria_line_user_flags_begin,
13384 v,
13386 out);
13387}
13388
13389
13390
13391template <int dim, int spacedim>
13394{
13395 std::vector<bool> v;
13396 read_bool_vector(mn_tria_line_user_flags_begin,
13397 v,
13399 in);
13400 load_user_flags_line(v);
13401}
13402
13403
13404
13405template <int dim, int spacedim>
13408 const std::vector<bool> &v)
13409{
13410 Assert(v.size() == n_lines(), ExcGridReadError());
13411
13412 line_iterator line = begin_line(), endl = end_line();
13413 std::vector<bool>::const_iterator i = v.begin();
13414 for (; line != endl; ++line, ++i)
13415 if (*i == true)
13416 line->set_user_flag();
13417 else
13418 line->clear_user_flag();
13419
13420 Assert(i == v.end(), ExcInternalError());
13421}
13422
13423#endif
13424
13425namespace
13426{
13427 template <typename Iterator>
13428 bool
13429 get_user_flag(const Iterator &i)
13430 {
13431 return i->user_flag_set();
13432 }
13433
13434
13435
13436 template <int structdim, int dim, int spacedim>
13437 bool
13439 {
13441 return false;
13442 }
13443
13444
13445
13446 template <typename Iterator>
13447 void
13448 set_user_flag(const Iterator &i)
13449 {
13450 i->set_user_flag();
13451 }
13452
13453
13454
13455 template <int structdim, int dim, int spacedim>
13456 void
13458 {
13460 }
13461
13462
13463
13464 template <typename Iterator>
13465 void
13466 clear_user_flag(const Iterator &i)
13467 {
13468 i->clear_user_flag();
13469 }
13470
13471
13472
13473 template <int structdim, int dim, int spacedim>
13474 void
13475 clear_user_flag(
13477 {
13479 }
13480} // namespace
13481
13482#ifndef DOXYGEN
13483
13484template <int dim, int spacedim>
13487 std::vector<bool> &v) const
13488{
13489 v.resize(n_quads(), false);
13490
13491 if (dim >= 2)
13492 {
13493 std::vector<bool>::iterator i = v.begin();
13494 quad_iterator quad = begin_quad(), endq = end_quad();
13495 for (; quad != endq; ++quad, ++i)
13496 *i = get_user_flag(quad);
13497
13498 Assert(i == v.end(), ExcInternalError());
13499 }
13500}
13501
13502
13503
13504template <int dim, int spacedim>
13506void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
13507{
13508 std::vector<bool> v;
13509 save_user_flags_quad(v);
13510 write_bool_vector(mn_tria_quad_user_flags_begin,
13511 v,
13513 out);
13514}
13515
13516
13517
13518template <int dim, int spacedim>
13521{
13522 std::vector<bool> v;
13523 read_bool_vector(mn_tria_quad_user_flags_begin,
13524 v,
13526 in);
13527 load_user_flags_quad(v);
13528}
13529
13530
13531
13532template <int dim, int spacedim>
13535 const std::vector<bool> &v)
13536{
13537 Assert(v.size() == n_quads(), ExcGridReadError());
13538
13539 if (dim >= 2)
13540 {
13541 quad_iterator quad = begin_quad(), endq = end_quad();
13542 std::vector<bool>::const_iterator i = v.begin();
13543 for (; quad != endq; ++quad, ++i)
13544 if (*i == true)
13545 set_user_flag(quad);
13546 else
13547 clear_user_flag(quad);
13548
13549 Assert(i == v.end(), ExcInternalError());
13550 }
13551}
13552
13553
13554
13555template <int dim, int spacedim>
13558 std::vector<bool> &v) const
13559{
13560 v.resize(n_hexs(), false);
13561
13562 if (dim >= 3)
13563 {
13564 std::vector<bool>::iterator i = v.begin();
13565 hex_iterator hex = begin_hex(), endh = end_hex();
13566 for (; hex != endh; ++hex, ++i)
13567 *i = get_user_flag(hex);
13568
13569 Assert(i == v.end(), ExcInternalError());
13570 }
13571}
13572
13573
13574
13575template <int dim, int spacedim>
13577void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
13578{
13579 std::vector<bool> v;
13580 save_user_flags_hex(v);
13581 write_bool_vector(mn_tria_hex_user_flags_begin,
13582 v,
13584 out);
13585}
13586
13587
13588
13589template <int dim, int spacedim>
13592{
13593 std::vector<bool> v;
13594 read_bool_vector(mn_tria_hex_user_flags_begin,
13595 v,
13597 in);
13598 load_user_flags_hex(v);
13599}
13600
13601
13602
13603template <int dim, int spacedim>
13606 const std::vector<bool> &v)
13607{
13608 Assert(v.size() == n_hexs(), ExcGridReadError());
13609
13610 if (dim >= 3)
13611 {
13612 hex_iterator hex = begin_hex(), endh = end_hex();
13613 std::vector<bool>::const_iterator i = v.begin();
13614 for (; hex != endh; ++hex, ++i)
13615 if (*i == true)
13616 set_user_flag(hex);
13617 else
13618 clear_user_flag(hex);
13619
13620 Assert(i == v.end(), ExcInternalError());
13621 }
13622}
13623
13624
13625
13626template <int dim, int spacedim>
13629 std::vector<unsigned int> &v) const
13630{
13631 // clear vector and append all the
13632 // stuff later on
13633 v.clear();
13634
13635 std::vector<unsigned int> tmp;
13636
13637 save_user_indices_line(tmp);
13638 v.insert(v.end(), tmp.begin(), tmp.end());
13639
13640 if (dim >= 2)
13641 {
13642 save_user_indices_quad(tmp);
13643 v.insert(v.end(), tmp.begin(), tmp.end());
13644 }
13645
13646 if (dim >= 3)
13647 {
13648 save_user_indices_hex(tmp);
13649 v.insert(v.end(), tmp.begin(), tmp.end());
13650 }
13651
13652 if (dim >= 4)
13654}
13655
13656
13657
13658template <int dim, int spacedim>
13661 const std::vector<unsigned int> &v)
13662{
13663 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
13664 std::vector<unsigned int> tmp;
13665
13666 // first extract the indices
13667 // belonging to lines
13668 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
13669 // and set the lines
13670 load_user_indices_line(tmp);
13671
13672 if (dim >= 2)
13673 {
13674 tmp.clear();
13675 tmp.insert(tmp.end(),
13676 v.begin() + n_lines(),
13677 v.begin() + n_lines() + n_quads());
13678 load_user_indices_quad(tmp);
13679 }
13680
13681 if (dim >= 3)
13682 {
13683 tmp.clear();
13684 tmp.insert(tmp.end(),
13685 v.begin() + n_lines() + n_quads(),
13686 v.begin() + n_lines() + n_quads() + n_hexs());
13687 load_user_indices_hex(tmp);
13688 }
13689
13690 if (dim >= 4)
13692}
13693
13694
13695
13696template <int dim, int spacedim>
13698void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
13699{
13700 // Save triangulation information.
13701 {
13702 std::ofstream ofs_tria(file_basename + "_triangulation.data");
13703 AssertThrow(ofs_tria.fail() == false, ExcIO());
13704
13705 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
13706 save(oa,
13708 }
13709
13710 // Save attached data.
13711 {
13712 std::ofstream ofs_info(file_basename + ".info");
13713 ofs_info
13714 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
13715 << std::endl
13717 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
13718 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
13719 << this->n_global_active_cells() << std::endl;
13720 }
13721
13722 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
13723}
13724
13725
13726
13727template <int dim, int spacedim>
13730{
13731 // Load triangulation information.
13732 {
13733 std::ifstream ifs_tria(file_basename + "_triangulation.data");
13734 AssertThrow(ifs_tria.fail() == false, ExcIO());
13735
13736 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
13737 load(ia,
13739 }
13740
13741 // Load attached data.
13743 n_global_active_cells;
13744 {
13745 std::ifstream ifs_info(std::string(file_basename) + ".info");
13746 AssertThrow(ifs_info.fail() == false, ExcIO());
13747 std::string firstline;
13748 std::getline(ifs_info, firstline);
13750 attached_count_variable >> n_global_active_cells;
13751 }
13752
13753 AssertThrow(numcpus == 1,
13754 ExcMessage("Incompatible number of CPUs found in .info file."));
13755
13756 const auto expected_version =
13758 spacedim>::version_number;
13760 ExcMessage(
13761 "The information saved in the file you are trying "
13762 "to read the triangulation from was written with an "
13763 "incompatible file format version and cannot be read."));
13764 Assert(this->n_global_active_cells() == n_global_active_cells,
13765 ExcMessage("The number of cells of the triangulation differs "
13766 "from the number of cells written into the .info file."));
13767
13768 // Clear all of the callback data, as explained in the documentation of
13769 // register_data_attach().
13770 this->cell_attached_data.n_attached_data_sets = 0;
13771 this->cell_attached_data.n_attached_deserialize =
13773
13774 this->load_attached_data(0,
13775 this->n_global_active_cells(),
13776 this->n_active_cells(),
13780
13781 this->update_cell_relations();
13782}
13783
13784#endif
13785namespace
13786{
13787 template <typename Iterator>
13788 unsigned int
13789 get_user_index(const Iterator &i)
13790 {
13791 return i->user_index();
13792 }
13793
13794
13795
13796 template <int structdim, int dim, int spacedim>
13797 unsigned int
13800 {
13803 }
13804
13805
13806
13807 template <typename Iterator>
13808 void
13809 set_user_index(const Iterator &i, const unsigned int x)
13810 {
13811 i->set_user_index(x);
13812 }
13813
13814
13815
13816 template <int structdim, int dim, int spacedim>
13817 void
13818 set_user_index(
13820 const unsigned int)
13821 {
13823 }
13824} // namespace
13825
13826#ifndef DOXYGEN
13827
13828template <int dim, int spacedim>
13831 std::vector<unsigned int> &v) const
13832{
13833 v.resize(n_lines(), 0);
13834 std::vector<unsigned int>::iterator i = v.begin();
13835 line_iterator line = begin_line(), endl = end_line();
13836 for (; line != endl; ++line, ++i)
13837 *i = line->user_index();
13838}
13839
13840
13841
13842template <int dim, int spacedim>
13845 const std::vector<unsigned int> &v)
13846{
13847 Assert(v.size() == n_lines(), ExcGridReadError());
13848
13849 line_iterator line = begin_line(), endl = end_line();
13850 std::vector<unsigned int>::const_iterator i = v.begin();
13851 for (; line != endl; ++line, ++i)
13852 line->set_user_index(*i);
13853}
13854
13855
13856template <int dim, int spacedim>
13859 std::vector<unsigned int> &v) const
13860{
13861 v.resize(n_quads(), 0);
13862
13863 if (dim >= 2)
13864 {
13865 std::vector<unsigned int>::iterator i = v.begin();
13866 quad_iterator quad = begin_quad(), endq = end_quad();
13867 for (; quad != endq; ++quad, ++i)
13868 *i = get_user_index(quad);
13869 }
13870}
13871
13872
13873
13874template <int dim, int spacedim>
13877 const std::vector<unsigned int> &v)
13878{
13879 Assert(v.size() == n_quads(), ExcGridReadError());
13880
13881 if (dim >= 2)
13882 {
13883 quad_iterator quad = begin_quad(), endq = end_quad();
13884 std::vector<unsigned int>::const_iterator i = v.begin();
13885 for (; quad != endq; ++quad, ++i)
13886 set_user_index(quad, *i);
13887 }
13888}
13889
13890
13891template <int dim, int spacedim>
13894 std::vector<unsigned int> &v) const
13895{
13896 v.resize(n_hexs(), 0);
13897
13898 if (dim >= 3)
13899 {
13900 std::vector<unsigned int>::iterator i = v.begin();
13901 hex_iterator hex = begin_hex(), endh = end_hex();
13902 for (; hex != endh; ++hex, ++i)
13903 *i = get_user_index(hex);
13904 }
13905}
13906
13907
13908
13909template <int dim, int spacedim>
13912 const std::vector<unsigned int> &v)
13913{
13914 Assert(v.size() == n_hexs(), ExcGridReadError());
13915
13916 if (dim >= 3)
13917 {
13918 hex_iterator hex = begin_hex(), endh = end_hex();
13919 std::vector<unsigned int>::const_iterator i = v.begin();
13920 for (; hex != endh; ++hex, ++i)
13921 set_user_index(hex, *i);
13922 }
13923}
13924
13925#endif
13926
13927
13928//---------------- user pointers ----------------------------------------//
13929
13930
13931namespace
13932{
13933 template <typename Iterator>
13934 void *
13935 get_user_pointer(const Iterator &i)
13936 {
13937 return i->user_pointer();
13938 }
13939
13940
13941
13942 template <int structdim, int dim, int spacedim>
13943 void *
13946 {
13948 return nullptr;
13949 }
13950
13951
13952
13953 template <typename Iterator>
13954 void
13955 set_user_pointer(const Iterator &i, void *x)
13956 {
13957 i->set_user_pointer(x);
13958 }
13959
13960
13961
13962 template <int structdim, int dim, int spacedim>
13963 void
13964 set_user_pointer(
13966 void *)
13967 {
13969 }
13970} // namespace
13971
13972#ifndef DOXYGEN
13973
13974template <int dim, int spacedim>
13977 std::vector<void *> &v) const
13978{
13979 // clear vector and append all the
13980 // stuff later on
13981 v.clear();
13982
13983 std::vector<void *> tmp;
13984
13985 save_user_pointers_line(tmp);
13986 v.insert(v.end(), tmp.begin(), tmp.end());
13987
13988 if (dim >= 2)
13989 {
13990 save_user_pointers_quad(tmp);
13991 v.insert(v.end(), tmp.begin(), tmp.end());
13992 }
13993
13994 if (dim >= 3)
13995 {
13996 save_user_pointers_hex(tmp);
13997 v.insert(v.end(), tmp.begin(), tmp.end());
13998 }
13999
14000 if (dim >= 4)
14002}
14003
14004
14005
14006template <int dim, int spacedim>
14009 const std::vector<void *> &v)
14010{
14011 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14012 std::vector<void *> tmp;
14013
14014 // first extract the pointers
14015 // belonging to lines
14016 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14017 // and set the lines
14018 load_user_pointers_line(tmp);
14019
14020 if (dim >= 2)
14021 {
14022 tmp.clear();
14023 tmp.insert(tmp.end(),
14024 v.begin() + n_lines(),
14025 v.begin() + n_lines() + n_quads());
14026 load_user_pointers_quad(tmp);
14027 }
14028
14029 if (dim >= 3)
14030 {
14031 tmp.clear();
14032 tmp.insert(tmp.end(),
14033 v.begin() + n_lines() + n_quads(),
14034 v.begin() + n_lines() + n_quads() + n_hexs());
14035 load_user_pointers_hex(tmp);
14036 }
14037
14038 if (dim >= 4)
14040}
14041
14042
14043
14044template <int dim, int spacedim>
14047 std::vector<void *> &v) const
14048{
14049 v.resize(n_lines(), nullptr);
14050 std::vector<void *>::iterator i = v.begin();
14051 line_iterator line = begin_line(), endl = end_line();
14052 for (; line != endl; ++line, ++i)
14053 *i = line->user_pointer();
14054}
14055
14056
14057
14058template <int dim, int spacedim>
14061 const std::vector<void *> &v)
14062{
14063 Assert(v.size() == n_lines(), ExcGridReadError());
14064
14065 line_iterator line = begin_line(), endl = end_line();
14066 std::vector<void *>::const_iterator i = v.begin();
14067 for (; line != endl; ++line, ++i)
14068 line->set_user_pointer(*i);
14069}
14070
14071
14072
14073template <int dim, int spacedim>
14076 std::vector<void *> &v) const
14077{
14078 v.resize(n_quads(), nullptr);
14079
14080 if (dim >= 2)
14081 {
14082 std::vector<void *>::iterator i = v.begin();
14083 quad_iterator quad = begin_quad(), endq = end_quad();
14084 for (; quad != endq; ++quad, ++i)
14085 *i = get_user_pointer(quad);
14086 }
14087}
14088
14089
14090
14091template <int dim, int spacedim>
14094 const std::vector<void *> &v)
14095{
14096 Assert(v.size() == n_quads(), ExcGridReadError());
14097
14098 if (dim >= 2)
14099 {
14100 quad_iterator quad = begin_quad(), endq = end_quad();
14101 std::vector<void *>::const_iterator i = v.begin();
14102 for (; quad != endq; ++quad, ++i)
14103 set_user_pointer(quad, *i);
14104 }
14105}
14106
14107
14108template <int dim, int spacedim>
14111 std::vector<void *> &v) const
14112{
14113 v.resize(n_hexs(), nullptr);
14114
14115 if (dim >= 3)
14116 {
14117 std::vector<void *>::iterator i = v.begin();
14118 hex_iterator hex = begin_hex(), endh = end_hex();
14119 for (; hex != endh; ++hex, ++i)
14120 *i = get_user_pointer(hex);
14121 }
14122}
14123
14124
14125
14126template <int dim, int spacedim>
14129 const std::vector<void *> &v)
14130{
14131 Assert(v.size() == n_hexs(), ExcGridReadError());
14132
14133 if (dim >= 3)
14134 {
14135 hex_iterator hex = begin_hex(), endh = end_hex();
14136 std::vector<void *>::const_iterator i = v.begin();
14137 for (; hex != endh; ++hex, ++i)
14138 set_user_pointer(hex, *i);
14139 }
14140}
14141
14142#endif
14143
14144/*------------------------ Cell iterator functions ------------------------*/
14145
14146#ifndef DOXYGEN
14147
14148template <int dim, int spacedim>
14151 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
14152{
14153 switch (dim)
14154 {
14155 case 1:
14156 return begin_raw_line(level);
14157 case 2:
14158 return begin_raw_quad(level);
14159 case 3:
14160 return begin_raw_hex(level);
14161 default:
14163 return raw_cell_iterator();
14164 }
14165}
14166
14167
14168
14169template <int dim, int spacedim>
14172 Triangulation<dim, spacedim>::begin(const unsigned int level) const
14173{
14174 switch (dim)
14175 {
14176 case 1:
14177 return begin_line(level);
14178 case 2:
14179 return begin_quad(level);
14180 case 3:
14181 return begin_hex(level);
14182 default:
14183 Assert(false, ExcImpossibleInDim(dim));
14184 return cell_iterator();
14185 }
14186}
14187
14188
14189
14190template <int dim, int spacedim>
14193 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
14194{
14195 switch (dim)
14196 {
14197 case 1:
14198 return begin_active_line(level);
14199 case 2:
14200 return begin_active_quad(level);
14201 case 3:
14202 return begin_active_hex(level);
14203 default:
14205 return active_cell_iterator();
14206 }
14207}
14208
14209
14210
14211template <int dim, int spacedim>
14215{
14216 const unsigned int level = levels.size() - 1;
14217 if (levels[level]->cells.n_objects() == 0)
14218 return end(level);
14219
14220 // find the last raw iterator on
14221 // this level
14222 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
14223 level,
14224 levels[level]->cells.n_objects() - 1);
14225
14226 // then move to the last used one
14227 if (ri->used() == true)
14228 return ri;
14229 while ((--ri).state() == IteratorState::valid)
14230 if (ri->used() == true)
14231 return ri;
14232 return ri;
14233}
14234
14235
14236
14237template <int dim, int spacedim>
14241{
14242 // get the last used cell
14243 cell_iterator cell = last();
14244
14245 if (cell != end())
14246 {
14247 // then move to the last active one
14248 if (cell->is_active() == true)
14249 return cell;
14250 while ((--cell).state() == IteratorState::valid)
14251 if (cell->is_active() == true)
14252 return cell;
14253 }
14254 return cell;
14255}
14256
14257
14258
14259template <int dim, int spacedim>
14263 const CellId &cell_id) const
14264{
14265 Assert(
14266 this->contains_cell(cell_id),
14267 ExcMessage(
14268 "CellId is invalid for this triangulation.\n"
14269 "Either the provided CellId does not correspond to a cell in this "
14270 "triangulation object, or, in case you are using a parallel "
14271 "triangulation, may correspond to an artificial cell that is less "
14272 "refined on this processor. In the case of "
14273 "parallel::fullydistributed::Triangulation, the corresponding coarse "
14274 "cell might not be accessible by the current process."));
14275
14276 cell_iterator cell(
14277 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
14278
14279 for (const auto &child_index : cell_id.get_child_indices())
14280 cell = cell->child(static_cast<unsigned int>(child_index));
14281
14282 return cell;
14283}
14284
14285
14286
14287template <int dim, int spacedim>
14289bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
14290{
14291 const auto coarse_cell_index =
14292 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
14293
14295 return false;
14296
14297 cell_iterator cell(this, 0, coarse_cell_index);
14298
14299 for (const auto &child_index : cell_id.get_child_indices())
14300 {
14301 if (cell->has_children() == false)
14302 return false;
14303 cell = cell->child(static_cast<unsigned int>(child_index));
14304 }
14305
14306 return true;
14307}
14308
14309
14310
14311template <int dim, int spacedim>
14315{
14316 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14317 -1,
14318 -1);
14319}
14320
14321
14322
14323template <int dim, int spacedim>
14326 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
14327{
14328 // This function may be called on parallel triangulations on levels
14329 // that exist globally, but not on the local portion of the
14330 // triangulation. In that case, just return the end iterator.
14331 //
14332 // We need to use levels.size() instead of n_levels() because the
14333 // latter function uses the cache, but we need to be able to call
14334 // this function at a time when the cache is not currently up to
14335 // date.
14336 if (level >= levels.size())
14337 {
14338 Assert(level < n_global_levels(),
14339 ExcInvalidLevel(level, n_global_levels()));
14340 return end();
14341 }
14342
14343 // Query whether the given level is valid for the local portion of the
14344 // triangulation.
14345 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14346 if (level < levels.size() - 1)
14347 return begin_raw(level + 1);
14348 else
14349 return end();
14350}
14351
14352
14353template <int dim, int spacedim>
14356 Triangulation<dim, spacedim>::end(const unsigned int level) const
14357{
14358 // This function may be called on parallel triangulations on levels
14359 // that exist globally, but not on the local portion of the
14360 // triangulation. In that case, just return the end iterator.
14361 //
14362 // We need to use levels.size() instead of n_levels() because the
14363 // latter function uses the cache, but we need to be able to call
14364 // this function at a time when the cache is not currently up to
14365 // date.
14366 if (level >= levels.size())
14367 {
14368 Assert(level < n_global_levels(),
14369 ExcInvalidLevel(level, n_global_levels()));
14370 return end();
14371 }
14372
14373 // Query whether the given level is valid for the local portion of the
14374 // triangulation.
14375 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14376 if (level < levels.size() - 1)
14377 return begin(level + 1);
14378 else
14379 return end();
14380}
14381
14382
14383template <int dim, int spacedim>
14386 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
14387{
14388 // This function may be called on parallel triangulations on levels
14389 // that exist globally, but not on the local portion of the
14390 // triangulation. In that case, just return the end iterator.
14391 //
14392 // We need to use levels.size() instead of n_levels() because the
14393 // latter function uses the cache, but we need to be able to call
14394 // this function at a time when the cache is not currently up to
14395 // date.
14396 if (level >= levels.size())
14397 {
14398 Assert(level < n_global_levels(),
14399 ExcInvalidLevel(level, n_global_levels()));
14400 return end();
14401 }
14402
14403 // Query whether the given level is valid for the local portion of the
14404 // triangulation.
14405 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14406 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
14407 begin_active(level + 1));
14408}
14409
14410
14411
14412template <int dim, int spacedim>
14416 const
14417{
14419 begin(), end());
14420}
14421
14422
14423template <int dim, int spacedim>
14428{
14429 return IteratorRange<
14431 end());
14432}
14433
14434
14435
14436template <int dim, int spacedim>
14440 cell_iterators_on_level(const unsigned int level) const
14441{
14443 begin(level), end(level));
14444}
14445
14446
14447
14448template <int dim, int spacedim>
14452 active_cell_iterators_on_level(const unsigned int level) const
14453{
14454 return IteratorRange<
14456 begin_active(level), end_active(level));
14457}
14458#endif
14459
14460/*------------------------ Face iterator functions ------------------------*/
14461
14462#ifndef DOXYGEN
14463
14464template <int dim, int spacedim>
14468{
14469 switch (dim)
14470 {
14471 case 1:
14472 Assert(false, ExcImpossibleInDim(1));
14473 return raw_face_iterator();
14474 case 2:
14475 return begin_line();
14476 case 3:
14477 return begin_quad();
14478 default:
14480 return face_iterator();
14481 }
14482}
14483
14484
14485
14486template <int dim, int spacedim>
14490{
14491 switch (dim)
14492 {
14493 case 1:
14494 Assert(false, ExcImpossibleInDim(1));
14495 return raw_face_iterator();
14496 case 2:
14497 return begin_active_line();
14498 case 3:
14499 return begin_active_quad();
14500 default:
14502 return active_face_iterator();
14503 }
14504}
14505
14506
14507
14508template <int dim, int spacedim>
14512{
14513 switch (dim)
14514 {
14515 case 1:
14516 Assert(false, ExcImpossibleInDim(1));
14517 return raw_face_iterator();
14518 case 2:
14519 return end_line();
14520 case 3:
14521 return end_quad();
14522 default:
14524 return raw_face_iterator();
14525 }
14526}
14527
14528
14529
14530template <int dim, int spacedim>
14535{
14536 return IteratorRange<
14538 begin_active_face(), end_face());
14539}
14540
14541/*------------------------ Vertex iterator functions ------------------------*/
14542
14543
14544template <int dim, int spacedim>
14548{
14549 vertex_iterator i =
14550 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14551 if (i.state() != IteratorState::valid)
14552 return i;
14553 // This loop will end because every triangulation has used vertices.
14554 while (i->used() == false)
14555 if ((++i).state() != IteratorState::valid)
14556 return i;
14557 return i;
14558}
14559
14560
14561
14562template <int dim, int spacedim>
14566{
14567 // every vertex is active
14568 return begin_vertex();
14569}
14570
14571
14572
14573template <int dim, int spacedim>
14577{
14578 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14579 -1,
14581}
14582
14583#endif
14584
14585
14586/*------------------------ Line iterator functions ------------------------*/
14587
14588#ifndef DOXYGEN
14589
14590template <int dim, int spacedim>
14593 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
14594{
14595 // This function may be called on parallel triangulations on levels
14596 // that exist globally, but not on the local portion of the
14597 // triangulation. In that case, just return the end iterator.
14598 //
14599 // We need to use levels.size() instead of n_levels() because the
14600 // latter function uses the cache, but we need to be able to call
14601 // this function at a time when the cache is not currently up to
14602 // date.
14603 if (level >= levels.size())
14604 {
14605 Assert(level < n_global_levels(),
14606 ExcInvalidLevel(level, n_global_levels()));
14607 return end_line();
14608 }
14609
14610 switch (dim)
14611 {
14612 case 1:
14613 // Query whether the given level is valid for the local portion of the
14614 // triangulation.
14615 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14616
14617 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14618 return end_line();
14619
14620 return raw_line_iterator(
14621 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14622
14623 default:
14624 Assert(level == 0, ExcFacesHaveNoLevel());
14625 return raw_line_iterator(
14626 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14627 }
14628}
14629
14630
14631template <int dim, int spacedim>
14634 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
14635{
14636 // level is checked in begin_raw
14637 raw_line_iterator ri = begin_raw_line(level);
14638 if (ri.state() != IteratorState::valid)
14639 return ri;
14640 while (ri->used() == false)
14641 if ((++ri).state() != IteratorState::valid)
14642 return ri;
14643 return ri;
14644}
14645
14646
14647
14648template <int dim, int spacedim>
14652 const unsigned int level) const
14653{
14654 // level is checked in begin_raw
14655 line_iterator i = begin_line(level);
14656 if (i.state() != IteratorState::valid)
14657 return i;
14658 while (i->has_children())
14659 if ((++i).state() != IteratorState::valid)
14660 return i;
14661 return i;
14662}
14663
14664
14665
14666template <int dim, int spacedim>
14670{
14671 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14672 -1,
14673 -1);
14674}
14675
14676#endif
14677
14678/*------------------------ Quad iterator functions ------------------------*/
14679
14680#ifndef DOXYGEN
14681
14682template <int dim, int spacedim>
14685 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
14686{
14687 // This function may be called on parallel triangulations on levels
14688 // that exist globally, but not on the local portion of the
14689 // triangulation. In that case, just return the end iterator.
14690 //
14691 // We need to use levels.size() instead of n_levels() because the
14692 // latter function uses the cache, but we need to be able to call
14693 // this function at a time when the cache is not currently up to
14694 // date.
14695 if (level >= levels.size())
14696 {
14697 Assert(level < n_global_levels(),
14698 ExcInvalidLevel(level, n_global_levels()));
14699 return end_quad();
14700 }
14701
14702 switch (dim)
14703 {
14704 case 1:
14705 Assert(false, ExcImpossibleInDim(1));
14706 return raw_hex_iterator();
14707 case 2:
14708 {
14709 // Query whether the given level is valid for the local portion of the
14710 // triangulation.
14711 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14712
14713 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14714 return end_quad();
14715
14716 return raw_quad_iterator(
14717 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14718 }
14719
14720 case 3:
14721 {
14722 Assert(level == 0, ExcFacesHaveNoLevel());
14723
14724 return raw_quad_iterator(
14725 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
14726 }
14727
14728
14729 default:
14731 return raw_hex_iterator();
14732 }
14733}
14734
14735
14736
14737template <int dim, int spacedim>
14740 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
14741{
14742 // level is checked in begin_raw
14743 raw_quad_iterator ri = begin_raw_quad(level);
14744 if (ri.state() != IteratorState::valid)
14745 return ri;
14746 while (ri->used() == false)
14747 if ((++ri).state() != IteratorState::valid)
14748 return ri;
14749 return ri;
14750}
14751
14752
14753
14754template <int dim, int spacedim>
14758 const unsigned int level) const
14759{
14760 // level is checked in begin_raw
14761 quad_iterator i = begin_quad(level);
14762 if (i.state() != IteratorState::valid)
14763 return i;
14764 while (i->has_children())
14765 if ((++i).state() != IteratorState::valid)
14766 return i;
14767 return i;
14768}
14769
14770
14771
14772template <int dim, int spacedim>
14776{
14777 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14778 -1,
14779 -1);
14780}
14781
14782#endif
14783
14784/*------------------------ Hex iterator functions ------------------------*/
14785
14786#ifndef DOXYGEN
14787
14788template <int dim, int spacedim>
14791 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
14792{
14793 // This function may be called on parallel triangulations on levels
14794 // that exist globally, but not on the local portion of the
14795 // triangulation. In that case, just return the end iterator.
14796 //
14797 // We need to use levels.size() instead of n_levels() because the
14798 // latter function uses the cache, but we need to be able to call
14799 // this function at a time when the cache is not currently up to
14800 // date.
14801 if (level >= levels.size())
14802 {
14803 Assert(level < n_global_levels(),
14804 ExcInvalidLevel(level, n_global_levels()));
14805 return end_hex();
14806 }
14807
14808 switch (dim)
14809 {
14810 case 1:
14811 case 2:
14812 Assert(false, ExcImpossibleInDim(1));
14813 return raw_hex_iterator();
14814 case 3:
14815 {
14816 // Query whether the given level is valid for the local portion of the
14817 // triangulation.
14818 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
14819
14820 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
14821 return end_hex();
14822
14823 return raw_hex_iterator(
14824 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
14825 }
14826
14827 default:
14829 return raw_hex_iterator();
14830 }
14831}
14832
14833
14834
14835template <int dim, int spacedim>
14838 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
14839{
14840 // level is checked in begin_raw
14841 raw_hex_iterator ri = begin_raw_hex(level);
14842 if (ri.state() != IteratorState::valid)
14843 return ri;
14844 while (ri->used() == false)
14845 if ((++ri).state() != IteratorState::valid)
14846 return ri;
14847 return ri;
14848}
14849
14850
14851
14852template <int dim, int spacedim>
14856{
14857 // level is checked in begin_raw
14858 hex_iterator i = begin_hex(level);
14859 if (i.state() != IteratorState::valid)
14860 return i;
14861 while (i->has_children())
14862 if ((++i).state() != IteratorState::valid)
14863 return i;
14864 return i;
14865}
14866
14867
14868
14869template <int dim, int spacedim>
14873{
14874 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
14875 -1,
14876 -1);
14877}
14878
14879#endif
14880
14881// -------------------------------- number of cells etc ---------------
14882
14883
14884namespace internal
14885{
14886 namespace TriangulationImplementation
14887 {
14888 inline unsigned int
14890 {
14891 return c.n_lines;
14892 }
14893
14894
14895 inline unsigned int
14898 {
14899 return c.n_active_lines;
14900 }
14901
14902
14903 inline unsigned int
14905 {
14906 return c.n_quads;
14907 }
14908
14909
14910 inline unsigned int
14913 {
14914 return c.n_active_quads;
14915 }
14916
14917
14918 inline unsigned int
14920 {
14921 return c.n_hexes;
14922 }
14923
14924
14925 inline unsigned int
14928 {
14929 return c.n_active_hexes;
14930 }
14931 } // namespace TriangulationImplementation
14932} // namespace internal
14933
14934#ifndef DOXYGEN
14935
14936template <int dim, int spacedim>
14938unsigned int Triangulation<dim, spacedim>::n_cells() const
14939{
14941}
14942
14943
14944template <int dim, int spacedim>
14947{
14949}
14950
14951template <int dim, int spacedim>
14955{
14956 return n_active_cells();
14957}
14958
14959template <int dim, int spacedim>
14963{
14964 return n_cells(0);
14965}
14966
14967template <int dim, int spacedim>
14969unsigned int Triangulation<dim, spacedim>::n_faces() const
14970{
14971 switch (dim)
14972 {
14973 case 1:
14974 return n_used_vertices();
14975 case 2:
14976 return n_lines();
14977 case 3:
14978 return n_quads();
14979 default:
14981 }
14982 return 0;
14983}
14984
14985
14986template <int dim, int spacedim>
14989{
14990 switch (dim)
14991 {
14992 case 1:
14993 return n_vertices();
14994 case 2:
14995 return n_raw_lines();
14996 case 3:
14997 return n_raw_quads();
14998 default:
15000 }
15001 return 0;
15002}
15003
15004
15005template <int dim, int spacedim>
15008{
15009 switch (dim)
15010 {
15011 case 1:
15012 return n_used_vertices();
15013 case 2:
15014 return n_active_lines();
15015 case 3:
15016 return n_active_quads();
15017 default:
15019 }
15020 return 0;
15021}
15022
15023
15024template <int dim, int spacedim>
15027 const unsigned int level) const
15028{
15029 switch (dim)
15030 {
15031 case 1:
15032 return n_raw_lines(level);
15033 case 2:
15034 return n_raw_quads(level);
15035 case 3:
15036 return n_raw_hexs(level);
15037 default:
15039 }
15040 return 0;
15041}
15042
15043
15044
15045template <int dim, int spacedim>
15048 const unsigned int level) const
15049{
15050 switch (dim)
15051 {
15052 case 1:
15053 return n_lines(level);
15054 case 2:
15055 return n_quads(level);
15056 case 3:
15057 return n_hexs(level);
15058 default:
15060 }
15061 return 0;
15062}
15063
15064
15065
15066template <int dim, int spacedim>
15069 const unsigned int level) const
15070{
15071 switch (dim)
15072 {
15073 case 1:
15074 return n_active_lines(level);
15075 case 2:
15076 return n_active_quads(level);
15077 case 3:
15078 return n_active_hexs(level);
15079 default:
15081 }
15082 return 0;
15083}
15084
15085
15086template <int dim, int spacedim>
15089{
15090 if (anisotropic_refinement == false)
15091 {
15092 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
15093 if (n_active_cells(lvl) != 0)
15094 return true;
15095 }
15096 else
15097 {
15098 for (const auto &cell : active_cell_iterators())
15099 for (const auto &i : cell->face_indices())
15100 if (cell->face(i)->has_children())
15101 return true;
15102 }
15103 return false;
15104}
15105
15106
15107template <int dim, int spacedim>
15109unsigned int Triangulation<dim, spacedim>::n_lines() const
15110{
15111 return number_cache.n_lines;
15112}
15113
15114
15115
15116template <int dim, int spacedim>
15119 const unsigned int level) const
15120{
15121 if (dim == 1)
15122 {
15123 AssertIndexRange(level, n_levels());
15124 return levels[level]->cells.n_objects();
15125 }
15126
15127 Assert(false, ExcFacesHaveNoLevel());
15128 return 0;
15129}
15130
15131
15132template <int dim, int spacedim>
15135{
15136 if (dim == 1)
15137 {
15139 return 0;
15140 }
15141
15142 return faces->lines.n_objects();
15143}
15144
15145
15146template <int dim, int spacedim>
15149 const unsigned int level) const
15150{
15151 AssertIndexRange(level, number_cache.n_lines_level.size());
15152 Assert(dim == 1, ExcFacesHaveNoLevel());
15153 return number_cache.n_lines_level[level];
15154}
15155
15156
15157template <int dim, int spacedim>
15160{
15161 return number_cache.n_active_lines;
15162}
15163
15164
15165template <int dim, int spacedim>
15168 const unsigned int level) const
15169{
15170 AssertIndexRange(level, number_cache.n_lines_level.size());
15171 Assert(dim == 1, ExcFacesHaveNoLevel());
15172
15173 return number_cache.n_active_lines_level[level];
15174}
15175#endif
15176
15177template <>
15178unsigned int
15180{
15181 return 0;
15182}
15183
15184
15185template <>
15186unsigned int
15187Triangulation<1, 1>::n_quads(const unsigned int) const
15188{
15189 return 0;
15190}
15191
15192
15193template <>
15194unsigned int
15195Triangulation<1, 1>::n_raw_quads(const unsigned int) const
15196{
15197 return 0;
15198}
15199
15200
15201template <>
15202unsigned int
15203Triangulation<1, 1>::n_raw_hexs(const unsigned int) const
15204{
15205 return 0;
15206}
15207
15208
15209template <>
15210unsigned int
15212{
15213 return 0;
15214}
15215
15216
15217template <>
15218unsigned int
15220{
15221 return 0;
15222}
15223
15224
15225
15226template <>
15227unsigned int
15229{
15230 return 0;
15231}
15232
15233
15234template <>
15235unsigned int
15236Triangulation<1, 2>::n_quads(const unsigned int) const
15237{
15238 return 0;
15239}
15240
15241
15242template <>
15243unsigned int
15244Triangulation<1, 2>::n_raw_quads(const unsigned int) const
15245{
15246 return 0;
15247}
15248
15249
15250template <>
15251unsigned int
15252Triangulation<1, 2>::n_raw_hexs(const unsigned int) const
15253{
15254 return 0;
15255}
15256
15257
15258template <>
15259unsigned int
15261{
15262 return 0;
15263}
15264
15265
15266template <>
15267unsigned int
15269{
15270 return 0;
15271}
15272
15273
15274template <>
15275unsigned int
15277{
15278 return 0;
15279}
15280
15281
15282template <>
15283unsigned int
15284Triangulation<1, 3>::n_quads(const unsigned int) const
15285{
15286 return 0;
15287}
15288
15289
15290template <>
15291unsigned int
15292Triangulation<1, 3>::n_raw_quads(const unsigned int) const
15293{
15294 return 0;
15295}
15296
15297
15298template <>
15299unsigned int
15300Triangulation<1, 3>::n_raw_hexs(const unsigned int) const
15301{
15302 return 0;
15303}
15304
15305
15306template <>
15307unsigned int
15309{
15310 return 0;
15311}
15312
15313
15314template <>
15315unsigned int
15317{
15318 return 0;
15319}
15320
15321#ifndef DOXYGEN
15322
15323template <int dim, int spacedim>
15325unsigned int Triangulation<dim, spacedim>::n_quads() const
15326{
15327 return number_cache.n_quads;
15328}
15329
15330
15331template <int dim, int spacedim>
15334 const unsigned int level) const
15335{
15336 Assert(dim == 2, ExcFacesHaveNoLevel());
15337 AssertIndexRange(level, number_cache.n_quads_level.size());
15338 return number_cache.n_quads_level[level];
15339}
15340
15341#endif
15342
15343template <>
15344unsigned int
15346{
15347 AssertIndexRange(level, n_levels());
15348 return levels[level]->cells.n_objects();
15349}
15350
15351
15352
15353template <>
15354unsigned int
15356{
15357 AssertIndexRange(level, n_levels());
15358 return levels[level]->cells.n_objects();
15359}
15360
15361
15362template <>
15363unsigned int
15364Triangulation<3, 3>::n_raw_quads(const unsigned int) const
15365{
15366 Assert(false, ExcFacesHaveNoLevel());
15367 return 0;
15368}
15369
15370#ifndef DOXYGEN
15371
15372template <int dim, int spacedim>
15375{
15377 return 0;
15378}
15379
15380#endif
15381
15382template <>
15383unsigned int
15385{
15386 return faces->quads.n_objects();
15387}
15388
15389#ifndef DOXYGEN
15390
15391template <int dim, int spacedim>
15394{
15395 return number_cache.n_active_quads;
15396}
15397
15398
15399template <int dim, int spacedim>
15402 const unsigned int level) const
15403{
15404 AssertIndexRange(level, number_cache.n_quads_level.size());
15405 Assert(dim == 2, ExcFacesHaveNoLevel());
15406
15407 return number_cache.n_active_quads_level[level];
15408}
15409
15410
15411template <int dim, int spacedim>
15413unsigned int Triangulation<dim, spacedim>::n_hexs() const
15414{
15415 return 0;
15416}
15417
15418
15419
15420template <int dim, int spacedim>
15422unsigned int Triangulation<dim, spacedim>::n_hexs(const unsigned int) const
15423{
15424 return 0;
15425}
15426
15427
15428
15429template <int dim, int spacedim>
15431unsigned int Triangulation<dim, spacedim>::n_raw_hexs(const unsigned int) const
15432{
15433 return 0;
15434}
15435
15436
15437template <int dim, int spacedim>
15440{
15441 return 0;
15442}
15443
15444
15445
15446template <int dim, int spacedim>
15449 const unsigned int) const
15450{
15451 return 0;
15452}
15453
15454#endif
15455
15456template <>
15457unsigned int
15459{
15460 return number_cache.n_hexes;
15461}
15462
15463
15464
15465template <>
15466unsigned int
15467Triangulation<3, 3>::n_hexs(const unsigned int level) const
15468{
15469 AssertIndexRange(level, number_cache.n_hexes_level.size());
15470
15471 return number_cache.n_hexes_level[level];
15472}
15473
15474
15475
15476template <>
15477unsigned int
15479{
15480 AssertIndexRange(level, n_levels());
15481 return levels[level]->cells.n_objects();
15482}
15483
15484
15485template <>
15486unsigned int
15488{
15489 return number_cache.n_active_hexes;
15490}
15491
15492
15493
15494template <>
15495unsigned int
15497{
15498 AssertIndexRange(level, number_cache.n_hexes_level.size());
15499
15500 return number_cache.n_active_hexes_level[level];
15501}
15502
15503#ifndef DOXYGEN
15504
15505template <int dim, int spacedim>
15508{
15509 return std::count(vertices_used.begin(), vertices_used.end(), true);
15510}
15511
15512
15513
15514template <int dim, int spacedim>
15516const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
15517{
15518 return vertices_used;
15519}
15520
15521#endif
15522
15523template <>
15524unsigned int
15526{
15527 return 2;
15528}
15529
15530
15531
15532template <>
15533unsigned int
15535{
15536 return 2;
15537}
15538
15539
15540template <>
15541unsigned int
15543{
15544 return 2;
15545}
15546
15547#ifndef DOXYGEN
15548
15549template <int dim, int spacedim>
15552{
15553 cell_iterator cell = begin(0),
15554 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
15555 // store the largest index of the
15556 // vertices used on level 0
15557 unsigned int max_vertex_index = 0;
15558 for (; cell != endc; ++cell)
15559 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15560 if (cell->vertex_index(vertex) > max_vertex_index)
15561 max_vertex_index = cell->vertex_index(vertex);
15562
15563 // store the number of times a cell
15564 // touches a vertex. An unsigned
15565 // int should suffice, even for
15566 // larger dimensions
15567 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
15568 // touch a vertex's usage count
15569 // every time we find an adjacent
15570 // element
15571 for (cell = begin(); cell != endc; ++cell)
15572 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
15573 ++usage_count[cell->vertex_index(vertex)];
15574
15576 static_cast<unsigned int>(
15577 *std::max_element(usage_count.begin(), usage_count.end())));
15578}
15579
15580
15581
15582template <int dim, int spacedim>
15586{
15588}
15589
15590
15591
15592template <int dim, int spacedim>
15595{
15596 return *this;
15597}
15598
15599
15600
15601template <int dim, int spacedim>
15605{
15606 return *this;
15607}
15608
15609
15610
15611template <int dim, int spacedim>
15616{
15617 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
15618 periodicity_vector.begin(),
15619 periodicity_vector.end());
15620
15621 // Now initialize periodic_face_map
15622 update_periodic_face_map();
15623}
15624
15625
15626
15627template <int dim, int spacedim>
15629const typename std::map<
15630 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
15631 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
15632 unsigned int>,
15635{
15636 return periodic_face_map;
15637}
15638
15639
15640template <int dim, int spacedim>
15643{
15644 // We only update the cell relations here for serial triangulations.
15645 // For other triangulations, this is done at other stages of
15646 // mesh creation and mesh refinement.
15648 this))
15649 return;
15650
15651 this->local_cell_relations.clear();
15652 this->local_cell_relations.reserve(this->n_active_cells());
15653
15654 for (const auto &cell : this->active_cell_iterators())
15655 this->local_cell_relations.emplace_back(
15656 cell, ::CellStatus::cell_will_persist);
15657}
15658
15659
15660
15661template <int dim, int spacedim>
15664{
15666 this))
15667 return;
15668
15669 std::vector<CellId> active_cell_old;
15670
15671 // pack data before triangulation gets updated
15672 if (this->cell_attached_data.n_attached_data_sets > 0)
15673 {
15674 // store old active cells to determine cell status after
15675 // coarsening/refinement
15676 active_cell_old.reserve(this->n_active_cells());
15677
15678 for (const auto &cell : this->active_cell_iterators())
15679 {
15680 const bool children_will_be_coarsened =
15681 (cell->level() > 0) && (cell->coarsen_flag_set());
15682
15683 if (children_will_be_coarsened == false)
15684 active_cell_old.emplace_back(cell->id());
15685 else
15686 {
15687 if (cell->parent()->child(0) == cell)
15688 active_cell_old.emplace_back(cell->parent()->id());
15689 }
15690 }
15691
15692 // update cell relations
15693 this->local_cell_relations.clear();
15694 this->local_cell_relations.reserve(this->n_global_active_cells());
15695
15696 std::vector<
15697 std::pair<unsigned int,
15701
15702 for (const auto &cell : this->active_cell_iterators())
15703 {
15704 if (std::find(active_cell_old.begin(),
15705 active_cell_old.end(),
15706 cell->id()) != active_cell_old.end())
15707 {
15708 const unsigned int index =
15709 std::distance(active_cell_old.begin(),
15710 std::find(active_cell_old.begin(),
15711 active_cell_old.end(),
15712 cell->id()));
15713
15714 ::CellStatus status =
15715 cell->refine_flag_set() ?
15718
15719 local_cell_relations_tmp.emplace_back(
15720 index,
15722 cell_relation_t{cell, status});
15723 }
15724 else if (cell->level() > 0 &&
15725 std::find(active_cell_old.begin(),
15726 active_cell_old.end(),
15727 cell->parent()->id()) != active_cell_old.end())
15728 {
15729 const unsigned int index =
15730 std::distance(active_cell_old.begin(),
15731 std::find(active_cell_old.begin(),
15732 active_cell_old.end(),
15733 cell->parent()->id()));
15734
15735 ::CellStatus status;
15736
15737 if (cell->parent()->child_iterator_to_index(cell) == 0)
15739 else
15741
15742 local_cell_relations_tmp.emplace_back(
15743 index,
15745 cell_relation_t{cell->parent(), status});
15746 }
15747 else
15748 {
15750 }
15751 }
15752
15753 std::stable_sort(local_cell_relations_tmp.begin(),
15755 [](const auto &a, const auto &b) {
15756 return a.first < b.first;
15757 });
15758
15759 for (const auto &tmp : local_cell_relations_tmp)
15760 this->local_cell_relations.emplace_back(tmp.second);
15761
15762 // pack data
15763 this->data_serializer.pack_data(
15764 this->local_cell_relations,
15765 this->cell_attached_data.pack_callbacks_fixed,
15766 this->cell_attached_data.pack_callbacks_variable,
15767 this->get_mpi_communicator());
15768
15769 // dummy copy of data
15770 this->data_serializer.dest_data_fixed =
15771 this->data_serializer.src_data_fixed;
15772 this->data_serializer.dest_data_variable =
15773 this->data_serializer.src_data_variable;
15774 this->data_serializer.dest_sizes_variable =
15775 this->data_serializer.src_sizes_variable;
15776 }
15777}
15778
15779
15780
15781template <int dim, int spacedim>
15784{
15786 this))
15787 return;
15788
15789 // transfer data after triangulation got updated
15790 if (this->cell_attached_data.n_attached_data_sets > 0)
15791 {
15792 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
15794 temp;
15795
15796 for (const auto &cell : local_cell_relations)
15797 {
15798 if (cell.first->has_children())
15799 {
15802
15803 temp.emplace_back(cell.first->child(0),
15805 }
15806 else
15807 temp.push_back(cell);
15808 }
15809
15810 this->local_cell_relations = temp;
15811 }
15812}
15813
15814
15815
15816template <int dim, int spacedim>
15819{
15820 // Call our version of prepare_coarsening_and_refinement() even if a derived
15821 // class like parallel::distributed::Triangulation overrides it. Their
15822 // function will be called in their execute_coarsening_and_refinement()
15823 // function. Even in a distributed computation our job here is to reconstruct
15824 // the local part of the mesh and as such checking our flags is enough.
15826
15827 // verify a case with which we have had
15828 // some difficulty in the past (see the
15829 // deal.II/coarsening_* tests)
15830 if (smooth_grid & limit_level_difference_at_vertices)
15832
15833 // Inform all listeners about beginning of refinement.
15834 signals.pre_refinement();
15835
15836 this->pack_data_serial();
15837
15838 execute_coarsening();
15839
15840 const DistortedCellList cells_with_distorted_children = execute_refinement();
15841
15842 // We need to update the cell relations in order to be able to
15843 // deserialize data. Later on, update_cell_relations is called to mark all
15844 // active cells with the cell_will_persist status.
15845 this->unpack_data_serial();
15846
15847 reset_cell_vertex_indices_cache();
15848
15849 // verify a case with which we have had
15850 // some difficulty in the past (see the
15851 // deal.II/coarsening_* tests)
15852 if (smooth_grid & limit_level_difference_at_vertices)
15854
15855 // finally build up neighbor connectivity information, and set
15856 // active cell indices
15857 this->policy->update_neighbors(*this);
15858 reset_active_cell_indices();
15859
15860 reset_global_cell_indices(); // TODO: better place?
15861
15862 // Inform all listeners about end of refinement.
15863 signals.post_refinement();
15864
15865 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
15867
15868 update_periodic_face_map();
15869
15870 if (this->cell_attached_data.n_attached_data_sets == 0)
15871 this->update_cell_relations();
15872
15873# ifdef DEBUG
15874
15875 // In debug mode, we want to check for some consistency of the
15876 // result of this function. Because there are multiple exit
15877 // paths, put this check into a ScopeExit object that is
15878 // executed on each of the exit paths.
15879 //
15880 // Specifically, check on exit of this function that if a quad
15881 // cell has been refined, all of its children have neighbors
15882 // in all directions in which the parent cell has neighbors as
15883 // well. The children's neighbors are either the parent
15884 // neighbor or the parent neighbor's children, or simply one of
15885 // the other children of the current cell. This check is
15886 // useful because if one creates a triangulation with an
15887 // inconsistently ordered set of cells (e.g., because one has
15888 // forgotten to call GridTools::consistently_order_cells()),
15889 // then this relatively simple invariant is violated -- so the
15890 // check here can be used to catch that case, at least
15891 // sometimes.
15892 //
15893 // In 1d, this situation cannot happen. In 3d, we have explicit
15894 // orientation flags to ensure that it is not necessary to re-orient
15895 // cells at the beginning. But in both cases, the invariant should
15896 // still hold as long as the cell is a hypercube.
15897 for (const auto &cell : cell_iterators())
15898 {
15899 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
15900 for (const unsigned int f : cell->face_indices())
15901 if (cell->at_boundary(f) == false)
15902 {
15903 for (const auto &child : cell->child_iterators())
15904 {
15905 Assert(
15906 child->at_boundary(f) == false,
15907 ExcMessage(
15908 "We ended up with a triangulation whose child cells "
15909 "are not connected to their neighbors as expected. "
15910 "When you created the triangulation, did you forget "
15911 "to call GridTools::consistently_order_cells() "
15912 "before calling Triangulation::create_triangulation()?"));
15913 }
15914 }
15915 }
15916# endif
15917}
15918
15919
15920
15921template <int dim, int spacedim>
15924{
15925 unsigned int active_cell_index = 0;
15926 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
15927 if ((cell->used() == false) || cell->has_children())
15928 cell->set_active_cell_index(numbers::invalid_unsigned_int);
15929 else
15930 {
15931 cell->set_active_cell_index(active_cell_index);
15932 ++active_cell_index;
15933 }
15934
15935 Assert(active_cell_index == n_active_cells(), ExcInternalError());
15936}
15937
15938
15939
15940template <int dim, int spacedim>
15943{
15944 {
15946 for (const auto &cell : active_cell_iterators())
15947 cell->set_global_active_cell_index(cell_index++);
15948 }
15949
15950 for (unsigned int l = 0; l < levels.size(); ++l)
15951 {
15953 for (const auto &cell : cell_iterators_on_level(l))
15954 cell->set_global_level_cell_index(cell_index++);
15955 }
15956}
15957
15958
15959
15960template <int dim, int spacedim>
15963{
15964 for (unsigned int l = 0; l < levels.size(); ++l)
15965 {
15966 std::vector<unsigned int> &cache = levels[l]->cell_vertex_indices_cache;
15967 cache.clear();
15968 cache.resize(levels[l]->refine_flags.size() *
15969 ReferenceCells::max_n_vertices<dim>(),
15971 for (const auto &cell : cell_iterators_on_level(l))
15972 {
15973 const unsigned int my_index =
15974 cell->index() * ReferenceCells::max_n_vertices<dim>();
15975
15976 // to reduce the cost of this function when passing down into quads,
15977 // then lines, then vertices, we use a more low-level access method
15978 // for hexahedral cells, where we can streamline most of the logic
15979 const ReferenceCell ref_cell = cell->reference_cell();
15981 for (unsigned int face = 4; face < 6; ++face)
15982 {
15983 const auto face_iter = cell->face(face);
15984 const std::array<types::geometric_orientation, 2>
15985 line_orientations{{face_iter->line_orientation(0),
15986 face_iter->line_orientation(1)}};
15987 std::array<unsigned int, 4> raw_vertex_indices{
15988 {face_iter->line(0)->vertex_index(1 - line_orientations[0]),
15989 face_iter->line(1)->vertex_index(1 - line_orientations[1]),
15990 face_iter->line(0)->vertex_index(line_orientations[0]),
15991 face_iter->line(1)->vertex_index(line_orientations[1])}};
15992
15993 const auto combined_orientation =
15994 levels[l]->face_orientations.get_combined_orientation(
15995 cell->index() * ReferenceCells::max_n_faces<dim>() + face);
15996 std::array<unsigned int, 4> vertex_order{
15997 {ref_cell.standard_to_real_face_vertex(0,
15998 face,
16000 ref_cell.standard_to_real_face_vertex(1,
16001 face,
16003 ref_cell.standard_to_real_face_vertex(2,
16004 face,
16006 ref_cell.standard_to_real_face_vertex(
16007 3, face, combined_orientation)}};
16008
16009 const unsigned int index = my_index + 4 * (face - 4);
16010 for (unsigned int i = 0; i < 4; ++i)
16011 cache[index + i] = raw_vertex_indices[vertex_order[i]];
16012 }
16014 {
16015 const std::array<types::geometric_orientation, 2>
16017 {cell->line_orientation(0), cell->line_orientation(1)}};
16018 std::array<unsigned int, 4> raw_vertex_indices{
16019 {cell->line(0)->vertex_index(1 - line_orientations[0]),
16020 cell->line(1)->vertex_index(1 - line_orientations[1]),
16021 cell->line(0)->vertex_index(line_orientations[0]),
16022 cell->line(1)->vertex_index(line_orientations[1])}};
16023 for (unsigned int i = 0; i < 4; ++i)
16024 cache[my_index + i] = raw_vertex_indices[i];
16025 }
16026 else if (ref_cell == ReferenceCells::Line)
16027 {
16028 cache[my_index + 0] = cell->vertex_index(0);
16029 cache[my_index + 1] = cell->vertex_index(1);
16030 }
16031 else
16032 {
16033 Assert(dim == 2 || dim == 3, ExcInternalError());
16034 for (const unsigned int i : cell->vertex_indices())
16035 {
16036 const auto [face_index, vertex_index] =
16037 ref_cell.standard_vertex_to_face_and_vertex_index(i);
16038 const auto vertex_within_face_index =
16039 ref_cell.standard_to_real_face_vertex(
16040 vertex_index,
16041 face_index,
16042 cell->combined_face_orientation(face_index));
16043 cache[my_index + i] =
16044 cell->face(face_index)
16045 ->vertex_index(vertex_within_face_index);
16046 }
16047 }
16048 }
16049 }
16050}
16051
16052
16053
16054template <int dim, int spacedim>
16057{
16058 // first empty the currently stored objects
16059 periodic_face_map.clear();
16060
16061 typename std::vector<
16063 for (it = periodic_face_pairs_level_0.begin();
16064 it != periodic_face_pairs_level_0.end();
16065 ++it)
16066 {
16068 it->cell[1],
16069 it->face_idx[0],
16070 it->face_idx[1],
16071 it->orientation,
16072 periodic_face_map);
16073
16074 const auto face_reference_cell =
16075 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16076 // for the other way, we need to invert the orientation
16078 it->cell[1],
16079 it->cell[0],
16080 it->face_idx[1],
16081 it->face_idx[0],
16082 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16083 periodic_face_map);
16084 }
16085
16086 // check consistency
16087 typename std::map<std::pair<cell_iterator, unsigned int>,
16088 std::pair<std::pair<cell_iterator, unsigned int>,
16089 types::geometric_orientation>>::const_iterator
16090 it_test;
16091 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16092 ++it_test)
16093 {
16095 it_test->first.first;
16097 it_test->second.first.first;
16098 if (cell_1->level() == cell_2->level())
16099 {
16100 // if both cells have the same neighbor, then the same pair
16101 // order swapped has to be in the map
16102 Assert(periodic_face_map[it_test->second.first].first ==
16103 it_test->first,
16105 }
16106 }
16107}
16108
16109
16110
16111template <int dim, int spacedim>
16114{
16115 std::set<ReferenceCell> reference_cells_set;
16116 for (auto cell : active_cell_iterators())
16117 if (cell->is_locally_owned())
16119
16120 this->reference_cells =
16121 std::vector<ReferenceCell>(reference_cells_set.begin(),
16122 reference_cells_set.end());
16123}
16124
16125
16126
16127template <int dim, int spacedim>
16129const std::vector<ReferenceCell>
16131{
16132 return this->reference_cells;
16133}
16134
16135
16136
16137template <int dim, int spacedim>
16140{
16141 Assert(this->reference_cells.size() > 0,
16142 ExcMessage("You can't ask about the kinds of reference "
16143 "cells used by this triangulation if the "
16144 "triangulation doesn't yet have any cells in it."));
16145 return (this->reference_cells.size() == 1 &&
16146 this->reference_cells[0].is_hyper_cube());
16147}
16148
16149
16150
16151template <int dim, int spacedim>
16154{
16155 Assert(this->reference_cells.size() > 0,
16156 ExcMessage("You can't ask about the kinds of reference "
16157 "cells used by this triangulation if the "
16158 "triangulation doesn't yet have any cells in it."));
16159 return (this->reference_cells.size() == 1 &&
16160 this->reference_cells[0].is_simplex());
16161}
16162
16163
16164
16165template <int dim, int spacedim>
16168{
16169 Assert(this->reference_cells.size() > 0,
16170 ExcMessage("You can't ask about the kinds of reference "
16171 "cells used by this triangulation if the "
16172 "triangulation doesn't yet have any cells in it."));
16173 return reference_cells.size() > 1 ||
16174 ((reference_cells[0].is_hyper_cube() == false) &&
16175 (reference_cells[0].is_simplex() == false));
16176}
16177
16178
16179
16180template <int dim, int spacedim>
16183 const std::function<std::vector<char>(const cell_iterator &,
16184 const ::CellStatus)>
16185 &pack_callback,
16186 const bool returns_variable_size_data)
16187{
16188 unsigned int handle = numbers::invalid_unsigned_int;
16189
16190 // Add new callback function to the corresponding register.
16191 // Encode handles according to returns_variable_size_data.
16193 {
16194 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16195 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16196 }
16197 else
16198 {
16199 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16200 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16201 }
16202
16203 // Increase overall counter.
16204 ++this->cell_attached_data.n_attached_data_sets;
16205
16206 return handle;
16207}
16208
16209
16210
16211template <int dim, int spacedim>
16214 const unsigned int handle,
16215 const std::function<
16216 void(const cell_iterator &,
16217 const ::CellStatus,
16218 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16219 &unpack_callback)
16220{
16221 // perform unpacking
16222 this->data_serializer.unpack_data(this->local_cell_relations,
16223 handle,
16224 unpack_callback);
16225
16226 // decrease counters
16227 --this->cell_attached_data.n_attached_data_sets;
16228 if (this->cell_attached_data.n_attached_deserialize > 0)
16229 --this->cell_attached_data.n_attached_deserialize;
16230
16231 // important: only remove data if we are not in the deserialization
16232 // process. There, each SolutionTransfer registers and unpacks before
16233 // the next one does this, so n_attached_data_sets is only 1 here. This
16234 // would destroy the saved data before the second SolutionTransfer can
16235 // get it. This created a bug that is documented in
16236 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16237
16238 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16239 this->cell_attached_data.n_attached_deserialize == 0)
16240 {
16241 // everybody got their data, time for cleanup!
16242 this->cell_attached_data.pack_callbacks_fixed.clear();
16243 this->cell_attached_data.pack_callbacks_variable.clear();
16244 this->data_serializer.clear();
16245
16246 // reset all cell_status entries after coarsening/refinement
16247 for (auto &cell_rel : this->local_cell_relations)
16249 }
16250}
16251
16252
16253
16254template <int dim, int spacedim>
16257 const unsigned int global_first_cell,
16258 const unsigned int global_num_cells,
16259 const std::string &file_basename) const
16260{
16261 // cast away constness
16262 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16263
16264 // each cell should have been flagged `CellStatus::cell_will_persist`
16265 for (const auto &cell_rel : this->local_cell_relations)
16266 {
16267 (void)cell_rel;
16268 Assert((cell_rel.second == // cell_status
16271 }
16272
16273 if (this->cell_attached_data.n_attached_data_sets > 0)
16274 {
16275 // pack attached data first
16276 tria->data_serializer.pack_data(
16277 tria->local_cell_relations,
16278 tria->cell_attached_data.pack_callbacks_fixed,
16279 tria->cell_attached_data.pack_callbacks_variable,
16280 this->get_mpi_communicator());
16281
16282 // then store buffers in file
16283 tria->data_serializer.save(global_first_cell,
16286 this->get_mpi_communicator());
16287
16288 // and release the memory afterwards
16289 tria->data_serializer.clear();
16290 }
16291
16292 // clear all of the callback data, as explained in the documentation of
16293 // register_data_attach()
16294 {
16295 tria->cell_attached_data.n_attached_data_sets = 0;
16296 tria->cell_attached_data.pack_callbacks_fixed.clear();
16297 tria->cell_attached_data.pack_callbacks_variable.clear();
16298 }
16299}
16300
16301
16302template <int dim, int spacedim>
16305 const unsigned int global_first_cell,
16306 const unsigned int global_num_cells,
16307 const unsigned int local_num_cells,
16308 const std::string &file_basename,
16309 const unsigned int n_attached_deserialize_fixed,
16310 const unsigned int n_attached_deserialize_variable)
16311{
16312 // load saved data, if any was stored
16313 if (this->cell_attached_data.n_attached_deserialize > 0)
16314 {
16315 this->data_serializer.load(global_first_cell,
16321 this->get_mpi_communicator());
16322
16323 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16324
16325# ifdef DEBUG
16326 // the CellStatus of all stored cells should always be
16327 // CellStatus::cell_will_persist.
16328 for (const auto &cell_rel : this->local_cell_relations)
16329 {
16330 Assert((cell_rel.second == // cell_status
16333 }
16334# endif
16335 }
16336}
16337
16338
16339template <int dim, int spacedim>
16342{
16343 levels.clear();
16344 faces.reset();
16345
16346 vertices.clear();
16347 vertices_used.clear();
16348
16349 manifolds.clear();
16350
16351 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16352 if (dim == 1)
16353 {
16354 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16355 vertex_to_boundary_id_map_1d->clear();
16356
16357 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16358 vertex_to_manifold_id_map_1d->clear();
16359 }
16360 else
16361 {
16362 // For dim>1, these maps should simply not exist.
16363 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
16364 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
16365 }
16366
16367
16369}
16370
16371
16372
16373template <int dim, int spacedim>
16377{
16378 const DistortedCellList cells_with_distorted_children =
16379 this->policy->execute_refinement(*this, check_for_distorted_cells);
16380
16381
16382
16383 // re-compute number of lines
16385 *this, levels.size(), number_cache);
16386
16387# ifdef DEBUG
16388 for (const auto &level : levels)
16389 monitor_memory(level->cells, dim);
16390
16391 // check whether really all refinement flags are reset (also of
16392 // previously non-active cells which we may not have touched. If the
16393 // refinement flag of a non-active cell is set, something went wrong
16394 // since the cell-accessors should have caught this)
16395 for (const auto &cell : this->cell_iterators())
16396 Assert(!cell->refine_flag_set(), ExcInternalError());
16397# endif
16398
16400}
16401
16402
16403
16404template <int dim, int spacedim>
16407{
16408 // first find out if there are any cells at all to be coarsened in the
16409 // loop below
16410 const cell_iterator endc = end();
16411 bool do_coarsen = false;
16412 if (levels.size() >= 2)
16413 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16414 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16415 {
16416 do_coarsen = true;
16417 break;
16418 }
16419
16420 if (!do_coarsen)
16421 return;
16422
16423 // create a vector counting for each line and quads how many cells contain
16424 // the respective object. this is used later to decide which lines can be
16425 // deleted after coarsening a cell.
16426 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
16427 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
16428 if (dim > 1)
16429 for (const auto &cell : this->cell_iterators())
16430 {
16431 if (dim > 2)
16432 {
16433 const auto line_indices = internal::TriaAccessorImplementation::
16434 Implementation::get_line_indices_of_cell(*cell);
16435 // avoid a compiler warning by fixing the max number of
16436 // loop iterations to 12
16437 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
16438 for (unsigned int l = 0; l < n_lines; ++l)
16439 ++line_cell_count[line_indices[l]];
16440 for (const unsigned int q : cell->face_indices())
16441 ++quad_cell_count[cell->face_index(q)];
16442 }
16443 else
16444 for (unsigned int l = 0; l < cell->n_lines(); ++l)
16445 ++line_cell_count[cell->line(l)->index()];
16446 }
16447
16448 // Since the loop goes over used cells we only need not worry about
16449 // deleting some cells since the ++operator will then just hop over them
16450 // if we should hit one. Do the loop in the reverse way since we may
16451 // only delete some cells if their neighbors have already been deleted
16452 // (if the latter are on a higher level for example). In effect, only
16453 // those cells are deleted of which originally all children were flagged
16454 // and for which all children are on the same refinement level. Note
16455 // that because of the effects of
16456 // @p{fix_coarsen_flags}, of a cell either all or no children must be
16457 // flagged for coarsening, so it is ok to only check the first child
16458 //
16459 // since we delete the *children* of cells, we can ignore cells on the
16460 // highest level, i.e., level must be less than or equal to
16461 // n_levels()-2.
16462 if (levels.size() >= 2)
16463 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16464 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
16465 {
16466 for (unsigned int child = 0; child < cell->n_children(); ++child)
16467 {
16468 Assert(cell->child(child)->coarsen_flag_set(),
16470 cell->child(child)->clear_coarsen_flag();
16471 }
16472 // inform all listeners that cell coarsening is going to happen
16473 signals.pre_coarsening_on_cell(cell);
16474 // use a separate function, since this is dimension specific
16475 this->policy->delete_children(*this,
16476 cell,
16479 }
16480
16481 // re-compute number of lines and quads
16483 *this, levels.size(), number_cache);
16484}
16485
16486
16487
16488template <int dim, int spacedim>
16491{
16492 // copy a piece of code from prepare_coarsening_and_refinement that
16493 // ensures that the level difference at vertices is limited if so
16494 // desired. we need this code here since at least in 1d we don't
16495 // call the dimension-independent version of
16496 // prepare_coarsening_and_refinement function. in 2d and 3d, having
16497 // this hunk here makes our lives a bit easier as well as it takes
16498 // care of these cases earlier than it would otherwise happen.
16499 //
16500 // the main difference to the code in p_c_and_r is that here we
16501 // absolutely have to make sure that we get things right, i.e. that
16502 // in particular we set flags right if
16503 // limit_level_difference_at_vertices is set. to do so we iterate
16504 // until the flags don't change any more
16505 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16506
16507 bool continue_iterating = true;
16508
16509 do
16510 {
16511 if (smooth_grid & limit_level_difference_at_vertices)
16512 {
16513 Assert(!anisotropic_refinement,
16514 ExcMessage("In case of anisotropic refinement the "
16515 "limit_level_difference_at_vertices flag for "
16516 "mesh smoothing must not be set!"));
16517
16518 // store highest level one of the cells adjacent to a vertex
16519 // belongs to
16520 std::vector<int> vertex_level(vertices.size(), 0);
16521 for (const auto &cell : this->active_cell_iterators())
16522 {
16523 if (cell->refine_flag_set())
16524 for (const unsigned int vertex : cell->vertex_indices())
16525 vertex_level[cell->vertex_index(vertex)] =
16526 std::max(vertex_level[cell->vertex_index(vertex)],
16527 cell->level() + 1);
16528 else if (!cell->coarsen_flag_set())
16529 for (const unsigned int vertex : cell->vertex_indices())
16530 vertex_level[cell->vertex_index(vertex)] =
16531 std::max(vertex_level[cell->vertex_index(vertex)],
16532 cell->level());
16533 else
16534 {
16535 // if coarsen flag is set then tentatively assume
16536 // that the cell will be coarsened. this isn't
16537 // always true (the coarsen flag could be removed
16538 // again) and so we may make an error here. we try
16539 // to correct this by iterating over the entire
16540 // process until we are converged
16541 Assert(cell->coarsen_flag_set(), ExcInternalError());
16542 for (const unsigned int vertex : cell->vertex_indices())
16543 vertex_level[cell->vertex_index(vertex)] =
16544 std::max(vertex_level[cell->vertex_index(vertex)],
16545 cell->level() - 1);
16546 }
16547 }
16548
16549
16550 // loop over all cells in reverse order. do so because we
16551 // can then update the vertex levels on the adjacent
16552 // vertices and maybe already flag additional cells in this
16553 // loop
16554 //
16555 // note that not only may we have to add additional
16556 // refinement flags, but we will also have to remove
16557 // coarsening flags on cells adjacent to vertices that will
16558 // see refinement
16559 active_cell_iterator endc = end();
16560 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
16561 if (cell->refine_flag_set() == false)
16562 {
16563 for (const unsigned int vertex : cell->vertex_indices())
16564 if (vertex_level[cell->vertex_index(vertex)] >=
16565 cell->level() + 1)
16566 {
16567 // remove coarsen flag...
16568 cell->clear_coarsen_flag();
16569
16570 // ...and if necessary also refine the current
16571 // cell, at the same time updating the level
16572 // information about vertices
16573 if (vertex_level[cell->vertex_index(vertex)] >
16574 cell->level() + 1)
16575 {
16576 cell->set_refine_flag();
16577
16578 for (const unsigned int v : cell->vertex_indices())
16579 vertex_level[cell->vertex_index(v)] =
16580 std::max(vertex_level[cell->vertex_index(v)],
16581 cell->level() + 1);
16582 }
16583
16584 // continue and see whether we may, for example,
16585 // go into the inner 'if' above based on a
16586 // different vertex
16587 }
16588 }
16589 }
16590
16591 // loop over all cells and remove the coarsen flags for those cells that
16592 // have sister cells not marked for coarsening, or where some neighbors
16593 // are more refined.
16594
16595 // Coarsen flags of cells with no mother cell, i.e. on the
16596 // coarsest level, are deleted explicitly.
16597 for (const auto &acell : this->active_cell_iterators_on_level(0))
16598 acell->clear_coarsen_flag();
16599
16600 const cell_iterator endc = end();
16601 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
16602 {
16603 // nothing to do if we are already on the finest level
16604 if (cell->is_active())
16605 continue;
16606
16607 const unsigned int n_children = cell->n_children();
16608 unsigned int flagged_children = 0;
16609 for (unsigned int child = 0; child < n_children; ++child)
16610 {
16611 const auto child_cell = cell->child(child);
16612 if (child_cell->is_active() && child_cell->coarsen_flag_set())
16613 {
16615 // clear flag since we don't need it anymore
16616 child_cell->clear_coarsen_flag();
16617 }
16618 }
16619
16620 // flag the children for coarsening again if all children were
16621 // flagged and if the policy allows it
16622 if (flagged_children == n_children &&
16623 this->policy->coarsening_allowed(cell))
16624 for (unsigned int c = 0; c < n_children; ++c)
16625 {
16626 Assert(cell->child(c)->refine_flag_set() == false,
16628
16629 cell->child(c)->set_coarsen_flag();
16630 }
16631 }
16632
16633 // now see if anything has changed in the last iteration of this
16634 // function
16635 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
16636
16639 }
16640 while (continue_iterating == true);
16641}
16642
16643#endif
16644
16645// TODO: merge the following 3 functions since they are the same
16646template <>
16647bool
16649{
16650 // save the flags to determine whether something was changed in the
16651 // course of this function
16652 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16653
16654 // do nothing in 1d, except setting the coarsening flags correctly
16655 fix_coarsen_flags();
16656
16657 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16658
16659 return (flags_before != flags_after);
16660}
16661
16662
16663
16664template <>
16665bool
16667{
16668 // save the flags to determine whether something was changed in the
16669 // course of this function
16670 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16671
16672 // do nothing in 1d, except setting the coarsening flags correctly
16673 fix_coarsen_flags();
16674
16675 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16676
16677 return (flags_before != flags_after);
16678}
16679
16680
16681
16682template <>
16683bool
16685{
16686 // save the flags to determine whether something was changed in the
16687 // course of this function
16688 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
16689
16690 // do nothing in 1d, except setting the coarsening flags correctly
16691 fix_coarsen_flags();
16692
16693 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
16694
16695 return (flags_before != flags_after);
16696}
16697
16698
16699
16700namespace
16701{
16702 // check if the given @param cell marked for coarsening would
16703 // produce an unrefined island. To break up long chains of these
16704 // cells we recursively check our neighbors in case we change this
16705 // cell. This reduces the number of outer iterations dramatically.
16706 template <int dim, int spacedim>
16707 void
16710 {
16711 Assert(cell->has_children(), ExcInternalError());
16712
16713 unsigned int n_neighbors = 0;
16714 // count all neighbors that will be refined along the face of our
16715 // cell after the next step
16716 unsigned int count = 0;
16717 for (const unsigned int n : GeometryInfo<dim>::face_indices())
16718 {
16719 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
16720 cell->neighbor(n);
16721 if (neighbor.state() == IteratorState::valid)
16722 {
16723 ++n_neighbors;
16725 ++count;
16726 }
16727 }
16728 // clear coarsen flags if either all existing neighbors will be
16729 // refined or all but one will be and the cell is in the interior
16730 // of the domain
16731 if (count == n_neighbors ||
16732 (count >= n_neighbors - 1 &&
16734 {
16735 for (unsigned int c = 0; c < cell->n_children(); ++c)
16736 cell->child(c)->clear_coarsen_flag();
16737
16738 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16739 if (!cell->at_boundary(face) &&
16740 (!cell->neighbor(face)->is_active()) &&
16741 (cell_will_be_coarsened(cell->neighbor(face))))
16743 cell->neighbor(face));
16744 }
16745 }
16746
16747
16748 // see if the current cell needs to be refined to avoid unrefined
16749 // islands.
16750 //
16751 // there are sometimes chains of cells that induce refinement of
16752 // each other. to avoid running the loop in
16753 // prepare_coarsening_and_refinement over and over again for each
16754 // one of them, at least for the isotropic refinement case we seek
16755 // to flag neighboring elements as well as necessary. this takes
16756 // care of (slightly pathological) cases like
16757 // deal.II/mesh_smoothing_03
16758 template <int dim, int spacedim>
16759 void
16762 const bool allow_anisotropic_smoothing)
16763 {
16764 Assert(cell->is_active(), ExcInternalError());
16765
16766#ifdef DEBUG
16767 // If this is not a parallel::distributed::Triangulation, then we really
16768 // should only get here if the cell is marked for refinement:
16770 *>(&cell->get_triangulation()) == nullptr)
16771 Assert(cell->refine_flag_set() == false, ExcInternalError());
16772 else
16773 // But if this is a p::d::Triangulation, then we don't have that
16774 // much control and we can get here because mesh smoothing is
16775 // requested but can not be honored because p4est controls
16776 // what gets refined. In that case, we can at least provide
16777 // a better error message.
16778 Assert(cell->refine_flag_set() == false,
16779 ExcMessage(
16780 "The triangulation is trying to avoid unrefined islands "
16781 "during mesh refinement/coarsening, as you had requested "
16782 " by passing the appropriate 'smoothing flags' to the "
16783 "constructor of the triangulation. However, for objects "
16784 "of type parallel::distributed::Triangulation, control "
16785 "over which cells get refined rests with p4est, not the "
16786 "deal.II triangulation, and consequently it is not "
16787 "always possible to avoid unrefined islands in the mesh. "
16788 "Please remove the constructor argument to the triangulation "
16789 "object that requests mesh smoothing."));
16790#endif
16791
16792 // now we provide two algorithms. the first one is the standard
16793 // one, coming from the time, where only isotropic refinement was
16794 // possible. it simply counts the neighbors that are or will be
16795 // refined and compares to the number of other ones. the second
16796 // one does this check independently for each direction: if all
16797 // neighbors in one direction (normally two, at the boundary only
16798 // one) are refined, the current cell is flagged to be refined in
16799 // an according direction.
16800
16801 if (allow_anisotropic_smoothing == false)
16802 {
16803 // use first algorithm
16804 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
16805 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16806 if (!cell->at_boundary(face))
16807 {
16808 if (face_will_be_refined_by_neighbor(cell, face))
16810 else
16812 }
16813
16815 {
16816 cell->clear_coarsen_flag();
16817 cell->set_refine_flag();
16818
16819 // ok, so now we have flagged this cell. if we know that
16820 // there were any unrefined neighbors at all, see if any
16821 // of those will have to be refined as well
16822 if (unrefined_neighbors > 0)
16823 for (const unsigned int face : GeometryInfo<dim>::face_indices())
16824 if (!cell->at_boundary(face) &&
16825 (face_will_be_refined_by_neighbor(cell, face) == false) &&
16826 (cell->neighbor(face)->has_children() == false) &&
16827 (cell->neighbor(face)->refine_flag_set() == false))
16828 possibly_refine_unrefined_island<dim, spacedim>(
16829 cell->neighbor(face), allow_anisotropic_smoothing);
16830 }
16831 }
16832 else
16833 {
16834 // variable to store the cell refine case needed to fulfill
16835 // all smoothing requirements
16838
16839 // use second algorithm, do the check individually for each
16840 // direction
16841 for (unsigned int face_pair = 0;
16843 ++face_pair)
16844 {
16845 // variable to store the cell refine case needed to refine
16846 // at the current face pair in the same way as the
16847 // neighbors do...
16850
16851 for (unsigned int face_index = 0; face_index < 2; ++face_index)
16852 {
16853 unsigned int face = 2 * face_pair + face_index;
16854 // variable to store the refine case (to come) of the
16855 // face under consideration
16857 RefinementCase<dim - 1>::no_refinement;
16858
16859 if (cell->neighbor(face).state() == IteratorState::valid)
16861 cell, face, expected_face_ref_case);
16862 // now extract which refine case would be necessary to
16863 // achieve the same face refinement. set the
16864 // intersection with other requirements for the same
16865 // direction.
16866
16867 // note: using the intersection is not an obvious
16868 // decision, we could also argue that it is more
16869 // natural to use the union. however, intersection is
16870 // the less aggressive tactic and favours a smaller
16871 // number of refined cells over an intensive
16872 // smoothing. this way we try not to lose too much of
16873 // the effort we put in anisotropic refinement
16874 // indicators due to overly aggressive smoothing...
16880 face,
16881 cell->face_orientation(face),
16882 cell->face_flip(face),
16883 cell->face_rotation(face)));
16884 } // for both face indices
16885 // if both requirements sum up to something useful, add
16886 // this to the refine case for smoothing. note: if
16887 // directional_cell_refinement_case is isotropic still,
16888 // then something went wrong...
16894 } // for all face_pairs
16895 // no we collected contributions from all directions. combine
16896 // the new flags with the existing refine case, but only if
16897 // smoothing is required
16899 {
16900 cell->clear_coarsen_flag();
16901 cell->set_refine_flag(cell->refine_flag_set() |
16903 }
16904 }
16905 }
16906} // namespace
16907
16908#ifndef DOXYGEN
16909template <int dim, int spacedim>
16912{
16913 // save the flags to determine whether something was changed in the
16914 // course of this function
16915 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
16916 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
16917
16918 // save the flags at the outset of each loop. we do so in order to
16919 // find out whether something was changed in the present loop, in
16920 // which case we would have to re-run the loop. the other
16921 // possibility to find this out would be to set a flag
16922 // @p{something_changed} to true each time we change something.
16923 // however, sometimes one change in one of the parts of the loop is
16924 // undone by another one, so we might end up in an endless loop. we
16925 // could be tempted to break this loop at an arbitrary number of
16926 // runs, but that would not be a clean solution, since we would
16927 // either have to 1/ break the loop too early, in which case the
16928 // promise that a second call to this function immediately after the
16929 // first one does not change anything, would be broken, or 2/ we do
16930 // as many loops as there are levels. we know that information is
16931 // transported over one level in each run of the loop, so this is
16932 // enough. Unfortunately, each loop is rather expensive, so we chose
16933 // the way presented here
16936
16937 // now for what is done in each loop: we have to fulfill several
16938 // tasks at the same time, namely several mesh smoothing algorithms
16939 // and mesh regularization, by which we mean that the next mesh
16940 // fulfills several requirements such as no double refinement at
16941 // each face or line, etc.
16942 //
16943 // since doing these things at once seems almost impossible (in the
16944 // first year of this library, they were done in two functions, one
16945 // for refinement and one for coarsening, and most things within
16946 // these were done at once, so the code was rather impossible to
16947 // join into this, only, function), we do them one after each
16948 // other. the order in which we do them is such that the important
16949 // tasks, namely regularization, are done last and the least
16950 // important things are done the first. the following order is
16951 // chosen:
16952 //
16953 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
16954 // coarsen flags on level 1 to avoid level 0 cells being created
16955 // by coarsening. As coarsen flags will never be added, this can
16956 // be done once and for all before the actual loop starts.
16957 //
16958 // 1/ do not coarsen a cell if 'most of the neighbors' will be
16959 // refined after the step. This is to prevent occurrence of
16960 // unrefined islands.
16961 //
16962 // 2/ eliminate refined islands in the interior and at the
16963 // boundary. since they don't do much harm besides increasing the
16964 // number of degrees of freedom, doing this has a rather low
16965 // priority.
16966 //
16967 // 3/ limit the level difference of neighboring cells at each
16968 // vertex.
16969 //
16970 // 4/ eliminate unrefined islands. this has higher priority since
16971 // this diminishes the approximation properties not only of the
16972 // unrefined island, but also of the surrounding patch.
16973 //
16974 // 5/ ensure patch level 1. Then the triangulation consists of
16975 // patches, i.e. of cells that are refined once. It follows that
16976 // if at least one of the children of a cell is or will be
16977 // refined than all children need to be refined. This step only
16978 // sets refinement flags and does not set coarsening flags. If
16979 // the patch_level_1 flag is set, then
16980 // eliminate_unrefined_islands, eliminate_refined_inner_islands
16981 // and eliminate_refined_boundary_islands will be fulfilled
16982 // automatically and do not need to be enforced separately.
16983 //
16984 // 6/ take care of the requirement that no double refinement is done
16985 // at each face
16986 //
16987 // 7/ take care that no double refinement is done at each line in 3d
16988 // or higher dimensions.
16989 //
16990 // 8/ make sure that all children of each cell are either flagged
16991 // for coarsening or none of the children is
16992 //
16993 // For some of these steps, it is known that they interact. Namely,
16994 // it is not possible to guarantee that after step 6 another step 5
16995 // would have no effect; the same holds for the opposite order and
16996 // also when taking into account step 7. however, it is important to
16997 // guarantee that step five or six do not undo something that step 5
16998 // did, and step 7 not something of step 6, otherwise the
16999 // requirements will not be satisfied even if the loop
17000 // terminates. this is accomplished by the fact that steps 5 and 6
17001 // only *add* refinement flags and delete coarsening flags
17002 // (therefore, step 6 can't undo something that step 4 already did),
17003 // and step 7 only deletes coarsening flags, never adds some. step 7
17004 // needs also take care that it won't tag cells for refinement for
17005 // which some neighbors are more refined or will be refined.
17006
17007 //------------------------------------
17008 // STEP 0:
17009 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17010 // coarsen flags on level 1 to avoid level 0 cells being created
17011 // by coarsening.
17012 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17013 n_levels() >= 2)
17014 {
17015 for (const auto &cell : active_cell_iterators_on_level(1))
17016 cell->clear_coarsen_flag();
17017 }
17018
17019 bool mesh_changed_in_this_loop = false;
17020 do
17021 {
17022 //------------------------------------
17023 // STEP 1:
17024 // do not coarsen a cell if 'most of the neighbors' will be
17025 // refined after the step. This is to prevent the occurrence
17026 // of unrefined islands. If patch_level_1 is set, this will
17027 // be automatically fulfilled.
17028 if (smooth_grid & do_not_produce_unrefined_islands &&
17029 !(smooth_grid & patch_level_1))
17030 {
17031 for (const auto &cell : cell_iterators())
17032 {
17033 // only do something if this
17034 // cell will be coarsened
17035 if (!cell->is_active() && cell_will_be_coarsened(cell))
17037 }
17038 }
17039
17040
17041 //------------------------------------
17042 // STEP 2:
17043 // eliminate refined islands in the interior and at the
17044 // boundary. since they don't do much harm besides increasing
17045 // the number of degrees of freedom, doing this has a rather
17046 // low priority. If patch_level_1 is set, this will be
17047 // automatically fulfilled.
17048 //
17049 // there is one corner case to consider: if this is a
17050 // distributed triangulation, there may be refined islands on
17051 // the boundary of which we own only part (e.g. a single cell
17052 // in the corner of a domain). the rest of the island is
17053 // ghost cells and it *looks* like the area around it
17054 // (artificial cells) are coarser but this is only because
17055 // they may actually be equally fine on other
17056 // processors. it's hard to detect this case but we can do
17057 // the following: only set coarsen flags to remove this
17058 // refined island if all cells we want to set flags on are
17059 // locally owned
17060 if (smooth_grid & (eliminate_refined_inner_islands |
17061 eliminate_refined_boundary_islands) &&
17062 !(smooth_grid & patch_level_1))
17063 {
17064 for (const auto &cell : cell_iterators())
17065 if (!cell->is_active() ||
17066 (cell->is_active() && cell->refine_flag_set() &&
17067 cell->is_locally_owned()))
17068 {
17069 // check whether all children are active, i.e. not
17070 // refined themselves. This is a precondition that the
17071 // children may be coarsened away. If the cell is only
17072 // flagged for refinement, then all future children
17073 // will be active
17074 bool all_children_active = true;
17075 if (!cell->is_active())
17076 for (unsigned int c = 0; c < cell->n_children(); ++c)
17077 if (!cell->child(c)->is_active() ||
17078 cell->child(c)->is_ghost() ||
17079 cell->child(c)->is_artificial())
17080 {
17081 all_children_active = false;
17082 break;
17083 }
17084
17086 {
17087 // count number of refined and unrefined neighbors
17088 // of cell. neighbors on lower levels are counted
17089 // as unrefined since they can only get to the
17090 // same level as this cell by the next refinement
17091 // cycle
17092 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17093
17094 // Keep track if this cell is at a periodic
17095 // boundary or not. TODO: We do not currently run
17096 // the algorithm for inner islands at a periodic
17097 // boundary (remains to be implemented), but we
17098 // also don't want to consider them
17099 // boundary_island cells as this can interfere
17100 // with 2:1 refinement across periodic faces.
17101 // Instead: just ignore those cells for this
17102 // smoothing operation below.
17103 bool at_periodic_boundary = false;
17104
17105 for (const unsigned int n : cell->face_indices())
17106 {
17107 const cell_iterator neighbor = cell->neighbor(n);
17108 if (neighbor.state() == IteratorState::valid)
17109 {
17111
17114 }
17115 else if (cell->has_periodic_neighbor(n))
17116 {
17118 at_periodic_boundary = true;
17119 }
17120 }
17121
17122 // if all neighbors unrefined: mark this cell for
17123 // coarsening or don't refine if marked for that
17124 //
17125 // also do the distinction between the two
17126 // versions of the eliminate_refined_*_islands
17127 // flag
17128 //
17129 // the last check is whether there are any
17130 // neighbors at all. if not so, then we are (e.g.)
17131 // on the coarsest grid with one cell, for which,
17132 // of course, we do not remove the refine flag.
17134 ((!cell->at_boundary() &&
17135 (smooth_grid & eliminate_refined_inner_islands)) ||
17136 (cell->at_boundary() && !at_periodic_boundary &&
17137 (smooth_grid &
17138 eliminate_refined_boundary_islands))) &&
17139 (total_neighbors != 0))
17140 {
17141 if (!cell->is_active())
17142 for (unsigned int c = 0; c < cell->n_children(); ++c)
17143 {
17144 cell->child(c)->clear_refine_flag();
17145 cell->child(c)->set_coarsen_flag();
17146 }
17147 else
17148 cell->clear_refine_flag();
17149 }
17150 }
17151 }
17152 }
17153
17154 //------------------------------------
17155 // STEP 3:
17156 // limit the level difference of neighboring cells at each
17157 // vertex.
17158 //
17159 // in case of anisotropic refinement this does not make
17160 // sense. as soon as one cell is anisotropically refined, an
17161 // Assertion is thrown. therefore we can ignore this problem
17162 // later on
17163 if (smooth_grid & limit_level_difference_at_vertices)
17164 {
17165 Assert(!anisotropic_refinement,
17166 ExcMessage("In case of anisotropic refinement the "
17167 "limit_level_difference_at_vertices flag for "
17168 "mesh smoothing must not be set!"));
17169
17170 // store highest level one of the cells adjacent to a vertex
17171 // belongs to
17172 std::vector<int> vertex_level(vertices.size(), 0);
17173 for (const auto &cell : active_cell_iterators())
17174 {
17175 if (cell->refine_flag_set())
17176 for (const unsigned int vertex : cell->vertex_indices())
17177 vertex_level[cell->vertex_index(vertex)] =
17178 std::max(vertex_level[cell->vertex_index(vertex)],
17179 cell->level() + 1);
17180 else if (!cell->coarsen_flag_set())
17181 for (const unsigned int vertex : cell->vertex_indices())
17182 vertex_level[cell->vertex_index(vertex)] =
17183 std::max(vertex_level[cell->vertex_index(vertex)],
17184 cell->level());
17185 else
17186 {
17187 // if coarsen flag is set then tentatively assume
17188 // that the cell will be coarsened. this isn't
17189 // always true (the coarsen flag could be removed
17190 // again) and so we may make an error here
17191 Assert(cell->coarsen_flag_set(), ExcInternalError());
17192 for (const unsigned int vertex : cell->vertex_indices())
17193 vertex_level[cell->vertex_index(vertex)] =
17194 std::max(vertex_level[cell->vertex_index(vertex)],
17195 cell->level() - 1);
17196 }
17197 }
17198
17199
17200 // loop over all cells in reverse order. do so because we
17201 // can then update the vertex levels on the adjacent
17202 // vertices and maybe already flag additional cells in this
17203 // loop
17204 //
17205 // note that not only may we have to add additional
17206 // refinement flags, but we will also have to remove
17207 // coarsening flags on cells adjacent to vertices that will
17208 // see refinement
17209 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17210 if (cell->refine_flag_set() == false)
17211 {
17212 for (const unsigned int vertex : cell->vertex_indices())
17213 if (vertex_level[cell->vertex_index(vertex)] >=
17214 cell->level() + 1)
17215 {
17216 // remove coarsen flag...
17217 cell->clear_coarsen_flag();
17218
17219 // ...and if necessary also refine the current
17220 // cell, at the same time updating the level
17221 // information about vertices
17222 if (vertex_level[cell->vertex_index(vertex)] >
17223 cell->level() + 1)
17224 {
17225 cell->set_refine_flag();
17226
17227 for (const unsigned int v : cell->vertex_indices())
17228 vertex_level[cell->vertex_index(v)] =
17229 std::max(vertex_level[cell->vertex_index(v)],
17230 cell->level() + 1);
17231 }
17232
17233 // continue and see whether we may, for example,
17234 // go into the inner'if'
17235 // above based on a
17236 // different vertex
17237 }
17238 }
17239 }
17240
17241 //-----------------------------------
17242 // STEP 4:
17243 // eliminate unrefined islands. this has higher priority
17244 // since this diminishes the approximation properties not
17245 // only of the unrefined island, but also of the surrounding
17246 // patch.
17247 //
17248 // do the loop from finest to coarsest cells since we may
17249 // trigger a cascade by marking cells for refinement which
17250 // may trigger more cells further down below
17251 if (smooth_grid & eliminate_unrefined_islands)
17252 {
17253 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17254 // only do something if cell is not already flagged for
17255 // (isotropic) refinement
17256 if (cell->refine_flag_set() !=
17259 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17260 }
17261
17262 //-------------------------------
17263 // STEP 5:
17264 // ensure patch level 1.
17265 //
17266 // Introduce some terminology:
17267 // - a cell that is refined
17268 // once is a patch of
17269 // level 1 simply called patch.
17270 // - a cell that is globally
17271 // refined twice is called
17272 // a patch of level 2.
17273 // - patch level n says that
17274 // the triangulation consists
17275 // of patches of level n.
17276 // This makes sense only
17277 // if the grid is already at
17278 // least n times globally
17279 // refined.
17280 //
17281 // E.g. from patch level 1 follows: if at least one of the
17282 // children of a cell is or will be refined than enforce all
17283 // children to be refined.
17284
17285 // This step 4 only sets refinement flags and does not set
17286 // coarsening flags.
17287 if (smooth_grid & patch_level_1)
17288 {
17289 // An important assumption (A) is that before calling this
17290 // function the grid was already of patch level 1.
17291
17292 // loop over all cells whose children are all active. (By
17293 // assumption (A) either all or none of the children are
17294 // active). If the refine flag of at least one of the
17295 // children is set then set_refine_flag and
17296 // clear_coarsen_flag of all children.
17297 for (const auto &cell : cell_iterators())
17298 if (!cell->is_active())
17299 {
17300 // ensure the invariant. we can then check whether all
17301 // of its children are further refined or not by
17302 // simply looking at the first child
17304 if (cell->child(0)->has_children() == true)
17305 continue;
17306
17307 // cell is found to be a patch. combine the refine
17308 // cases of all children
17311 for (unsigned int i = 0; i < cell->n_children(); ++i)
17313 combined_ref_case | cell->child(i)->refine_flag_set();
17315 for (unsigned int i = 0; i < cell->n_children(); ++i)
17316 {
17317 cell_iterator child = cell->child(i);
17318
17319 child->clear_coarsen_flag();
17320 child->set_refine_flag(combined_ref_case);
17321 }
17322 }
17323
17324 // The code above dealt with the case where we may get a
17325 // non-patch_level_1 mesh from refinement. Now also deal
17326 // with the case where we could get such a mesh by
17327 // coarsening. Coarsen the children (and remove the
17328 // grandchildren) only if all cell->grandchild(i)
17329 // ->coarsen_flag_set() are set.
17330 //
17331 // for a case where this is a bit tricky, take a look at the
17332 // mesh_smoothing_0[12] testcases
17333 for (const auto &cell : cell_iterators())
17334 {
17335 // check if this cell has active grandchildren. note
17336 // that we know that it is patch_level_1, i.e. if one of
17337 // its children is active then so are all, and it isn't
17338 // going to have any grandchildren at all:
17339 if (cell->is_active() || cell->child(0)->is_active())
17340 continue;
17341
17342 // cell is not active, and so are none of its
17343 // children. check the grandchildren. note that the
17344 // children are also patch_level_1, and so we only ever
17345 // need to check their first child
17346 const unsigned int n_children = cell->n_children();
17347 bool has_active_grandchildren = false;
17348
17349 for (unsigned int i = 0; i < n_children; ++i)
17350 if (cell->child(i)->child(0)->is_active())
17351 {
17353 break;
17354 }
17355
17356 if (has_active_grandchildren == false)
17357 continue;
17358
17359
17360 // ok, there are active grandchildren. see if either all
17361 // or none of them are flagged for coarsening
17362 unsigned int n_grandchildren = 0;
17363
17364 // count all coarsen flags of the grandchildren.
17365 unsigned int n_coarsen_flags = 0;
17366
17367 // cell is not a patch (of level 1) as it has a
17368 // grandchild. Is cell a patch of level 2?? Therefore:
17369 // find out whether all cell->child(i) are patches
17370 for (unsigned int c = 0; c < n_children; ++c)
17371 {
17372 // get at the child. by assumption (A), and the
17373 // check by which we got here, the child is not
17374 // active
17375 cell_iterator child = cell->child(c);
17376
17377 const unsigned int nn_children = child->n_children();
17379
17380 // if child is found to be a patch of active cells
17381 // itself, then add up how many of its children are
17382 // supposed to be coarsened
17383 if (child->child(0)->is_active())
17384 for (unsigned int cc = 0; cc < nn_children; ++cc)
17385 if (child->child(cc)->coarsen_flag_set())
17387 }
17388
17389 // if not all grandchildren are supposed to be coarsened
17390 // (e.g. because some simply don't have the flag set, or
17391 // because they are not active and therefore cannot
17392 // carry the flag), then remove the coarsen flag from
17393 // all of the active grandchildren. note that there may
17394 // be coarsen flags on the grandgrandchildren -- we
17395 // don't clear them here, but we'll get to them in later
17396 // iterations if necessary
17397 //
17398 // there is nothing we have to do if no coarsen flags
17399 // have been set at all
17401 for (unsigned int c = 0; c < n_children; ++c)
17402 {
17403 const cell_iterator child = cell->child(c);
17404 if (child->child(0)->is_active())
17405 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
17406 child->child(cc)->clear_coarsen_flag();
17407 }
17408 }
17409 }
17410
17411 //--------------------------------
17412 //
17413 // at the boundary we could end up with cells with negative
17414 // volume or at least with a part, that is negative, if the
17415 // cell is refined anisotropically. we have to check, whether
17416 // that can happen
17417 this->policy->prevent_distorted_boundary_cells(*this);
17418
17419 //-------------------------------
17420 // STEP 6:
17421 // take care of the requirement that no
17422 // double refinement is done at each face
17423 //
17424 // in case of anisotropic refinement it is only likely, but
17425 // not sure, that the cells, which are more refined along a
17426 // certain face common to two cells are on a higher
17427 // level. therefore we cannot be sure, that the requirement
17428 // of no double refinement is fulfilled after a single pass
17429 // of the following actions. We could just wait for the next
17430 // global loop. when this function terminates, the
17431 // requirement will be fulfilled. However, it might be faster
17432 // to insert an inner loop here.
17433 bool changed = true;
17434 while (changed)
17435 {
17436 changed = false;
17437 active_cell_iterator cell = last_active(), endc = end();
17438
17439 for (; cell != endc; --cell)
17440 if (cell->refine_flag_set())
17441 {
17442 // loop over neighbors of cell
17443 for (const auto i : cell->face_indices())
17444 {
17445 // only do something if the face is not at the
17446 // boundary and if the face will be refined with
17447 // the RefineCase currently flagged for
17448 const bool has_periodic_neighbor =
17449 cell->has_periodic_neighbor(i);
17451 !cell->at_boundary(i) || has_periodic_neighbor;
17454 cell->refine_flag_set(), i) !=
17456 {
17457 // 1) if the neighbor has children: nothing to
17458 // worry about. 2) if the neighbor is active
17459 // and a coarser one, ensure, that its
17460 // refine_flag is set 3) if the neighbor is
17461 // active and as refined along the face as our
17462 // current cell, make sure, that no
17463 // coarsen_flag is set. if we remove the
17464 // coarsen flag of our neighbor,
17465 // fix_coarsen_flags() makes sure, that the
17466 // mother cell will not be coarsened
17467 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
17468 {
17469 if ((!has_periodic_neighbor &&
17470 cell->neighbor_is_coarser(i)) ||
17471 (has_periodic_neighbor &&
17472 cell->periodic_neighbor_is_coarser(i)))
17473 {
17474 if (cell->neighbor_or_periodic_neighbor(i)
17475 ->coarsen_flag_set())
17476 cell->neighbor_or_periodic_neighbor(i)
17477 ->clear_coarsen_flag();
17478 // we'll set the refine flag for this
17479 // neighbor below. we note, that we
17480 // have changed something by setting
17481 // the changed flag to true. We do not
17482 // need to do so, if we just removed
17483 // the coarsen flag, as the changed
17484 // flag only indicates the need to
17485 // re-run the inner loop. however, we
17486 // only loop over cells flagged for
17487 // refinement here, so nothing to
17488 // worry about if we remove coarsen
17489 // flags
17490
17491 if (dim == 2)
17492 {
17493 if (smooth_grid &
17494 allow_anisotropic_smoothing)
17495 changed =
17496 has_periodic_neighbor ?
17497 cell->periodic_neighbor(i)
17498 ->flag_for_face_refinement(
17499 cell
17500 ->periodic_neighbor_of_coarser_periodic_neighbor(
17501 i)
17502 .first,
17504 cell->neighbor(i)
17505 ->flag_for_face_refinement(
17506 cell
17507 ->neighbor_of_coarser_neighbor(
17508 i)
17509 .first,
17511 else
17512 {
17513 if (!cell
17514 ->neighbor_or_periodic_neighbor(
17515 i)
17516 ->refine_flag_set())
17517 changed = true;
17518 cell->neighbor_or_periodic_neighbor(i)
17519 ->set_refine_flag();
17520 }
17521 }
17522 else // i.e. if (dim==3)
17523 {
17524 // ugly situations might arise here,
17525 // consider the following situation, which
17526 // shows neighboring cells at the common
17527 // face, where the upper right element is
17528 // coarser at the given face. Now the upper
17529 // child element of the lower left wants to
17530 // refine according to cut_z, such that
17531 // there is a 'horizontal' refinement of the
17532 // face marked with #####
17533 //
17534 // / /
17535 // / /
17536 // *---------------*
17537 // | |
17538 // | |
17539 // | |
17540 // | |
17541 // | |
17542 // | | /
17543 // | |/
17544 // *---------------*
17545 //
17546 //
17547 // *---------------*
17548 // /| /|
17549 // / | ##### / |
17550 // | |
17551 // *---------------*
17552 // /| /|
17553 // / | / |
17554 // | |
17555 // *---------------*
17556 // / /
17557 // / /
17558 //
17559 // this introduces too many hanging nodes
17560 // and the neighboring (coarser) cell (upper
17561 // right) has to be refined. If it is only
17562 // refined according to cut_z, then
17563 // everything is ok:
17564 //
17565 // / /
17566 // / /
17567 // *---------------*
17568 // | |
17569 // | | /
17570 // | |/
17571 // *---------------*
17572 // | |
17573 // | | /
17574 // | |/
17575 // *---------------*
17576 //
17577 //
17578 // *---------------*
17579 // /| /|
17580 // / *---------------*
17581 // /| /|
17582 // *---------------*
17583 // /| /|
17584 // / | / |
17585 // | |
17586 // *---------------*
17587 // / /
17588 // / /
17589 //
17590 // if however the cell wants to refine
17591 // itself in an other way, or if we disallow
17592 // anisotropic smoothing, then simply
17593 // refining the neighbor isotropically is
17594 // not going to work, since this introduces
17595 // a refinement of face ##### with both
17596 // cut_x and cut_y, which is not possible:
17597 //
17598 // / / /
17599 // / / /
17600 // *-------*-------*
17601 // | | |
17602 // | | | /
17603 // | | |/
17604 // *-------*-------*
17605 // | | |
17606 // | | | /
17607 // | | |/
17608 // *-------*-------*
17609 //
17610 //
17611 // *---------------*
17612 // /| /|
17613 // / *---------------*
17614 // /| /|
17615 // *---------------*
17616 // /| /|
17617 // / | / |
17618 // | |
17619 // *---------------*
17620 // / /
17621 // / /
17622 //
17623 // thus, in this case we also need to refine
17624 // our current cell in the new direction:
17625 //
17626 // / / /
17627 // / / /
17628 // *-------*-------*
17629 // | | |
17630 // | | | /
17631 // | | |/
17632 // *-------*-------*
17633 // | | |
17634 // | | | /
17635 // | | |/
17636 // *-------*-------*
17637 //
17638 //
17639 // *-------*-------*
17640 // /| /| /|
17641 // / *-------*-------*
17642 // /| /| /|
17643 // *-------*-------*
17644 // /| / /|
17645 // / | / |
17646 // | |
17647 // *---------------*
17648 // / /
17649 // / /
17650
17651 std::pair<unsigned int, unsigned int>
17652 nb_indices =
17653 has_periodic_neighbor ?
17654 cell
17655 ->periodic_neighbor_of_coarser_periodic_neighbor(
17656 i) :
17657 cell->neighbor_of_coarser_neighbor(i);
17658 unsigned int refined_along_x = 0,
17659 refined_along_y = 0,
17662
17663 const int this_face_index =
17664 cell->face_index(i);
17665
17666 // step 1: detect, along which axis the face
17667 // is currently refined
17668
17669 // first, we need an iterator pointing to
17670 // the parent face. This requires a slight
17671 // detour in case the neighbor is behind a
17672 // periodic face.
17673 const auto parent_face = [&]() {
17674 if (has_periodic_neighbor)
17675 {
17676 const auto neighbor =
17677 cell->periodic_neighbor(i);
17678 const auto parent_face_no =
17679 neighbor
17680 ->periodic_neighbor_of_periodic_neighbor(
17681 nb_indices.first);
17682 auto parent =
17683 neighbor->periodic_neighbor(
17684 nb_indices.first);
17685 return parent->face(parent_face_no);
17686 }
17687 else
17688 return cell->neighbor(i)->face(
17689 nb_indices.first);
17690 }();
17691
17692 if ((this_face_index ==
17693 parent_face->child_index(0)) ||
17694 (this_face_index ==
17695 parent_face->child_index(1)))
17696 {
17697 // this might be an
17698 // anisotropic child. get the
17699 // face refine case of the
17700 // neighbors face and count
17701 // refinements in x and y
17702 // direction.
17703 RefinementCase<dim - 1> frc =
17704 parent_face->refinement_case();
17709 }
17710 else
17711 // this has to be an isotropic
17712 // child
17713 {
17716 }
17717 // step 2: detect, along which axis the face
17718 // has to be refined given the current
17719 // refine flag
17720 RefinementCase<dim - 1> flagged_frc =
17722 cell->refine_flag_set(),
17723 i,
17724 cell->face_orientation(i),
17725 cell->face_flip(i),
17726 cell->face_rotation(i));
17727 if (flagged_frc &
17730 if (flagged_frc &
17733
17734 // step 3: set the refine flag of the
17735 // (coarser and active) neighbor.
17736 if ((smooth_grid &
17737 allow_anisotropic_smoothing) ||
17738 cell->neighbor_or_periodic_neighbor(i)
17739 ->refine_flag_set())
17740 {
17741 if (refined_along_x +
17743 1)
17744 changed |=
17745 cell
17746 ->neighbor_or_periodic_neighbor(i)
17747 ->flag_for_face_refinement(
17748 nb_indices.first,
17749 RefinementCase<dim -
17750 1>::cut_axis(0));
17751 if (refined_along_y +
17753 1)
17754 changed |=
17755 cell
17756 ->neighbor_or_periodic_neighbor(i)
17757 ->flag_for_face_refinement(
17758 nb_indices.first,
17759 RefinementCase<dim -
17760 1>::cut_axis(1));
17761 }
17762 else
17763 {
17764 if (cell
17765 ->neighbor_or_periodic_neighbor(i)
17766 ->refine_flag_set() !=
17769 changed = true;
17770 cell->neighbor_or_periodic_neighbor(i)
17771 ->set_refine_flag();
17772 }
17773
17774 // step 4: if necessary (see above) add to
17775 // the refine flag of the current cell
17776 cell_iterator nb =
17777 cell->neighbor_or_periodic_neighbor(i);
17778 RefinementCase<dim - 1> nb_frc =
17780 nb->refine_flag_set(),
17781 nb_indices.first,
17782 nb->face_orientation(nb_indices.first),
17783 nb->face_flip(nb_indices.first),
17784 nb->face_rotation(nb_indices.first));
17786 !((refined_along_x != 0u) ||
17787 (to_be_refined_along_x != 0u)))
17788 changed |= cell->flag_for_face_refinement(
17789 i,
17792 !((refined_along_y != 0u) ||
17793 (to_be_refined_along_y != 0u)))
17794 changed |= cell->flag_for_face_refinement(
17795 i,
17797 }
17798 } // if neighbor is coarser
17799 else // -> now the neighbor is not coarser
17800 {
17801 cell->neighbor_or_periodic_neighbor(i)
17802 ->clear_coarsen_flag();
17803 const unsigned int nb_nb =
17804 has_periodic_neighbor ?
17805 cell
17806 ->periodic_neighbor_of_periodic_neighbor(
17807 i) :
17808 cell->neighbor_of_neighbor(i);
17809 const cell_iterator neighbor =
17810 cell->neighbor_or_periodic_neighbor(i);
17811 RefinementCase<dim - 1> face_ref_case =
17813 neighbor->refine_flag_set(),
17814 nb_nb,
17815 neighbor->face_orientation(nb_nb),
17816 neighbor->face_flip(nb_nb),
17817 neighbor->face_rotation(nb_nb));
17820 cell->refine_flag_set(),
17821 i,
17822 cell->face_orientation(i),
17823 cell->face_flip(i),
17824 cell->face_rotation(i));
17825 // if the neighbor wants to refine the
17826 // face with cut_x and we want cut_y
17827 // or vice versa, we have to refine
17828 // isotropically at the given face
17829 if ((face_ref_case ==
17833 (face_ref_case ==
17837 {
17838 changed = cell->flag_for_face_refinement(
17839 i, face_ref_case);
17840 neighbor->flag_for_face_refinement(
17842 }
17843 }
17844 }
17845 else //-> the neighbor is not active
17846 {
17847 RefinementCase<dim - 1>
17848 face_ref_case = cell->face(i)->refinement_case(),
17851 cell->refine_flag_set(),
17852 i,
17853 cell->face_orientation(i),
17854 cell->face_flip(i),
17855 cell->face_rotation(i));
17856 // if the face is refined with cut_x and
17857 // we want cut_y or vice versa, we have to
17858 // refine isotropically at the given face
17865 changed =
17866 cell->flag_for_face_refinement(i,
17868 }
17869 }
17870 }
17871 }
17872 }
17873
17874 //------------------------------------
17875 // STEP 7:
17876 // take care that no double refinement is done at each line in 3d or
17877 // higher dimensions.
17878 this->policy->prepare_refinement_dim_dependent(*this);
17879
17880 //------------------------------------
17881 // STEP 8:
17882 // make sure that all children of each cell are either flagged for
17883 // coarsening or none of the children is
17884 fix_coarsen_flags();
17885
17886 // get the refinement and coarsening flags
17888 internal::extract_raw_coarsen_flags(levels);
17889 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
17890
17891 // find out whether something was changed in this loop
17895
17896 // set the flags for the next loop already
17899 }
17901
17902
17903 // find out whether something was really changed in this
17904 // function. Note that @p{..._flags_before_loop} represents the state
17905 // after the last loop, i.e., the present state
17908}
17909
17910
17911
17912template <int dim, int spacedim>
17915 const unsigned int magic_number1,
17916 const std::vector<bool> &v,
17917 const unsigned int magic_number2,
17918 std::ostream &out)
17919{
17920 const unsigned int N = v.size();
17921 unsigned char *flags = new unsigned char[N / 8 + 1];
17922 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17923 flags[i] = 0;
17924
17925 for (unsigned int position = 0; position < N; ++position)
17926 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
17927
17928 AssertThrow(out.fail() == false, ExcIO());
17929
17930 // format:
17931 // 0. magic number
17932 // 1. number of flags
17933 // 2. the flags
17934 // 3. magic number
17935 out << magic_number1 << ' ' << N << std::endl;
17936 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17937 out << static_cast<unsigned int>(flags[i]) << ' ';
17938
17939 out << std::endl << magic_number2 << std::endl;
17940
17941 delete[] flags;
17942
17943 AssertThrow(out.fail() == false, ExcIO());
17944}
17945
17946
17947template <int dim, int spacedim>
17950 const unsigned int magic_number1,
17951 std::vector<bool> &v,
17952 const unsigned int magic_number2,
17953 std::istream &in)
17954{
17955 AssertThrow(in.fail() == false, ExcIO());
17956
17957 unsigned int magic_number;
17958 in >> magic_number;
17959 AssertThrow(magic_number == magic_number1, ExcGridReadError());
17960
17961 unsigned int N;
17962 in >> N;
17963 v.resize(N);
17964
17965 unsigned char *flags = new unsigned char[N / 8 + 1];
17966 unsigned short int tmp;
17967 for (unsigned int i = 0; i < N / 8 + 1; ++i)
17968 {
17969 in >> tmp;
17970 flags[i] = tmp;
17971 }
17972
17973 for (unsigned int position = 0; position != N; ++position)
17974 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
17975
17976 in >> magic_number;
17977 AssertThrow(magic_number == magic_number2, ExcGridReadError());
17978
17979 delete[] flags;
17980
17981 AssertThrow(in.fail() == false, ExcIO());
17982}
17983
17984
17985
17986template <int dim, int spacedim>
17989{
17990 std::size_t mem = 0;
17991 mem += sizeof(MeshSmoothing);
17992 mem += MemoryConsumption::memory_consumption(reference_cells);
17993 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
17995 for (const auto &level : levels)
17998 mem += MemoryConsumption::memory_consumption(vertices_used);
17999 mem += sizeof(manifolds);
18000 mem += sizeof(smooth_grid);
18001 mem += MemoryConsumption::memory_consumption(number_cache);
18002 mem += sizeof(faces);
18003 if (faces)
18005
18006 return mem;
18007}
18008
18009
18010
18011template <int dim, int spacedim>
18014 default;
18015
18016#endif
18017
18018// explicit instantiations
18019#include "grid/tria.inst"
18020
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
Definition array_view.h:949
CellStatus
Definition cell_status.h:31
@ cell_will_be_refined
@ children_will_be_coarsened
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:393
EnableObserverPointer & operator=(const EnableObserverPointer &)
Number * begin_raw()
constexpr void clear()
friend class Tensor
Definition tensor.h:865
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
MPI_Comm get_communicator() const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4127
active_vertex_iterator begin_active_vertex() 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)
virtual void clear()
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
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)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
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 save(Archive &ar, const unsigned int version) const
void reset_global_cell_indices()
face_iterator end_face() const
void reset_active_cell_indices()
cell_iterator create_cell_iterator(const CellId &cell_id) const
cell_iterator begin(const unsigned int level=0) const
void fix_coarsen_flags()
virtual MPI_Comm get_mpi_communicator() 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
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)
raw_cell_iterator end_raw(const unsigned int level) const
line_iterator end_line() const
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
virtual void update_reference_cells()
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)
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_level_cell_index_partitioner(const unsigned int level) const
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
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:4128
void load_user_pointers(const std::vector< void * > &v)
unsigned int register_data_attach(const std::function< std::vector< char >(const cell_iterator &, const ::CellStatus)> &pack_callback, const bool returns_variable_size_data)
void save_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &file_basename) const
void save_user_indices_hex(std::vector< unsigned int > &v) const
DistortedCellList execute_refinement()
void update_cell_relations()
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)
void pack_data_serial()
cell_iterator end() const
virtual bool has_hanging_nodes() const
unsigned int n_raw_cells(const unsigned int level) const
bool contains_cell(const CellId &cell_id) const
void load_attached_data(const unsigned int global_first_cell, const unsigned int global_num_cells, const unsigned int local_num_cells, const std::string &file_basename, const unsigned int n_attached_deserialize_fixed, const unsigned int n_attached_deserialize_variable)
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()
void unpack_data_serial()
const std::vector< bool > & get_used_vertices() const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4129
void save_refine_flags(std::ostream &out) const
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
virtual ~Triangulation() override
unsigned int n_vertices() const
void load(Archive &ar, const unsigned int version)
void save_user_indices(std::vector< unsigned int > &v) const
void notify_ready_to_unpack(const unsigned int handle, const std::function< void(const cell_iterator &, const ::CellStatus, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback)
bool all_reference_cells_are_simplex() const
unsigned int n_raw_hexs(const unsigned int level) const
void set_all_refine_flags()
const std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, types::geometric_orientation > > & get_periodic_face_map() const
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()
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:394
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2590
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2597
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:2573
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2567
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2604
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2583
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2612
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
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:518
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:190
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:519
Point< 2 > second
Definition grid_out.cc:4630
Point< 2 > first
Definition grid_out.cc:4629
unsigned int level
Definition grid_out.cc:4632
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
unsigned int cell_index
IteratorRange< active_cell_iterator > active_cell_iterators_on_level(const unsigned int level) const
IteratorRange< active_face_iterator > active_face_iterators() const
IteratorRange< active_cell_iterator > active_cell_iterators() const
IteratorRange< cell_iterator > cell_iterators_on_level(const unsigned int level) const
IteratorRange< cell_iterator > cell_iterators() const
static ::ExceptionBase & ExcInternalErrorOnCell(int arg1)
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcInteriorQuadCantBeBoundary(int arg1, int arg2, int arg3, int arg4, types::boundary_id arg5)
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcInconsistentLineInfoOfLine(int arg1, int arg2, std::string arg3)
static ::ExceptionBase & ExcCellHasNegativeMeasure(int arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
static ::ExceptionBase & ExcMemoryInexact(int arg1, int arg2)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition exceptions.h:536
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcGridHasInvalidCell(int arg1)
static ::ExceptionBase & ExcMultiplySetLineInfoOfLine(int arg1, int arg2)
#define AssertNothrow(cond, exc)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcInteriorLineCantBeBoundary(int arg1, int arg2, types::boundary_id arg3)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition exceptions.h:559
#define DeclException1(Exception1, type1, outsequence)
Definition exceptions.h:513
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:608
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcInconsistentQuadInfoOfQuad(int arg1, int arg2, int arg3, int arg4, std::string arg5)
typename IteratorSelector::hex_iterator hex_iterator
Definition tria.h:1692
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1683
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1703
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1668
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1644
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1557
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1659
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)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int mn_tria_refine_flags_end
const unsigned int mn_tria_coarsen_flags_end
const unsigned int mn_tria_refine_flags_begin
const unsigned int mn_tria_hex_user_flags_end
const unsigned int mn_tria_line_user_flags_begin
const unsigned int mn_tria_line_user_flags_end
const unsigned int mn_tria_quad_user_flags_end
const unsigned int mn_tria_coarsen_flags_begin
const unsigned int mn_tria_hex_user_flags_begin
const unsigned int mn_tria_quad_user_flags_begin
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:316
std::vector< index_type > data
Definition mpi.cc:740
std::size_t size
Definition mpi.cc:739
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell &reference_cell)
double diameter(const Triangulation< dim, spacedim > &tria)
@ valid
Iterator points to a valid object.
constexpr char N
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
constexpr const ReferenceCell Tetrahedron
constexpr const ReferenceCell Quadrilateral
constexpr const ReferenceCell Invalid
constexpr const ReferenceCell Triangle
constexpr const ReferenceCell Hexahedron
constexpr unsigned int max_n_faces()
constexpr const ReferenceCell Line
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
Definition mpi.cc:97
T max(const T &t, const MPI_Comm mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:112
size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1382
constexpr T fixed_power(const T t)
Definition utilities.h:943
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14896
const Manifold< dim, spacedim > & get_default_flat_manifold()
Definition tria.cc:11998
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:14889
void reserve_space(TriaFaces &tria_faces, const unsigned int new_quads_in_pairs, const unsigned int new_quads_single)
Definition tria.cc:2035
void monitor_memory(const TriaLevel &tria_level, const unsigned int true_dimension)
Definition tria.cc:2234
std::tuple< bool, bool, bool > split_face_orientation(const types::geometric_orientation combined_face_orientation)
constexpr types::global_dof_index invalid_dof_index
Definition types.h:263
constexpr unsigned int invalid_unsigned_int
Definition types.h:232
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:323
constexpr types::manifold_id flat_manifold_id
Definition types.h:336
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:359
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:375
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:346
STL namespace.
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > abs(const ::VectorizedArray< Number, width > &)
unsigned int manifold_id
Definition types.h:165
unsigned int boundary_id
Definition types.h:153
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 std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1738
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:11880
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:11970
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:11961
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:11986
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11884
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11978
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:11950
static void reserve_space_(TriaObjects &obj, const unsigned int size)
Definition tria.cc:3660
static void reserve_space_(TriaFaces &faces, const unsigned structdim, const unsigned int size)
Definition tria.cc:3603
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 2 > &number_cache)
Definition tria.cc:2818
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:11487
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3046
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:11575
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:3954
static void reserve_space_(TriaLevel &level, const unsigned int spacedim, const unsigned int size, const bool orientation_needed)
Definition tria.cc:3623
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3040
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7116
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:4950
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:3018
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:4583
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:11494
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:11808
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 3 > &number_cache)
Definition tria.cc:2925
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:3712
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:11585
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:3816
static void compute_number_cache_dim(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< 1 > &number_cache)
Definition tria.cc:2730
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5405
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5947
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:3225
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5639
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:3492
std::vector< std::vector< CellData< dim > > > cell_infos