deal.II version GIT relicensing-7047-g33e1a45c58 2026-11-07 15:00: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: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1999 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
17#include <deal.II/base/mpi.templates.h>
25
28
33#include <deal.II/grid/tria.h>
40
41#include <boost/archive/text_iarchive.hpp>
42#include <boost/archive/text_oarchive.hpp>
43
44#include <algorithm>
45#include <array>
46#include <cmath>
47#include <cstdint>
48#include <fstream>
49#include <functional>
50#include <limits>
51#include <list>
52#include <map>
53#include <memory>
54#include <numeric>
55#include <vector>
56
57
59
60
61namespace internal
62{
63 namespace TriangulationImplementation
64 {
66 : n_levels(0)
67 , n_lines(0)
68 , n_active_lines(0)
69 // all other fields are
70 // default constructed
71 {}
72
73
74
75 std::size_t
77 {
78 std::size_t mem =
83 MemoryConsumption::memory_consumption(n_active_lines_level);
84
85 if (active_cell_index_partitioner)
86 mem += active_cell_index_partitioner->memory_consumption();
87
88 for (const auto &partitioner : level_cell_index_partitioners)
89 if (partitioner)
90 mem += partitioner->memory_consumption();
91
92 return mem;
93 }
94
95
97 : n_quads(0)
98 , n_active_quads(0)
99 // all other fields are
100 // default constructed
101 {}
102
103
104
105 std::size_t
114
115
116
118 : n_hexes(0)
119 , n_active_hexes(0)
120 // all other fields are
121 // default constructed
122 {}
123
124
125
126 std::size_t
135
136
137
138 template <int dim>
140 : max_children_per_cell(numbers::invalid_unsigned_int)
141 , max_faces_per_cell(numbers::invalid_unsigned_int)
142 , max_lines_per_cell(numbers::invalid_unsigned_int)
143 , max_vertices_per_cell(numbers::invalid_unsigned_int)
144 , max_children_per_face(numbers::invalid_unsigned_int)
145 , max_lines_per_face(numbers::invalid_unsigned_int)
146 {}
147
148
149
150 template <int dim>
152 const std::vector<ReferenceCell<dim>> &reference_cells)
153 : max_children_per_cell(0u)
154 , max_faces_per_cell(0u)
155 , max_lines_per_cell(0u)
156 , max_vertices_per_cell(0u)
157 , max_children_per_face(0u)
158 , max_lines_per_face(0u)
159 {
160 for (const ReferenceCell<dim> &reference_cell : reference_cells)
161 {
164 reference_cell.n_isotropic_children());
166 std::max(max_faces_per_cell, reference_cell.n_faces());
168 std::max(max_lines_per_cell, reference_cell.n_lines());
170 std::max(max_vertices_per_cell, reference_cell.n_vertices());
171
172 for (unsigned int face_no : reference_cell.face_indices())
173 {
174 const auto face_reference_cell =
175 reference_cell.face_reference_cell(face_no);
178 face_reference_cell.n_isotropic_children());
180 std::max(max_lines_per_face, face_reference_cell.n_lines());
181 }
182 }
183 }
184 } // namespace TriangulationImplementation
185
186
187 template <int dim, int spacedim>
190 : variable_size_data_stored(false)
191 {}
192
193
194 template <int dim, int spacedim>
196 void CellAttachedDataSerializer<dim, spacedim>::pack_data(
197 const std::vector<cell_relation_t> &cell_relations,
198 const std::vector<
199 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
200 &pack_callbacks_fixed,
201 const std::vector<
202 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
203 &pack_callbacks_variable,
204 const MPI_Comm &mpi_communicator)
205 {
206 Assert(src_data_fixed.empty(),
207 ExcMessage("Previously packed data has not been released yet!"));
208 Assert(src_sizes_variable.empty(), ExcInternalError());
209
210 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
211 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
212
213 // Store information that we packed variable size data in
214 // a member variable for later.
215 variable_size_data_stored = (n_callbacks_variable > 0);
216
217 // If variable transfer is scheduled, we will store the data size that
218 // each variable size callback function writes in this auxiliary
219 // container. The information will be stored by each cell in this vector
220 // temporarily.
221 std::vector<unsigned int> cell_sizes_variable_cumulative(
222 n_callbacks_variable);
223
224 // Prepare the buffer structure, in which each callback function will
225 // store its data for each active cell.
226 // The outmost shell in this container construct corresponds to the
227 // data packed per cell. The next layer resembles the data that
228 // each callback function packs on the corresponding cell. These
229 // buffers are chains of chars stored in an std::vector<char>.
230 // A visualisation of the data structure:
231 /* clang-format off */
232 // | cell_1 | | cell_2 | ...
233 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
234 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
235 /* clang-format on */
236 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
237 cell_relations.size());
238 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
239 variable_size_data_stored ? cell_relations.size() : 0);
240
241 //
242 // --------- Pack data for fixed and variable size transfer ---------
243 //
244 // Iterate over all cells, call all callback functions on each cell,
245 // and store their data in the corresponding buffer scope.
246 {
247 auto cell_rel_it = cell_relations.cbegin();
248 auto data_cell_fixed_it = packed_fixed_size_data.begin();
249 auto data_cell_variable_it = packed_variable_size_data.begin();
250 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
251 {
252 const auto &dealii_cell = cell_rel_it->first;
253 const auto &cell_status = cell_rel_it->second;
254
255 // Assertions about the tree structure.
256 switch (cell_status)
257 {
260 // double check the condition that we will only ever attach
261 // data to active cells when we get here
262 Assert(dealii_cell->is_active(), ExcInternalError());
263 break;
264
266 // double check the condition that we will only ever attach
267 // data to cells with children when we get here. however, we
268 // can only tolerate one level of coarsening at a time, so
269 // check that the children are all active
270 Assert(dealii_cell->is_active() == false, ExcInternalError());
271 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
272 Assert(dealii_cell->child(c)->is_active(),
274 break;
275
277 // do nothing on invalid cells
278 break;
279
280 default:
282 break;
283 }
284
285 // Reserve memory corresponding to the number of callback
286 // functions that will be called.
287 // If variable size transfer is scheduled, we need to leave
288 // room for an array that holds information about how many
289 // bytes each of the variable size callback functions will
290 // write.
291 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
292 // will be stored.
293 const unsigned int n_fixed_size_data_sets_on_cell =
294 1 + ((cell_status == CellStatus::cell_invalid) ?
295 0 :
296 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
297 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
298
299 // We continue with packing all data on this specific cell.
300 auto data_fixed_it = data_cell_fixed_it->begin();
301
302 // First, we pack the CellStatus information.
303 // to get consistent data sizes on each cell for the fixed size
304 // transfer, we won't allow compression
305 *data_fixed_it =
306 Utilities::pack(cell_status, /*allow_compression=*/false);
307 ++data_fixed_it;
308
309 // Proceed with all registered callback functions.
310 // Skip cells with the CellStatus::cell_invalid flag.
311 if (cell_status != CellStatus::cell_invalid)
312 {
313 // Pack fixed size data.
314 for (auto callback_it = pack_callbacks_fixed.cbegin();
315 callback_it != pack_callbacks_fixed.cend();
316 ++callback_it, ++data_fixed_it)
317 {
318 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
319 }
320
321 // Pack variable size data.
322 // If we store variable size data, we need to transfer
323 // the sizes of each corresponding callback function
324 // via fixed size transfer as well.
325 if (variable_size_data_stored)
326 {
327 const unsigned int n_variable_size_data_sets_on_cell =
328 ((cell_status == CellStatus::cell_invalid) ?
329 0 :
330 n_callbacks_variable);
331 data_cell_variable_it->resize(
332 n_variable_size_data_sets_on_cell);
333
334 auto callback_it = pack_callbacks_variable.cbegin();
335 auto data_variable_it = data_cell_variable_it->begin();
336 auto sizes_variable_it =
337 cell_sizes_variable_cumulative.begin();
338 for (; callback_it != pack_callbacks_variable.cend();
339 ++callback_it, ++data_variable_it, ++sizes_variable_it)
340 {
341 *data_variable_it =
342 (*callback_it)(dealii_cell, cell_status);
343
344 // Store data sizes for each callback function first.
345 // Make it cumulative below.
346 *sizes_variable_it = data_variable_it->size();
347 }
348
349 // Turn size vector into its cumulative representation.
350 std::partial_sum(cell_sizes_variable_cumulative.begin(),
351 cell_sizes_variable_cumulative.end(),
352 cell_sizes_variable_cumulative.begin());
353
354 // Serialize cumulative variable size vector
355 // value-by-value. This way we can circumvent the overhead
356 // of storing the container object as a whole, since we
357 // know its size by the number of registered callback
358 // functions.
359 data_fixed_it->resize(n_callbacks_variable *
360 sizeof(unsigned int));
361 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
362 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
363 &(cell_sizes_variable_cumulative.at(i)),
364 sizeof(unsigned int));
365
366 ++data_fixed_it;
367 }
368
369 // Double check that we packed everything we wanted
370 // in the fixed size buffers.
371 Assert(data_fixed_it == data_cell_fixed_it->end(),
373 }
374
375 ++data_cell_fixed_it;
376
377 // Increment the variable size data iterator
378 // only if we actually pack this kind of data
379 // to avoid getting out of bounds.
380 if (variable_size_data_stored)
381 ++data_cell_variable_it;
382 } // loop over cell_relations
383 }
384
385 //
386 // ----------- Gather data sizes for fixed size transfer ------------
387 //
388 // Generate a vector which stores the sizes of each callback function,
389 // including the packed CellStatus transfer.
390 // Find the very first cell that we wrote to with all callback
391 // functions (i.e. a cell that was not flagged with
392 // CellStatus::cell_invalid) and store the sizes of each buffer.
393 //
394 // To deal with the case that at least one of the processors does not
395 // own any cell at all, we will exchange the information about the data
396 // sizes among them later. The code in between is still well-defined,
397 // since the following loops will be skipped.
398 std::vector<unsigned int> local_sizes_fixed(
399 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
400 for (const auto &data_cell : packed_fixed_size_data)
401 {
402 if (data_cell.size() == local_sizes_fixed.size())
403 {
404 auto sizes_fixed_it = local_sizes_fixed.begin();
405 auto data_fixed_it = data_cell.cbegin();
406 for (; data_fixed_it != data_cell.cend();
407 ++data_fixed_it, ++sizes_fixed_it)
408 {
409 *sizes_fixed_it = data_fixed_it->size();
410 }
411
412 break;
413 }
414 }
415
416 // Check if all cells have valid sizes.
417 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
418 data_cell_fixed_it != packed_fixed_size_data.cend();
419 ++data_cell_fixed_it)
420 {
421 Assert((data_cell_fixed_it->size() == 1) ||
422 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
424 }
425
426 // Share information about the packed data sizes
427 // of all callback functions across all processors, in case one
428 // of them does not own any cells at all.
429 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
430 Utilities::MPI::max(local_sizes_fixed,
431 mpi_communicator,
432 global_sizes_fixed);
433
434 // Construct cumulative sizes, since this is the only information
435 // we need from now on.
436 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
437 std::partial_sum(global_sizes_fixed.begin(),
438 global_sizes_fixed.end(),
439 sizes_fixed_cumulative.begin());
440
441 //
442 // ---------- Gather data sizes for variable size transfer ----------
443 //
444 if (variable_size_data_stored)
445 {
446 src_sizes_variable.reserve(packed_variable_size_data.size());
447 for (const auto &data_cell : packed_variable_size_data)
448 {
449 int variable_data_size_on_cell = 0;
450
451 for (const auto &data : data_cell)
452 variable_data_size_on_cell += data.size();
453
454 src_sizes_variable.push_back(variable_data_size_on_cell);
455 }
456 }
457
458 //
459 // ------------------------ Build buffers ---------------------------
460 //
461 const unsigned int expected_size_fixed =
462 cell_relations.size() * sizes_fixed_cumulative.back();
463 const unsigned int expected_size_variable =
464 std::accumulate(src_sizes_variable.begin(),
465 src_sizes_variable.end(),
466 std::vector<int>::size_type(0));
467
468 // Move every piece of packed fixed size data into the consecutive
469 // buffer.
470 src_data_fixed.reserve(expected_size_fixed);
471 for (const auto &data_cell_fixed : packed_fixed_size_data)
472 {
473 // Move every fraction of packed data into the buffer
474 // reserved for this particular cell.
475 for (const auto &data_fixed : data_cell_fixed)
476 std::move(data_fixed.begin(),
477 data_fixed.end(),
478 std::back_inserter(src_data_fixed));
479
480 // If we only packed the CellStatus information
481 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
482 // fill the remaining space with invalid entries.
483 // We can skip this if there is nothing else to pack.
484 if ((data_cell_fixed.size() == 1) &&
485 (sizes_fixed_cumulative.size() > 1))
486 {
487 const std::size_t bytes_skipped =
488 sizes_fixed_cumulative.back() - sizes_fixed_cumulative.front();
490 src_data_fixed.insert(src_data_fixed.end(),
491 bytes_skipped,
492 static_cast<char>(-1)); // invalid_char
493 }
494 }
495
496 // Move every piece of packed variable size data into the consecutive
497 // buffer.
498 if (variable_size_data_stored)
499 {
500 src_data_variable.reserve(expected_size_variable);
501 for (const auto &data_cell : packed_variable_size_data)
502 {
503 // Move every fraction of packed data into the buffer
504 // reserved for this particular cell.
505 for (const auto &data : data_cell)
506 std::move(data.begin(),
507 data.end(),
508 std::back_inserter(src_data_variable));
509 }
510 }
511
512 // Double check that we packed everything correctly.
513 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
514 Assert(src_data_variable.size() == expected_size_variable,
516 }
517
518
519
520 template <int dim, int spacedim>
522 void CellAttachedDataSerializer<dim, spacedim>::unpack_cell_status(
523 std::vector<
524 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
525 &cell_relations) const
526 {
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 // Size of CellStatus object that will be unpacked on each cell.
536 const unsigned int size = sizes_fixed_cumulative.front();
537
538 // Iterate over all cells and overwrite the CellStatus
539 // information from the transferred data.
540 // Proceed buffer iterator position to next cell after
541 // each iteration.
542 auto cell_rel_it = cell_relations.begin();
543 auto dest_fixed_it = dest_data_fixed.cbegin();
544 for (; cell_rel_it != cell_relations.end();
545 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
546 {
547 cell_rel_it->second = // cell_status
548 Utilities::unpack<CellStatus>(dest_fixed_it,
549 dest_fixed_it + size,
550 /*allow_compression=*/false);
551 }
553
554
555
556 template <int dim, int spacedim>
558 void CellAttachedDataSerializer<dim, spacedim>::unpack_data(
559 const std::vector<
560 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
561 &cell_relations,
562 const unsigned int handle,
563 const std::function<
564 void(const cell_iterator &,
565 const CellStatus &,
566 const boost::iterator_range<std::vector<char>::const_iterator> &)>
567 &unpack_callback) const
568 {
569 // We decode the handle returned by register_data_attach() back into
570 // a format we can use. All even handles belong to those callback
571 // functions which write/read variable size data, all odd handles
572 // interact with fixed size buffers.
573 const bool callback_variable_transfer = (handle % 2 == 0);
574 const unsigned int callback_index = handle / 2;
575
576 // Cells will always receive fixed size data (i.e., CellStatus
577 // information), but not necessarily variable size data (e.g., with a
578 // ParticleHandler a cell might not contain any particle at all).
579 // Thus it is sufficient to check if fixed size data has been received.
580 Assert(sizes_fixed_cumulative.size() > 0,
581 ExcMessage("No data has been packed!"));
582 if (cell_relations.size() > 0)
583 {
584 Assert(dest_data_fixed.size() > 0,
585 ExcMessage("No data has been received!"));
586 }
587
588 std::vector<char>::const_iterator dest_data_it;
589 std::vector<char>::const_iterator dest_sizes_cell_it;
590
591 // Depending on whether our callback function unpacks fixed or
592 // variable size data, we have to pursue different approaches
593 // to localize the correct fraction of the buffer from which
594 // we are allowed to read.
595 unsigned int offset = numbers::invalid_unsigned_int;
596 unsigned int size = numbers::invalid_unsigned_int;
597 unsigned int data_increment = numbers::invalid_unsigned_int;
598
599 if (callback_variable_transfer)
600 {
601 // For the variable size data, we need to extract the
602 // data size from the fixed size buffer on each cell.
603 //
604 // We packed this information last, so the last packed
605 // object in the fixed size buffer corresponds to the
606 // variable data sizes.
607 //
608 // The last entry of sizes_fixed_cumulative corresponds
609 // to the size of all fixed size data packed on the cell.
610 // To get the offset for the last packed object, we need
611 // to get the next-to-last entry.
612 const unsigned int offset_variable_data_sizes =
613 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
614
615 // This iterator points to the data size that the
616 // callback_function packed for each specific cell.
617 // Adjust buffer iterator to the offset of the callback
618 // function so that we only have to advance its position
619 // to the next cell after each iteration.
620 dest_sizes_cell_it = dest_data_fixed.cbegin() +
621 offset_variable_data_sizes +
622 callback_index * sizeof(unsigned int);
623
624 // Let the data iterator point to the correct buffer.
625 dest_data_it = dest_data_variable.cbegin();
626 }
627 else
628 {
629 // For the fixed size data, we can get the information about
630 // the buffer location on each cell directly from the
631 // sizes_fixed_cumulative vector.
632 offset = sizes_fixed_cumulative[callback_index];
633 size = sizes_fixed_cumulative[callback_index + 1] - offset;
634 data_increment = sizes_fixed_cumulative.back();
635
636 // Let the data iterator point to the correct buffer.
637 // Adjust buffer iterator to the offset of the callback
638 // function so that we only have to advance its position
639 // to the next cell after each iteration.
640 if (cell_relations.begin() != cell_relations.end())
641 dest_data_it = dest_data_fixed.cbegin() + offset;
642 }
643
644 // Iterate over all cells and unpack the transferred data.
645 auto cell_rel_it = cell_relations.begin();
646 auto dest_sizes_it = dest_sizes_variable.cbegin();
647 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
648 {
649 const auto &dealii_cell = cell_rel_it->first;
650 const auto &cell_status = cell_rel_it->second;
651
652 if (callback_variable_transfer)
653 {
654 // Update the increment according to the whole data size
655 // of the current cell.
656 data_increment = *dest_sizes_it;
657
658 if (cell_status != CellStatus::cell_invalid)
659 {
660 // Extract the corresponding values for offset and size from
661 // the cumulative sizes array stored in the fixed size
662 // buffer.
663 if (callback_index == 0)
664 offset = 0;
665 else
666 std::memcpy(&offset,
667 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
668 sizeof(unsigned int));
669
670 std::memcpy(&size,
671 &(*dest_sizes_cell_it),
672 sizeof(unsigned int));
673
674 size -= offset;
675
676 // Move the data iterator to the corresponding position
677 // of the callback function and adjust the increment
678 // accordingly.
679 dest_data_it += offset;
680 data_increment -= offset;
681 }
682
683 // Advance data size iterators to the next cell, avoid iterating
684 // past the end of dest_sizes_cell_it
685 if (cell_rel_it != cell_relations.end() - 1)
686 dest_sizes_cell_it += sizes_fixed_cumulative.back();
687 ++dest_sizes_it;
688 }
689
690 switch (cell_status)
691 {
694 unpack_callback(dealii_cell,
695 cell_status,
696 boost::make_iterator_range(dest_data_it,
697 dest_data_it + size));
698 break;
699
701 unpack_callback(dealii_cell->parent(),
702 cell_status,
703 boost::make_iterator_range(dest_data_it,
704 dest_data_it + size));
705 break;
706
708 // Skip this cell.
709 break;
710
711 default:
713 break;
714 }
715
716 if (cell_rel_it != cell_relations.end() - 1)
717 dest_data_it += data_increment;
718 }
719 }
720
721
722
723 template <int dim, int spacedim>
725 void CellAttachedDataSerializer<dim, spacedim>::save(
726 const unsigned int global_first_cell,
727 const unsigned int global_num_cells,
728 const std::string &file_basename,
729 const MPI_Comm &mpi_communicator) const
730 {
731 Assert(sizes_fixed_cumulative.size() > 0,
732 ExcMessage("No data has been packed!"));
733
734#ifdef DEAL_II_WITH_MPI
735 // Large fractions of this function have been copied from
736 // DataOutInterface::write_vtu_in_parallel.
737 // TODO: Write general MPIIO interface.
738
739 const unsigned int myrank =
740 Utilities::MPI::this_mpi_process(mpi_communicator);
741 const unsigned int mpisize =
742 Utilities::MPI::n_mpi_processes(mpi_communicator);
743
744 if (mpisize > 1)
745 {
746 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
747
748 //
749 // ---------- Fixed size data ----------
750 //
751 {
752 const std::string fname_fixed =
753 std::string(file_basename) + "_fixed.data";
754
755 MPI_Info info;
756 int ierr = MPI_Info_create(&info);
757 AssertThrowMPI(ierr);
758
759 MPI_File fh;
760 ierr = MPI_File_open(mpi_communicator,
761 fname_fixed.c_str(),
762 MPI_MODE_CREATE | MPI_MODE_WRONLY,
763 info,
764 &fh);
765 AssertThrowMPI(ierr);
766
767 ierr = MPI_File_set_size(fh, 0); // delete the file contents
768 AssertThrowMPI(ierr);
769 // this barrier is necessary, because otherwise others might already
770 // write while one core is still setting the size to zero.
771 ierr = MPI_Barrier(mpi_communicator);
772 AssertThrowMPI(ierr);
773 ierr = MPI_Info_free(&info);
774 AssertThrowMPI(ierr);
775 // ------------------
776
777 // Write cumulative sizes to file.
778 // Since each processor owns the same information about the data
779 // sizes, it is sufficient to let only the first processor perform
780 // this task.
781 if (myrank == 0)
782 {
784 fh,
785 0,
786 sizes_fixed_cumulative.data(),
787 sizes_fixed_cumulative.size(),
788 MPI_UNSIGNED,
789 MPI_STATUS_IGNORE);
790 AssertThrowMPI(ierr);
791 }
792
793 // Write packed data to file simultaneously.
794 const MPI_Offset size_header =
795 sizes_fixed_cumulative.size() * sizeof(unsigned int);
796
797 // Make sure we do the following computation in 64bit integers to be
798 // able to handle 4GB+ files:
799 const MPI_Offset my_global_file_position =
800 size_header +
801 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
802
803 ierr =
805 my_global_file_position,
806 src_data_fixed.data(),
807 src_data_fixed.size(),
808 MPI_BYTE,
809 MPI_STATUS_IGNORE);
810 AssertThrowMPI(ierr);
811
812 ierr = MPI_File_close(&fh);
813 AssertThrowMPI(ierr);
814 }
815
816
817
818 //
819 // ---------- Variable size data ----------
820 //
821 if (variable_size_data_stored)
822 {
823 const std::string fname_variable =
824 std::string(file_basename) + "_variable.data";
825
826 MPI_Info info;
827 int ierr = MPI_Info_create(&info);
828 AssertThrowMPI(ierr);
829
830 MPI_File fh;
831 ierr = MPI_File_open(mpi_communicator,
832 fname_variable.c_str(),
833 MPI_MODE_CREATE | MPI_MODE_WRONLY,
834 info,
835 &fh);
836 AssertThrowMPI(ierr);
837
838 ierr = MPI_File_set_size(fh, 0); // delete the file contents
839 AssertThrowMPI(ierr);
840 // this barrier is necessary, because otherwise others might already
841 // write while one core is still setting the size to zero.
842 ierr = MPI_Barrier(mpi_communicator);
843 AssertThrowMPI(ierr);
844 ierr = MPI_Info_free(&info);
845 AssertThrowMPI(ierr);
846
847 // Write sizes of each cell into file simultaneously.
848 {
849 const MPI_Offset my_global_file_position =
850 static_cast<MPI_Offset>(global_first_cell) *
851 sizeof(unsigned int);
852
853 // It is very unlikely that a single process has more than
854 // 2 billion cells, but we might as well check.
855 AssertThrow(src_sizes_variable.size() <
856 static_cast<std::size_t>(
857 std::numeric_limits<int>::max()),
859
861 fh,
862 my_global_file_position,
863 src_sizes_variable.data(),
864 src_sizes_variable.size(),
865 MPI_INT,
866 MPI_STATUS_IGNORE);
867 AssertThrowMPI(ierr);
868 }
869
870 // Gather size of data in bytes we want to store from this
871 // processor and compute the prefix sum. We do this in 64 bit
872 // to avoid overflow for files larger than 4GB:
873 const std::uint64_t size_on_proc = src_data_variable.size();
874 std::uint64_t prefix_sum = 0;
875 ierr = MPI_Exscan(&size_on_proc,
876 &prefix_sum,
877 1,
878 MPI_UINT64_T,
879 MPI_SUM,
880 mpi_communicator);
881 AssertThrowMPI(ierr);
882
883 const MPI_Offset my_global_file_position =
884 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
885 prefix_sum;
886
887 // Write data consecutively into file.
889 fh,
890 my_global_file_position,
891 src_data_variable.data(),
892 src_data_variable.size(),
893 MPI_BYTE,
894 MPI_STATUS_IGNORE);
895 AssertThrowMPI(ierr);
896
897
898 ierr = MPI_File_close(&fh);
899 AssertThrowMPI(ierr);
900 }
901 } // if (mpisize > 1)
902 else
903#endif
904 {
905 (void)global_first_cell;
906 (void)global_num_cells;
907 (void)mpi_communicator;
908
909 //
910 // ---------- Fixed size data ----------
911 //
912 {
913 const std::string fname_fixed =
914 std::string(file_basename) + "_fixed.data";
915
916 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
917 AssertThrow(file.fail() == false, ExcIO());
918
919 // Write header data.
920 file.write(reinterpret_cast<const char *>(
921 sizes_fixed_cumulative.data()),
922 sizes_fixed_cumulative.size() * sizeof(unsigned int));
923
924 // Write packed data.
925 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
926 src_data_fixed.size() * sizeof(char));
927 }
928
929 //
930 // ---------- Variable size data ----------
931 //
932 if (variable_size_data_stored)
933 {
934 const std::string fname_variable =
935 std::string(file_basename) + "_variable.data";
936
937 std::ofstream file(fname_variable,
938 std::ios::binary | std::ios::out);
939 AssertThrow(file.fail() == false, ExcIO());
940
941 // Write header data.
942 file.write(reinterpret_cast<const char *>(
943 src_sizes_variable.data()),
944 src_sizes_variable.size() * sizeof(int));
945
946 // Write packed data.
947 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
948 src_data_variable.size() * sizeof(char));
949 }
950 }
951 }
952
953
954 template <int dim, int spacedim>
956 void CellAttachedDataSerializer<dim, spacedim>::load(
957 const unsigned int global_first_cell,
958 const unsigned int global_num_cells,
959 const unsigned int local_num_cells,
960 const std::string &file_basename,
961 const unsigned int n_attached_deserialize_fixed,
962 const unsigned int n_attached_deserialize_variable,
963 const MPI_Comm &mpi_communicator)
964 {
965 Assert(dest_data_fixed.empty(),
966 ExcMessage("Previously loaded data has not been released yet!"));
967
968 variable_size_data_stored = (n_attached_deserialize_variable > 0);
969
970#ifdef DEAL_II_WITH_MPI
971 // Large fractions of this function have been copied from
972 // DataOutInterface::write_vtu_in_parallel.
973 // TODO: Write general MPIIO interface.
974
975 const unsigned int mpisize =
976 Utilities::MPI::n_mpi_processes(mpi_communicator);
977
978 if (mpisize > 1)
979 {
980 //
981 // ---------- Fixed size data ----------
982 //
983 {
984 const std::string fname_fixed =
985 std::string(file_basename) + "_fixed.data";
986
987 MPI_Info info;
988 int ierr = MPI_Info_create(&info);
989 AssertThrowMPI(ierr);
990
991 MPI_File fh;
992 ierr = MPI_File_open(
993 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
994 AssertThrowMPI(ierr);
995
996 ierr = MPI_Info_free(&info);
997 AssertThrowMPI(ierr);
998
999 // Read cumulative sizes from file.
1000 // Since all processors need the same information about the data
1001 // sizes, let each of them retrieve it by reading from the same
1002 // location in the file.
1003 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1004 (variable_size_data_stored ? 1 : 0));
1006 fh,
1007 0,
1008 sizes_fixed_cumulative.data(),
1009 sizes_fixed_cumulative.size(),
1010 MPI_UNSIGNED,
1011 MPI_STATUS_IGNORE);
1012 AssertThrowMPI(ierr);
1013
1014 // Allocate sufficient memory.
1015 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1016 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
1017 bytes_per_cell);
1018
1019 // Read packed data from file simultaneously.
1020 const MPI_Offset size_header =
1021 sizes_fixed_cumulative.size() * sizeof(unsigned int);
1022
1023 // Make sure we do the following computation in 64bit integers to be
1024 // able to handle 4GB+ files:
1025 const MPI_Offset my_global_file_position =
1026 size_header +
1027 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
1028
1029 ierr =
1031 my_global_file_position,
1032 dest_data_fixed.data(),
1033 dest_data_fixed.size(),
1034 MPI_BYTE,
1035 MPI_STATUS_IGNORE);
1036 AssertThrowMPI(ierr);
1037
1038
1039 ierr = MPI_File_close(&fh);
1040 AssertThrowMPI(ierr);
1041 }
1042
1043 //
1044 // ---------- Variable size data ----------
1045 //
1046 if (variable_size_data_stored)
1047 {
1048 const std::string fname_variable =
1049 std::string(file_basename) + "_variable.data";
1050
1051 MPI_Info info;
1052 int ierr = MPI_Info_create(&info);
1053 AssertThrowMPI(ierr);
1054
1055 MPI_File fh;
1056 ierr = MPI_File_open(mpi_communicator,
1057 fname_variable.c_str(),
1058 MPI_MODE_RDONLY,
1059 info,
1060 &fh);
1061 AssertThrowMPI(ierr);
1062
1063 ierr = MPI_Info_free(&info);
1064 AssertThrowMPI(ierr);
1065
1066 // Read sizes of all locally owned cells.
1067 dest_sizes_variable.resize(local_num_cells);
1068
1069 const MPI_Offset my_global_file_position_sizes =
1070 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1071
1073 fh,
1074 my_global_file_position_sizes,
1075 dest_sizes_variable.data(),
1076 dest_sizes_variable.size(),
1077 MPI_INT,
1078 MPI_STATUS_IGNORE);
1079 AssertThrowMPI(ierr);
1080
1081
1082 // Compute my data size in bytes and compute prefix sum. We do this
1083 // in 64 bit to avoid overflow for files larger than 4 GB:
1084 const std::uint64_t size_on_proc =
1085 std::accumulate(dest_sizes_variable.begin(),
1086 dest_sizes_variable.end(),
1087 0ULL);
1088
1089 std::uint64_t prefix_sum = 0;
1090 ierr = MPI_Exscan(&size_on_proc,
1091 &prefix_sum,
1092 1,
1093 MPI_UINT64_T,
1094 MPI_SUM,
1095 mpi_communicator);
1096 AssertThrowMPI(ierr);
1097
1098 const MPI_Offset my_global_file_position =
1099 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1100 prefix_sum;
1101
1102 dest_data_variable.resize(size_on_proc);
1103
1105 fh,
1106 my_global_file_position,
1107 dest_data_variable.data(),
1108 dest_data_variable.size(),
1109 MPI_BYTE,
1110 MPI_STATUS_IGNORE);
1111 AssertThrowMPI(ierr);
1112
1113 ierr = MPI_File_close(&fh);
1114 AssertThrowMPI(ierr);
1115 }
1116 }
1117 else // if (mpisize > 1)
1118#endif
1119 {
1120 (void)mpi_communicator;
1121 (void)global_first_cell;
1122 (void)global_num_cells;
1123
1124 //
1125 // ---------- Fixed size data ----------
1126 //
1127 {
1128 const std::string fname_fixed =
1129 std::string(file_basename) + "_fixed.data";
1130
1131 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1132 AssertThrow(file.fail() == false, ExcIO());
1133
1134 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1135 (variable_size_data_stored ? 1 : 0));
1136 // Read header data.
1137 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1138 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1139
1140 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1141 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
1142 bytes_per_cell);
1143
1144 // Read packed data.
1145 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1146 dest_data_fixed.size() * sizeof(char));
1147 }
1148
1149 //
1150 // ---------- Variable size data ----------
1151 //
1152 if (variable_size_data_stored)
1153 {
1154 const std::string fname_variable =
1155 std::string(file_basename) + "_variable.data";
1156
1157 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1158 AssertThrow(file.fail() == false, ExcIO());
1159
1160 // Read header data.
1161 dest_sizes_variable.resize(local_num_cells);
1162 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1163 dest_sizes_variable.size() * sizeof(int));
1164
1165 // Read packed data.
1166 const std::uint64_t size =
1167 std::accumulate(dest_sizes_variable.begin(),
1168 dest_sizes_variable.end(),
1169 0ULL);
1170 dest_data_variable.resize(size);
1171 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1172 dest_data_variable.size() * sizeof(char));
1173 }
1174 }
1175 }
1176
1177
1178 template <int dim, int spacedim>
1180 void CellAttachedDataSerializer<dim, spacedim>::clear()
1181 {
1182 variable_size_data_stored = false;
1183
1184 // free information about data sizes
1185 sizes_fixed_cumulative.clear();
1186 sizes_fixed_cumulative.shrink_to_fit();
1187
1188 // free fixed size transfer data
1189 src_data_fixed.clear();
1190 src_data_fixed.shrink_to_fit();
1191
1192 dest_data_fixed.clear();
1193 dest_data_fixed.shrink_to_fit();
1194
1195 // free variable size transfer data
1196 src_sizes_variable.clear();
1197 src_sizes_variable.shrink_to_fit();
1198
1199 src_data_variable.clear();
1200 src_data_variable.shrink_to_fit();
1201
1202 dest_sizes_variable.clear();
1203 dest_sizes_variable.shrink_to_fit();
1204
1205 dest_data_variable.clear();
1206 dest_data_variable.shrink_to_fit();
1207 }
1208
1209} // namespace internal
1210
1211// anonymous namespace for internal helper functions
1212namespace
1213{
1214 // return whether the given cell is
1215 // patch_level_1, i.e. determine
1216 // whether either all or none of
1217 // its children are further
1218 // refined. this function can only
1219 // be called for non-active cells.
1220 template <int dim, int spacedim>
1221 bool
1222 cell_is_patch_level_1(
1224 {
1225 Assert(cell->is_active() == false, ExcInternalError());
1226
1227 unsigned int n_active_children = 0;
1228 for (unsigned int i = 0; i < cell->n_children(); ++i)
1229 if (cell->child(i)->is_active())
1230 ++n_active_children;
1231
1232 return (n_active_children == 0) ||
1233 (n_active_children == cell->n_children());
1234 }
1235
1236
1237
1238 // return, whether a given @p cell will be
1239 // coarsened, which is the case if all
1240 // children are active and have their coarsen
1241 // flag set. In case only part of the coarsen
1242 // flags are set, remove them.
1243 template <int dim, int spacedim>
1244 bool
1245 cell_will_be_coarsened(
1247 {
1248 // only cells with children should be
1249 // considered for coarsening
1250
1251 if (cell->has_children())
1252 {
1253 unsigned int children_to_coarsen = 0;
1254 const unsigned int n_children = cell->n_children();
1255
1256 for (unsigned int c = 0; c < n_children; ++c)
1257 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1258 ++children_to_coarsen;
1259 if (children_to_coarsen == n_children)
1260 return true;
1261 else
1262 for (unsigned int c = 0; c < n_children; ++c)
1263 if (cell->child(c)->is_active())
1264 cell->child(c)->clear_coarsen_flag();
1265 }
1266 // no children, so no coarsening
1267 // possible. however, no children also
1268 // means that this cell will be in the same
1269 // state as if it had children and was
1270 // coarsened. So, what should we return -
1271 // false or true?
1272 // make sure we do not have to do this at
1273 // all...
1274 Assert(cell->has_children(), ExcInternalError());
1275 // ... and then simply return false
1276 return false;
1277 }
1278
1279
1280 // return, whether the face @p face_no of the
1281 // given @p cell will be refined after the
1282 // current refinement step, considering
1283 // refine and coarsen flags and considering
1284 // only those refinemnts that will be caused
1285 // by the neighboring cell.
1286
1287 // this function is used on both active cells
1288 // and cells with children. on cells with
1289 // children it also of interest to know 'how'
1290 // the face will be refined. thus there is an
1291 // additional third argument @p
1292 // expected_face_ref_case returning just
1293 // that. be aware, that this variable will
1294 // only contain useful information if this
1295 // function is called for an active cell.
1296 //
1297 // thus, this is an internal function, users
1298 // should call one of the two alternatives
1299 // following below.
1300 template <int dim, int spacedim>
1301 bool
1302 face_will_be_refined_by_neighbor_internal(
1304 const unsigned int face_no,
1305 RefinementCase<dim - 1> &expected_face_ref_case)
1306 {
1307 // first of all: set the default value for
1308 // expected_face_ref_case, which is no
1309 // refinement at all
1310 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1311
1312 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1313 cell->neighbor(face_no);
1314
1315 // If we are at the boundary, there is no
1316 // neighbor which could refine the face
1317 if (neighbor.state() != IteratorState::valid)
1318 return false;
1319
1320 if (neighbor->has_children())
1321 {
1322 // if the neighbor is refined, it may be
1323 // coarsened. if so, then it won't refine
1324 // the face, no matter what else happens
1325 if (cell_will_be_coarsened(neighbor))
1326 return false;
1327 else
1328 // if the neighbor is refined, then it
1329 // is also refined at our current
1330 // face. It will stay so without
1331 // coarsening, so return true in that
1332 // case.
1333 {
1334 expected_face_ref_case = cell->face(face_no)->refinement_case();
1335 return true;
1336 }
1337 }
1338
1339 // now, the neighbor is not refined, but
1340 // perhaps it will be
1341 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1342 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1343 {
1344 // now we need to know, which of the
1345 // neighbors faces points towards us
1346 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1347 // check, whether the cell will be
1348 // refined in a way that refines our
1349 // face
1350 const RefinementCase<dim - 1> face_ref_case =
1352 nb_ref_flag,
1353 neighbor_neighbor,
1354 neighbor->face_orientation(neighbor_neighbor),
1355 neighbor->face_flip(neighbor_neighbor),
1356 neighbor->face_rotation(neighbor_neighbor));
1357 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1358 {
1360 neighbor_face = neighbor->face(neighbor_neighbor);
1361 const int this_face_index = cell->face_index(face_no);
1362
1363 // there are still two basic
1364 // possibilities here: the neighbor
1365 // might be coarser or as coarse
1366 // as we are
1367 if (neighbor_face->index() == this_face_index)
1368 // the neighbor is as coarse as
1369 // we are and will be refined at
1370 // the face of consideration, so
1371 // return true
1372 {
1373 expected_face_ref_case = face_ref_case;
1374 return true;
1375 }
1376 else
1377 {
1378 // the neighbor is coarser.
1379 // this is the most complicated
1380 // case. It might be, that the
1381 // neighbor's face will be
1382 // refined, but that we will
1383 // not see this, as we are
1384 // refined in a similar way.
1385
1386 // so, the neighbor's face must
1387 // have children. check, if our
1388 // cell's face is one of these
1389 // (it could also be a
1390 // grand_child)
1391 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1392 if (neighbor_face->child_index(c) == this_face_index)
1393 {
1394 // if the flagged refine
1395 // case of the face is a
1396 // subset or the same as
1397 // the current refine case,
1398 // then the face, as seen
1399 // from our cell, won't be
1400 // refined by the neighbor
1401 if ((neighbor_face->refinement_case() | face_ref_case) ==
1402 neighbor_face->refinement_case())
1403 return false;
1404 else
1405 {
1406 // if we are active, we
1407 // must be an
1408 // anisotropic child
1409 // and the coming
1410 // face_ref_case is
1411 // isotropic. Thus,
1412 // from our cell we
1413 // will see exactly the
1414 // opposite refine case
1415 // that the face has
1416 // now...
1417 Assert(
1418 face_ref_case ==
1421 expected_face_ref_case =
1422 ~neighbor_face->refinement_case();
1423 return true;
1424 }
1425 }
1426
1427 // so, obviously we were not
1428 // one of the children, but a
1429 // grandchild. This is only
1430 // possible in 3d.
1431 Assert(dim == 3, ExcInternalError());
1432 // In that case, however, no
1433 // matter what the neighbor
1434 // does, it won't be finer
1435 // after the next refinement
1436 // step.
1437 return false;
1438 }
1439 } // if face will be refined
1440 } // if neighbor is flagged for refinement
1441
1442 // no cases left, so the neighbor will not
1443 // refine the face
1444 return false;
1445 }
1446
1447 // version of above function for both active
1448 // and non-active cells
1449 template <int dim, int spacedim>
1450 bool
1451 face_will_be_refined_by_neighbor(
1453 const unsigned int face_no)
1454 {
1455 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1456 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1457 }
1458
1459 // version of above function for active cells
1460 // only. Additionally returning the refine
1461 // case (to come) of the face under
1462 // consideration
1463 template <int dim, int spacedim>
1464 bool
1465 face_will_be_refined_by_neighbor(
1467 const unsigned int face_no,
1468 RefinementCase<dim - 1> &expected_face_ref_case)
1469 {
1470 return face_will_be_refined_by_neighbor_internal(cell,
1471 face_no,
1472 expected_face_ref_case);
1473 }
1474
1475
1476
1477 template <int dim, int spacedim>
1478 bool
1479 satisfies_level1_at_vertex_rule(
1480 const Triangulation<dim, spacedim> &triangulation)
1481 {
1482 std::vector<unsigned int> min_adjacent_cell_level(
1483 triangulation.n_vertices(), triangulation.n_levels());
1484 std::vector<unsigned int> max_adjacent_cell_level(
1485 triangulation.n_vertices(), 0);
1486
1487 for (const auto &cell : triangulation.active_cell_iterators())
1488 for (const unsigned int v : cell->vertex_indices())
1489 {
1490 min_adjacent_cell_level[cell->vertex_index(v)] =
1491 std::min<unsigned int>(
1492 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1493 max_adjacent_cell_level[cell->vertex_index(v)] =
1494 std::max<unsigned int>(
1495 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1496 }
1497
1498 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1499 if (triangulation.vertex_used(k))
1500 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1501 return false;
1502 return true;
1503 }
1504
1505
1506
1524 template <int dim, int spacedim>
1525 unsigned int
1526 middle_vertex_index(
1528 {
1529 if (line->has_children())
1530 return line->child(0)->vertex_index(1);
1532 }
1533
1534
1535 template <int dim, int spacedim>
1536 unsigned int
1537 middle_vertex_index(
1539 {
1540 switch (static_cast<unsigned char>(quad->refinement_case()))
1541 {
1543 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1544 break;
1546 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1547 break;
1549 return quad->child(0)->vertex_index(3);
1550 break;
1551 default:
1552 break;
1553 }
1555 }
1556
1557
1558
1571 template <class TRIANGULATION>
1572 typename TRIANGULATION::DistortedCellList
1573 collect_distorted_coarse_cells(const TRIANGULATION &)
1574 {
1575 return typename TRIANGULATION::DistortedCellList();
1576 }
1577
1578
1579
1588 template <int dim>
1590 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1591 {
1592 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1593 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1594 {
1596 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1597 vertices[i] = cell->vertex(i);
1598
1601
1602 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1603 if (determinants[i] <=
1604 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1605 {
1606 distorted_cells.distorted_cells.push_back(cell);
1607 break;
1608 }
1609 }
1610
1611 return distorted_cells;
1612 }
1613
1614
1619 template <int dim, int spacedim>
1620 bool
1621 has_distorted_children(
1623 {
1624 Assert(cell->has_children(), ExcInternalError());
1625 Assert(cell->reference_cell().is_hyper_cube(), ExcNotImplemented());
1626
1627 if constexpr (dim == spacedim)
1628 {
1629 for (unsigned int c = 0; c < cell->n_children(); ++c)
1630 {
1631 // We call this function during mesh refinement, at a time
1632 // when the cell vertex cache has not yet been
1633 // re-built. As a consequence, we cannot call
1634 // cell->vertex(), or cell->diameter() (the latter
1635 // implicitly depending on the former). Instead, we have to
1636 // use a helper function to extract vertex locations into
1637 // an array that bypasses the cache.
1638
1639 const unsigned int n_vertices = cell->child(c)->n_vertices();
1641 ReferenceCells::max_n_vertices<dim>()>
1642 child_vertex_indices(n_vertices);
1643 GridTools::internal::extract_vertices_without_cache<dim, spacedim>(
1644 cell->child(c), child_vertex_indices);
1645
1647 for (unsigned int i = 0; i < n_vertices; ++i)
1648 child_vertices[i] = cell->get_triangulation()
1649 .get_vertices()[child_vertex_indices[i]];
1650
1653 determinants);
1654
1655 double child_diameter = numbers::signaling_nan<double>();
1656 if constexpr (dim == 1)
1657 child_diameter = (child_vertices[1] - child_vertices[0]).norm();
1658 else if constexpr (dim == 2)
1659 // Take the longer one of the two diagonals of the quadrilateral
1660 child_diameter =
1661 std::max({(child_vertices[3] - child_vertices[0]).norm(),
1662 (child_vertices[2] - child_vertices[1]).norm()});
1663 else if constexpr (dim == 3)
1664 // Take the longest of the four diagonals of the hexahedron
1665 child_diameter =
1666 std::max({(child_vertices[7] - child_vertices[0]).norm(),
1667 (child_vertices[6] - child_vertices[1]).norm(),
1668 (child_vertices[2] - child_vertices[5]).norm(),
1669 (child_vertices[3] - child_vertices[4]).norm()});
1670 else
1672
1673 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1674 if (determinants[i] <=
1675 1e-9 * Utilities::fixed_power<dim>(child_diameter))
1676 return true;
1677 }
1678
1679 return false;
1680 }
1681 else
1682 // Like for collect_distorted_coarse_cells, there is nothing
1683 // that we can do in this case.
1684 return false;
1685 }
1686
1687
1688
1689 template <int dim, int spacedim>
1690 void
1691 update_periodic_face_map_recursively(
1692 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1693 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1694 unsigned int n_face_1,
1695 unsigned int n_face_2,
1696 const types::geometric_orientation orientation,
1697 typename std::map<
1699 unsigned int>,
1700 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1701 unsigned int>,
1702 types::geometric_orientation>> &periodic_face_map)
1703 {
1704 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1705 const FaceIterator face_1 = cell_1->face(n_face_1);
1706 const FaceIterator face_2 = cell_2->face(n_face_2);
1707
1708 const auto inverse_orientation =
1709 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1710
1711 if constexpr (running_in_debug_mode())
1712 {
1713 const auto [face_orientation, face_rotation, face_flip] =
1715
1716 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1717 face_rotation == false),
1718 ExcMessage("The supplied orientation "
1719 "(face_orientation, face_flip, face_rotation) "
1720 "is invalid for 1d"));
1721
1722 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1723 ExcMessage("The supplied orientation "
1724 "(face_orientation, face_flip, face_rotation) "
1725 "is invalid for 2d"));
1726 }
1727
1728 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1729
1730 Assert(face_1->at_boundary() && face_2->at_boundary(),
1731 ExcMessage("Periodic faces must be on the boundary"));
1732
1733 // Check if the requirement that each edge can only have at most one hanging
1734 // node, and as a consequence neighboring cells can differ by at most
1735 // one refinement level is enforced. In 1d, there are no hanging nodes and
1736 // so neighboring cells can differ by more than one refinement level.
1737 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1739
1740 // insert periodic face pair for both cells
1741 using CellFace =
1742 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1743 unsigned int>;
1744 const CellFace cell_face_1(cell_1, n_face_1);
1745 const CellFace cell_face_2(cell_2, n_face_2);
1746 const std::pair<CellFace, types::geometric_orientation>
1747 cell_face_orientation_2(cell_face_2, orientation);
1748
1749 const std::pair<CellFace, std::pair<CellFace, types::geometric_orientation>>
1750 periodic_faces(cell_face_1, cell_face_orientation_2);
1751
1752 // Only one periodic neighbor is allowed
1753 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1754 periodic_face_map.insert(periodic_faces);
1755
1756 if (dim == 1)
1757 {
1758 if (cell_1->has_children())
1759 {
1760 if (cell_2->has_children())
1761 {
1762 update_periodic_face_map_recursively<dim, spacedim>(
1763 cell_1->child(n_face_1),
1764 cell_2->child(n_face_2),
1765 n_face_1,
1766 n_face_2,
1767 orientation,
1768 periodic_face_map);
1769 }
1770 else // only face_1 has children
1771 {
1772 update_periodic_face_map_recursively<dim, spacedim>(
1773 cell_1->child(n_face_1),
1774 cell_2,
1775 n_face_1,
1776 n_face_2,
1777 orientation,
1778 periodic_face_map);
1779 }
1780 }
1781 }
1782 else // dim == 2 || dim == 3
1783 {
1784 if (cell_1->has_children())
1785 {
1786 if (cell_2->has_children())
1787 {
1788 // In the case that both faces have children, we loop over all
1789 // children and apply update_periodic_face_map_recursively
1790 // recursively:
1791
1792 Assert(face_1->n_children() ==
1794 face_2->n_children() ==
1797
1798 const auto reference_cell = cell_1->reference_cell();
1799
1800 for (unsigned int i = 0;
1801 i < GeometryInfo<dim>::max_children_per_face;
1802 ++i)
1803 {
1804 // Lookup the index for the second face
1805 const unsigned int j =
1806 reference_cell.standard_to_real_face_vertex(
1807 i, n_face_1, inverse_orientation);
1808
1809 // find subcell ids that belong to the subface indices
1810 unsigned int child_cell_1 =
1812 cell_1->refinement_case(),
1813 n_face_1,
1814 i,
1815 cell_1->face_orientation(n_face_1),
1816 cell_1->face_flip(n_face_1),
1817 cell_1->face_rotation(n_face_1),
1818 face_1->refinement_case());
1819 unsigned int child_cell_2 =
1821 cell_2->refinement_case(),
1822 n_face_2,
1823 j,
1824 cell_2->face_orientation(n_face_2),
1825 cell_2->face_flip(n_face_2),
1826 cell_2->face_rotation(n_face_2),
1827 face_2->refinement_case());
1828
1829 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1830 face_1->child(i),
1832 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1833 face_2->child(j),
1835
1836 // precondition: subcell has the same orientation as cell
1837 // (so that the face numbers coincide) recursive call
1838 update_periodic_face_map_recursively<dim, spacedim>(
1839 cell_1->child(child_cell_1),
1840 cell_2->child(child_cell_2),
1841 n_face_1,
1842 n_face_2,
1843 orientation,
1844 periodic_face_map);
1845 }
1846 }
1847 else // only face_1 has children
1848 {
1849 for (unsigned int i = 0;
1850 i < GeometryInfo<dim>::max_children_per_face;
1851 ++i)
1852 {
1853 // find subcell ids that belong to the subface indices
1854 unsigned int child_cell_1 =
1856 cell_1->refinement_case(),
1857 n_face_1,
1858 i,
1859 cell_1->face_orientation(n_face_1),
1860 cell_1->face_flip(n_face_1),
1861 cell_1->face_rotation(n_face_1),
1862 face_1->refinement_case());
1863
1864 // recursive call
1865 update_periodic_face_map_recursively<dim, spacedim>(
1866 cell_1->child(child_cell_1),
1867 cell_2,
1868 n_face_1,
1869 n_face_2,
1870 orientation,
1871 periodic_face_map);
1872 }
1873 }
1874 }
1875 }
1876 }
1877
1878 // Given the child number and parent's line orientation, return the child face
1879 // number.
1880 unsigned int
1881 child_line_index(const unsigned int child_no,
1882 const types::geometric_orientation line_orientation)
1883 {
1884 AssertIndexRange(child_no, ReferenceCells::Line.n_children());
1885 Assert(line_orientation == numbers::default_geometric_orientation ||
1886 line_orientation == numbers::reverse_line_orientation,
1888 constexpr auto D = numbers::default_geometric_orientation;
1889 if (child_no == 0)
1890 return line_orientation == D ? 0 : 1;
1891 else
1892 return line_orientation == D ? 1 : 0;
1893 }
1894} // end of anonymous namespace
1895
1896
1897namespace internal
1898{
1899 namespace TriangulationImplementation
1900 {
1901 // make sure that if in the following we
1902 // write Triangulation<dim,spacedim>
1903 // we mean the *class*
1904 // ::Triangulation, not the
1905 // enclosing namespace
1906 // internal::TriangulationImplementation
1907 using ::Triangulation;
1908
1914 int,
1915 << "Something went wrong upon construction of cell "
1916 << arg1);
1927 int,
1928 << "Cell " << arg1
1929 << " has negative measure. This typically "
1930 << "indicates some distortion in the cell, or a mistakenly "
1931 << "swapped pair of vertices in the input to "
1932 << "Triangulation::create_triangulation().");
1941 int,
1942 int,
1943 int,
1944 << "Error while creating cell " << arg1
1945 << ": the vertex index " << arg2 << " must be between 0 and "
1946 << arg3 << '.');
1953 int,
1954 int,
1956 << "The input data for creating a triangulation contained "
1957 << "information about a line with indices " << arg1 << " and " << arg2
1958 << " that is described to have boundary indicator "
1959 << static_cast<int>(arg3)
1960 << ". However, this is an internal line not located on the "
1961 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1962 << std::endl
1963 << "If this happened at a place where you call "
1964 << "Triangulation::create_triangulation() yourself, you need "
1965 << "to check the SubCellData object you pass to this function."
1966 << std::endl
1967 << std::endl
1968 << "If this happened in a place where you are reading a mesh "
1969 << "from a file, then you need to investigate why such a line "
1970 << "ended up in the input file. A typical case is a geometry "
1971 << "that consisted of multiple parts and for which the mesh "
1972 << "generator program assumes that the interface between "
1973 << "two parts is a boundary when that isn't supposed to be "
1974 << "the case, or where the mesh generator simply assigns "
1975 << "'geometry indicators' to lines at the perimeter of "
1976 << "a part that are not supposed to be interpreted as "
1977 << "'boundary indicators'.");
1984 int,
1985 int,
1986 int,
1987 int,
1989 << "The input data for creating a triangulation contained "
1990 << "information about a quad with indices " << arg1 << ", " << arg2
1991 << ", " << arg3 << ", and " << arg4
1992 << " that is described to have boundary indicator "
1993 << static_cast<int>(arg5)
1994 << ". However, this is an internal quad not located on the "
1995 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1996 << std::endl
1997 << "If this happened at a place where you call "
1998 << "Triangulation::create_triangulation() yourself, you need "
1999 << "to check the SubCellData object you pass to this function."
2000 << std::endl
2001 << std::endl
2002 << "If this happened in a place where you are reading a mesh "
2003 << "from a file, then you need to investigate why such a quad "
2004 << "ended up in the input file. A typical case is a geometry "
2005 << "that consisted of multiple parts and for which the mesh "
2006 << "generator program assumes that the interface between "
2007 << "two parts is a boundary when that isn't supposed to be "
2008 << "the case, or where the mesh generator simply assigns "
2009 << "'geometry indicators' to quads at the surface of "
2010 << "a part that are not supposed to be interpreted as "
2011 << "'boundary indicators'.");
2018 int,
2019 int,
2020 << "In SubCellData the line info of the line with vertex indices " << arg1
2021 << " and " << arg2 << " appears more than once. "
2022 << "This is not allowed.");
2029 int,
2030 int,
2031 std::string,
2032 << "In SubCellData the line info of the line with vertex indices " << arg1
2033 << " and " << arg2 << " appears multiple times with different (valid) "
2034 << arg3 << ". This is not allowed.");
2041 int,
2042 int,
2043 int,
2044 int,
2045 std::string,
2046 << "In SubCellData the quad info of the quad with line indices " << arg1
2047 << ", " << arg2 << ", " << arg3 << " and " << arg4
2048 << " appears multiple times with different (valid) " << arg5
2049 << ". This is not allowed.");
2050
2055 int,
2056 int,
2057 << "The containers have sizes " << arg1 << " and " << arg2
2058 << ", which is not as expected.");
2059
2065 template <int dim, int spacedim>
2066 void
2068 const unsigned int true_dimension)
2069 {
2070 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2071 tria_level.neighbors.size(),
2072 ExcMemoryInexact(tria_level.refine_flags.size(),
2073 tria_level.neighbors.size()));
2074 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2075 tria_level.neighbors.size(),
2076 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2077 tria_level.neighbors.size()));
2078 }
2079
2080
2081
2087 void
2088 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2089 {
2090 Assert(tria_object.n_objects() == tria_object.used.size(),
2091 ExcMemoryInexact(tria_object.n_objects(),
2092 tria_object.used.size()));
2093 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2094 ExcMemoryInexact(tria_object.n_objects(),
2095 tria_object.user_flags.size()));
2096 Assert(tria_object.n_objects() ==
2097 tria_object.boundary_or_material_id.size(),
2098 ExcMemoryInexact(tria_object.n_objects(),
2099 tria_object.boundary_or_material_id.size()));
2100 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2101 ExcMemoryInexact(tria_object.n_objects(),
2102 tria_object.manifold_id.size()));
2103 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2104 ExcMemoryInexact(tria_object.n_objects(),
2105 tria_object.user_data.size()));
2106
2107 if (tria_object.structdim > 0)
2108 {
2109 const unsigned int factor = tria_object.children_per_object / 2;
2110 Assert(factor * tria_object.n_objects() ==
2111 tria_object.children.size(),
2112 ExcMemoryInexact(tria_object.n_objects(),
2113 tria_object.children.size()));
2114 }
2115 }
2116 } // namespace TriangulationImplementation
2117} // namespace internal
2118
2119
2124template <int dim, int spacedim>
2126class Triangulation<dim, spacedim>::Policy
2127{
2128public:
2132 virtual ~Policy() = default;
2133
2137 virtual void
2139
2143 virtual void
2146 std::vector<unsigned int> &line_cell_count,
2147 std::vector<unsigned int> &quad_cell_count) = 0;
2148
2154 const bool check_for_distorted_cells) = 0;
2155
2159 virtual void
2161 Triangulation<dim, spacedim> &triangulation) = 0;
2162
2166 virtual void
2168 Triangulation<dim, spacedim> &triangulation) = 0;
2169
2173 virtual bool
2175 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2176
2183 virtual std::unique_ptr<Policy>
2184 clone() = 0;
2185};
2186
2187
2188namespace internal
2189{
2190 namespace TriangulationImplementation
2191 {
2192
2198 template <int dim, int spacedim, typename T>
2199 class PolicyWrapper : public Triangulation<dim, spacedim>::Policy
2200 {
2201 public:
2202 void
2204 {
2205 T::update_neighbors(tria);
2206 }
2207
2208 void
2212 std::vector<unsigned int> &line_cell_count,
2213 std::vector<unsigned int> &quad_cell_count) override
2214 {
2215 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2216 }
2217
2220 const bool check_for_distorted_cells) override
2221 {
2222 return T::execute_refinement(triangulation, check_for_distorted_cells);
2223 }
2224
2225 void
2227 Triangulation<dim, spacedim> &triangulation) override
2228 {
2229 T::prevent_distorted_boundary_cells(triangulation);
2230 }
2231
2232 void
2234 Triangulation<dim, spacedim> &triangulation) override
2235 {
2236 T::prepare_refinement_dim_dependent(triangulation);
2237 }
2238
2239 bool
2242 override
2243 {
2244 return T::template coarsening_allowed<dim, spacedim>(cell);
2245 }
2246
2247 std::unique_ptr<typename Triangulation<dim, spacedim>::Policy>
2248 clone() override
2249 {
2250 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2251 }
2252 };
2253
2254
2260 {
2265 : offsets{0} {};
2266
2270 ArrayOfArrays(const ArrayOfArrays &) = default;
2271
2276
2280 ArrayOfArrays(const std::vector<std::size_t> &offsets,
2281 const std::vector<unsigned int> &columns)
2282 : offsets(offsets)
2283 , columns(columns)
2284 {}
2285
2290 ArrayOfArrays(std::vector<std::size_t> &&offsets,
2291 std::vector<unsigned int> &&columns)
2292 : offsets(std::move(offsets))
2293 , columns(std::move(columns))
2294 {}
2295
2300 operator=(const ArrayOfArrays &) = default;
2301
2307
2311 unsigned int
2312 size() const
2313 {
2314 return offsets.size() - 1;
2315 }
2316
2321 operator[](const unsigned int i) const
2322 {
2323 AssertIndexRange(i, offsets.size() - 1);
2325 offsets[i + 1] - offsets[i]);
2326 }
2327
2328 private:
2333 std::vector<std::size_t> offsets;
2334
2338 std::vector<unsigned int> columns;
2339 };
2340
2341
2342
2371 template <int dim>
2373 {
2375 const std::set<ReferenceCell<dim>> &all_reference_cells)
2378 {
2379 if constexpr (running_in_debug_mode())
2380 for (const auto &reference_cell : cell_types)
2381 Assert(all_reference_cells_.count(reference_cell) == 1u,
2383 }
2384
2385 const std::set<ReferenceCell<dim>> &
2387 {
2388 return all_reference_cells_;
2389 }
2390
2391 std::vector<types::geometric_orientation> &
2392 entity_orientations(const unsigned int structdim)
2393 {
2394 if (structdim == 1)
2395 return line_orientation;
2396
2397 AssertDimension(structdim, 2);
2398
2399 return quad_orientation;
2400 }
2401
2402 const std::vector<types::geometric_orientation> &
2403 entity_orientations(const unsigned int structdim) const
2404 {
2405 if (structdim == 1)
2406 return line_orientation;
2407
2408 AssertDimension(structdim, 2);
2409
2410 return quad_orientation;
2411 }
2412
2413 template <int structdim>
2414 std::vector<ReferenceCell<structdim>> &
2416 {
2417 if constexpr (structdim == dim)
2418 return cell_types;
2419 else if constexpr ((structdim == 2) && (dim == 3))
2420 {
2421 return quad_types;
2422 }
2423 else
2424 // for vertices/lines the entity types are clear
2425 // and we shouldn't need this function
2427 }
2428
2429 template <int structdim>
2430 const std::vector<ReferenceCell<structdim>> &
2432 {
2433 if constexpr (structdim == dim)
2434 return cell_types;
2435 else if constexpr ((structdim == 2) && (dim == 3))
2436 {
2437 return quad_types;
2438 }
2439 else
2440 // for vertices/lines the entity types are clear
2441 // and we shouldn't need this function
2443 }
2444
2446 entity_to_entities(const unsigned int from, const unsigned int to)
2447 {
2448 if (from == dim && to == dim)
2449 return neighbors;
2450 else if (from == dim && to == dim - 1)
2451 return cell_entities;
2452 else if (dim == 3 && from == 2 && to == 0)
2453 return quad_vertices;
2454 else if (dim == 3 && from == 2 && to == 1)
2455 return quad_lines;
2456 else if (from == 1 && to == 0)
2457 return line_vertices;
2458
2460
2461 return cell_entities;
2462 }
2463
2464 const ArrayOfArrays &
2465 entity_to_entities(const unsigned int from, const unsigned int to) const
2466 {
2467 if (from == dim && to == dim)
2468 return neighbors;
2469 else if (from == dim && to == dim - 1)
2470 return cell_entities;
2471 else if (dim == 3 && from == 2 && to == 0)
2472 return quad_vertices;
2473 else if (dim == 3 && from == 2 && to == 1)
2474 return quad_lines;
2475 else if (from == 1 && to == 0)
2476 return line_vertices;
2477
2479
2480 return cell_entities;
2481 }
2482
2483 private:
2484 std::vector<ReferenceCell<dim>> cell_types;
2485
2486 std::set<ReferenceCell<dim>> all_reference_cells_;
2487
2489
2490 std::vector<types::geometric_orientation> line_orientation;
2491
2494
2495 std::vector<types::geometric_orientation> quad_orientation;
2496
2499
2500 std::vector<ReferenceCell<2>> quad_types;
2501 };
2502
2503
2504
2513 determine_neighbors(const ArrayOfArrays &cells_to_faces)
2514 {
2515 // First determine the maximal face number used. The number of faces
2516 // is then one more (faces are counted starting at zero):
2517 unsigned int n_faces = 0;
2518 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2519 {
2520 const ArrayView<const unsigned int> face_indices =
2521 cells_to_faces[cell];
2522 n_faces = std::max(n_faces,
2523 *std::max_element(face_indices.begin(),
2524 face_indices.end()) +
2525 1);
2526 }
2527
2528 std::vector<std::size_t> cells_to_cells_offsets(cells_to_faces.size() + 1,
2529 0u);
2530 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2531 {
2532 const ArrayView<const unsigned int> face_indices =
2533 cells_to_faces[cell];
2534 cells_to_cells_offsets[cell + 1] =
2535 cells_to_cells_offsets[cell] + face_indices.size();
2536 }
2537 std::vector<unsigned int> cells_to_cells_columns(
2538 cells_to_cells_offsets.back(),
2539 /* default: cells is at the boundary in this direction */ -1);
2540
2541 std::vector<std::pair<unsigned int, unsigned int>> neighbors(
2542 n_faces,
2543 std::make_pair(numbers::invalid_unsigned_int,
2545
2546 // loop over all cells
2547 unsigned int global_face_index = 0;
2548 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2549 {
2550 // ... and all its faces
2551 const auto faces = cells_to_faces[cell];
2552 for (unsigned int f = 0; f < faces.size(); ++f, ++global_face_index)
2553 {
2554 if (neighbors[faces[f]].first == numbers::invalid_unsigned_int)
2555 {
2556 // face is visited the first time -> save the visiting cell
2557 // and the face pointer
2558 neighbors[faces[f]] = std::make_pair(cell, global_face_index);
2559 }
2560 else
2561 {
2562 // face is visited the second time -> now we know the cells
2563 // on both sides of the face and we can determine for both
2564 // cells the neighbor
2565 cells_to_cells_columns[global_face_index] =
2566 neighbors[faces[f]].first;
2567 cells_to_cells_columns[neighbors[faces[f]].second] = cell;
2568 }
2569 }
2570 }
2571
2572 return ArrayOfArrays(std::move(cells_to_cells_offsets),
2573 std::move(cells_to_cells_columns));
2574 }
2575
2576
2577
2586 template <int max_n_vertices, int face_dim, int dim, typename FU>
2587 void
2589 const std::vector<ReferenceCell<dim>> &cell_types,
2590 const ArrayOfArrays &cells_to_vertices,
2591 ArrayOfArrays &cells_to_faces, // result
2592 ArrayOfArrays &crs_0, // result
2593 std::vector<types::geometric_orientation> &orientations, // result
2594 const FU &second_key_function)
2595 {
2596 const bool compatibility_mode = true;
2597
2598 // note: we do not pre-allocate memory for these arrays because it turned
2599 // out that counting unique entities is more expensive than push_back().
2600 std::vector<std::size_t> offsets_0;
2601 std::vector<unsigned int> columns_0;
2602
2603 unsigned int n_entities = 0;
2604
2605 for (const auto &c : cell_types)
2606 {
2607 // Make sure that there are only two possibilities for
2608 // face_dim that we can cover with the ?: statement below:
2609 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2611 n_entities += (face_dim == dim - 1 ? c.n_faces() : c.n_lines());
2612 }
2613
2614 // step 1: store each d-dimensional entity of a cell (described by their
2615 // vertices) into a vector and create a key for them
2616 //
2617 // note: it turned out to be more efficient to have a vector of tuples
2618 // than to have two vectors (sorting becomes inefficient)
2619 std::vector<
2620 std::tuple<std::array<unsigned int, max_n_vertices>, unsigned int>>
2621 keys; // key (sorted vertices), cell-entity index
2622
2623 std::vector<std::array<unsigned int, max_n_vertices>> ad_entity_vertices;
2624 std::vector<ReferenceCell<face_dim>> ad_entity_types;
2625 std::vector<std::array<unsigned int, max_n_vertices>> ad_compatibility;
2626
2627 keys.reserve(n_entities);
2628 ad_entity_vertices.reserve(n_entities);
2629 ad_entity_types.reserve(n_entities);
2630 ad_compatibility.reserve(n_entities);
2631
2632 std::vector<std::size_t> cells_to_faces_offsets(cell_types.size() + 1);
2633 cells_to_faces_offsets[0] = 0;
2634
2635 constexpr unsigned int offset = 1;
2636
2637 // loop over all cells
2638 for (unsigned int c = 0, counter = 0; c < cell_types.size(); ++c)
2639 {
2640 const auto &cell_type = cell_types[c];
2641
2642 // Make sure that there are only two possibilities for
2643 // face_dimensionality that we can cover with the ?: statement below:
2644 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2646 const unsigned int n_face_entities =
2647 (face_dim == dim - 1 ? cell_type.n_faces() : cell_type.n_lines());
2648 cells_to_faces_offsets[c + 1] =
2649 cells_to_faces_offsets[c] + n_face_entities;
2650
2651 // ... loop over all its entities
2652 const ArrayView<const unsigned int> local_vertices =
2653 cells_to_vertices[c];
2654 for (unsigned int e = 0; e < n_face_entities; ++e)
2655 {
2656 // ... determine global entity vertices
2657 std::array<unsigned int, max_n_vertices> entity_vertices;
2658 std::fill(entity_vertices.begin(), entity_vertices.end(), 0);
2659
2660 // Same as above, make sure that there are only two possibilities
2661 // for face_dimensionality that we can cover with the ?: statement
2662 // below:
2663 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2665 for (unsigned int i = 0;
2666 i < (face_dim == dim - 1 ?
2667 cell_type.face_reference_cell(e).n_vertices() :
2668 ReferenceCells::Line.n_vertices());
2669 ++i)
2670 entity_vertices[i] =
2671 local_vertices[face_dim == dim - 1 ?
2672 cell_type.face_to_cell_vertices(
2673 e,
2674 i,
2676 cell_type.line_to_cell_vertices(e, i)] +
2677 offset;
2678
2679 // ... create key
2680 std::array<unsigned int, max_n_vertices> key = entity_vertices;
2681 std::sort(key.begin(), key.end());
2682 keys.emplace_back(key, counter++);
2683
2684 ad_entity_vertices.emplace_back(entity_vertices);
2685
2686 if constexpr (face_dim == dim - 1)
2687 ad_entity_types.emplace_back(cell_type.face_reference_cell(e));
2688 else if constexpr (face_dim == dim - 2)
2689 {
2690 // Since we only deal with meshes up to dimension 3,
2691 // something that has co-dimensionality -2 must either be
2692 // a vertex or a line, regardless of what the object we are
2693 // working on actually us:
2694 if constexpr (face_dim == 0)
2695 ad_entity_types.emplace_back(ReferenceCells::Vertex);
2696 else if constexpr (face_dim == 1)
2697 ad_entity_types.emplace_back(ReferenceCells::Line);
2698 else
2699 // But it's probably useful to be conservative if someone
2700 // ever comes along to implement 4d meshes:
2702 }
2703 else
2705
2706 if (compatibility_mode)
2707 ad_compatibility.emplace_back(
2708 second_key_function(entity_vertices, cell_type, c, e));
2709 }
2710 }
2711
2712 std::vector<unsigned int> cells_to_faces_indices(keys.size());
2713 orientations.assign(keys.size(), numbers::default_geometric_orientation);
2714
2715 // step 2: sort according to key so that entities with same key can be
2716 // merged
2717 std::sort(keys.begin(), keys.end());
2718
2719 if (compatibility_mode)
2720 {
2721 unsigned int n_unique_entities = 0;
2722 unsigned int n_unique_entity_vertices = 0;
2723
2724 std::array<unsigned int, max_n_vertices> ref_key, new_key;
2725 std::fill(ref_key.begin(), ref_key.end(), 0);
2726 for (unsigned int i = 0; i < keys.size(); ++i)
2727 {
2728 const auto offset_i = std::get<1>(keys[i]);
2729
2730 if (ref_key != std::get<0>(keys[i]))
2731 {
2732 ref_key = std::get<0>(keys[i]);
2733
2734 ++n_unique_entities;
2735 n_unique_entity_vertices +=
2736 ad_entity_types[offset_i].n_vertices();
2737
2738 new_key = ad_compatibility[offset_i];
2739 }
2740
2741 std::get<0>(keys[i]) = new_key;
2742 }
2743
2744 std::sort(keys.begin(), keys.end());
2745
2746 offsets_0.reserve(n_unique_entities + 1);
2747 columns_0.reserve(n_unique_entity_vertices);
2748 }
2749
2750
2751 std::array<unsigned int, max_n_vertices> ref_key;
2752 std::array<unsigned int, max_n_vertices> ref_indices;
2753 std::fill(ref_key.begin(), ref_key.end(), 0);
2754
2755 unsigned int counter = ::numbers::invalid_unsigned_int;
2756 for (unsigned int i = 0; i < keys.size(); i++)
2757 {
2758 const auto offset_i = std::get<1>(keys[i]);
2759
2760 if (ref_key != std::get<0>(keys[i]))
2761 {
2762 // new key: default orientation is correct
2763 ++counter;
2764 ref_key = std::get<0>(keys[i]);
2765 ref_indices = ad_entity_vertices[offset_i];
2766
2767 offsets_0.push_back(columns_0.size());
2768 for (const auto j : ad_entity_vertices[offset_i])
2769 if (j != 0)
2770 columns_0.push_back(j - offset);
2771 }
2772 else
2773 {
2774 // previously seen key: set orientation relative to the first
2775 // occurrence
2776 orientations[offset_i] =
2777 ad_entity_types[offset_i]
2778 .template get_combined_orientation<unsigned int>(
2779 make_array_view(ad_entity_vertices[offset_i].begin(),
2780 ad_entity_vertices[offset_i].begin() +
2781 ad_entity_types[offset_i].n_vertices()),
2782 make_array_view(ref_indices.begin(),
2783 ref_indices.begin() +
2784 ad_entity_types[offset_i].n_vertices()));
2785 }
2786 cells_to_faces_indices[offset_i] = counter;
2787 }
2788 offsets_0.push_back(columns_0.size());
2789
2790 // Finally build the output objects:
2791 crs_0 = ArrayOfArrays(std::move(offsets_0), std::move(columns_0));
2792 cells_to_faces = ArrayOfArrays(std::move(cells_to_faces_offsets),
2793 std::move(cells_to_faces_indices));
2794 }
2795
2796
2797
2802 template <int face_dim, int dim, typename FU>
2803 void
2804 build_face_entities(const std::vector<ReferenceCell<dim>> &cell_types,
2805 const ArrayOfArrays &cells_to_vertices,
2806 ArrayOfArrays &cells_to_faces,
2807 ArrayOfArrays &crs_0,
2808 std::vector<types::geometric_orientation> &orientations,
2809 const FU &second_key_function)
2810 {
2811 unsigned int max_n_vertices = 0;
2812
2813 // If we are dealing with faces of cells, figure out how many vertices
2814 // each face may have. Otherwise, we're in 3d and are dealing with
2815 // lines, for which we know the number of vertices:
2816 for (const auto &c : cell_types)
2817 if (face_dim == dim - 1)
2818 {
2819 for (unsigned int f = 0; f < c.n_faces(); ++f)
2820 max_n_vertices =
2821 std::max(max_n_vertices, c.face_reference_cell(f).n_vertices());
2822 }
2823 else if (face_dim == 1)
2824 max_n_vertices = std::max(max_n_vertices, 2u);
2825 else
2827
2828 if (max_n_vertices == 2)
2829 build_face_entities_templated<2, face_dim>(cell_types,
2830 cells_to_vertices,
2831 cells_to_faces,
2832 crs_0,
2833 orientations,
2834 second_key_function);
2835 else if (max_n_vertices == 3)
2836 build_face_entities_templated<3, face_dim>(cell_types,
2837 cells_to_vertices,
2838 cells_to_faces,
2839 crs_0,
2840 orientations,
2841 second_key_function);
2842 else if (max_n_vertices == 4)
2843 build_face_entities_templated<4, face_dim>(cell_types,
2844 cells_to_vertices,
2845 cells_to_faces,
2846 crs_0,
2847 orientations,
2848 second_key_function);
2849 else
2851 }
2852
2853
2854
2862 template <int dim>
2863 void
2865 const std::vector<ReferenceCell<dim>> &cell_types,
2866 const ArrayOfArrays &cells_to_vertices,
2867 const ArrayOfArrays &cells_to_lines,
2868 const ArrayOfArrays &lines_to_vertices,
2869 const ArrayOfArrays &cells_to_quads,
2870 const ArrayOfArrays &quads_to_vertices,
2871 const std::vector<types::geometric_orientation> &ori_cq,
2872 ArrayOfArrays &quads_to_lines, // result
2873 std::vector<types::geometric_orientation> &ori_ql, // result
2874 std::vector<ReferenceCell<2>> &quad_t_id // result
2875 )
2876 {
2877 quad_t_id.resize(quads_to_vertices.size());
2878
2879 // Build the offsets of the compressed representation of the
2880 // quads-to-lines array by counting the number of lines of each face.
2881 // We do this by looping over all cells and querying their faces.
2882 // This encounters faces in a random order, so we first
2883 // store the number of lines of the f'th face in the (f+1)st
2884 // offset and then run a prefix sum to sum up all
2885 // previous offsets
2886 std::vector<std::size_t> quads_to_lines_offsets(quads_to_vertices.size() +
2887 1);
2888 for (unsigned int c = 0; c < cells_to_quads.size(); ++c)
2889 {
2890 // loop over faces
2891 const ArrayView<const unsigned int> faces = cells_to_quads[c];
2892 for (unsigned int f = 0; f < faces.size(); ++f)
2893 {
2894 quads_to_lines_offsets[faces[f] + 1] =
2895 cell_types[c].face_reference_cell(f).n_lines();
2896 }
2897 }
2898 quads_to_lines_offsets[0] = 0;
2899 for (unsigned int i = 0; i < quads_to_lines_offsets.size() - 1; ++i)
2900 quads_to_lines_offsets[i + 1] += quads_to_lines_offsets[i];
2901
2902 // Now that we have the offsets, allocate memory for the indices:
2903 std::vector<unsigned int> quads_to_lines_indices(
2904 quads_to_lines_offsets.back());
2905 ori_ql.assign(quads_to_lines_offsets.back(),
2907
2908 // loop over cells
2909 unsigned int global_face_index = 0;
2910 for (unsigned int c = 0; c < cells_to_quads.size(); ++c)
2911 {
2912 const ReferenceCell<dim> cell_type = cell_types[c];
2913
2914 // loop over faces
2915 const ArrayView<const unsigned int> faces = cells_to_quads[c];
2916 for (unsigned int f_index = 0; f_index < faces.size();
2917 ++f_index, ++global_face_index)
2918 {
2919 const unsigned int f = faces[f_index];
2920
2921 // only faces with default orientation have to do something
2922 if (ori_cq[global_face_index] !=
2924 continue;
2925
2926 // loop over the lines of this face
2927 quad_t_id[f] = cell_type.face_reference_cell(f_index);
2928 for (unsigned int l = 0; l < quad_t_id[f].n_lines(); ++l)
2929 {
2930 // determine global index of line
2931 const unsigned int local_line_index =
2932 cell_type.face_to_cell_lines(
2934 const unsigned int global_line_index =
2935 cells_to_lines[c][local_line_index];
2936 quads_to_lines_indices[quads_to_lines_offsets[f] + l] =
2937 global_line_index;
2938
2939 // determine orientation of line
2940 bool same = true;
2941 for (unsigned int v = 0; v < 2; ++v)
2942 if (cells_to_vertices
2943 [c][cell_type.face_and_line_to_cell_vertices(
2944 f_index,
2945 l,
2946 v,
2948 lines_to_vertices[global_line_index][v])
2949 {
2950 same = false;
2951 break;
2952 }
2953
2954 // ... comparison gives orientation
2955 ori_ql[quads_to_lines_offsets[f] + l] =
2958 }
2959 }
2960 }
2961
2962 // Finally build the output object:
2963 quads_to_lines = ArrayOfArrays(std::move(quads_to_lines_offsets),
2964 std::move(quads_to_lines_indices));
2965 }
2966
2967
2968
2977 template <int dim>
2978 Connectivity<dim>
2979 build_connectivity(const std::vector<ReferenceCell<dim>> &cell_types,
2980 const std::set<ReferenceCell<dim>> &all_reference_cells,
2981 const ArrayOfArrays &cells_to_vertices)
2982 {
2983 Connectivity<dim> connectivity(cell_types, all_reference_cells);
2984
2985 ArrayOfArrays temp1; // needed for 3d
2986
2987 if constexpr (dim == 1)
2988 connectivity.entity_to_entities(1, 0) = cells_to_vertices;
2989
2990 if constexpr (dim == 2 || dim == 3) // build lines
2991 {
2992 std::vector<types::geometric_orientation> dummy;
2993
2994 build_face_entities<1>(
2995 connectivity.template entity_types<dim>(),
2996 cells_to_vertices,
2997 dim == 2 ? connectivity.entity_to_entities(2, 1) : temp1,
2998 connectivity.entity_to_entities(1, 0),
2999 dim == 2 ? connectivity.entity_orientations(1) : dummy,
3000 [](auto key, const auto &, const auto &, const auto &) {
3001 // to ensure same enumeration as in deal.II
3002 return key;
3003 });
3004 }
3005
3006 if constexpr (dim == 3) // build quads
3007 {
3008 build_face_entities<2>(
3009 connectivity.template entity_types<3>(),
3010 cells_to_vertices,
3011 connectivity.entity_to_entities(3, 2),
3012 connectivity.entity_to_entities(2, 0),
3013 connectivity.entity_orientations(2),
3014 [&](auto key, // of type std::array<unsigned int, max_n_vertices>
3015 // but max_n_vertices is not known here
3016 const ReferenceCell<dim> &cell_type,
3017 const unsigned int &c,
3018 const unsigned int &f) {
3019 // to ensure same enumeration as in deal.II
3020 AssertIndexRange(cell_type.face_reference_cell(f).n_lines(),
3021 key.size() + 1);
3022
3023 unsigned int l = 0;
3024
3025 for (; l < cell_type.face_reference_cell(f).n_lines(); ++l)
3026 {
3027 AssertIndexRange(l, key.size());
3028 key[l] = temp1[c][cell_type.face_to_cell_lines(
3029 f, l, numbers::default_geometric_orientation)] +
3030 1 /*offset!*/;
3031 }
3032
3033 for (; l < key.size(); ++l)
3034 key[l] = 0;
3035
3036 return key;
3037 });
3038
3039 // create connectivity: quad -> line
3040 build_intersection(connectivity.template entity_types<3>(),
3041 cells_to_vertices,
3042 temp1,
3043 connectivity.entity_to_entities(1, 0),
3044 connectivity.entity_to_entities(3, 2),
3045 connectivity.entity_to_entities(2, 0),
3046 connectivity.entity_orientations(2),
3047 connectivity.entity_to_entities(2, 1),
3048 connectivity.entity_orientations(1),
3049 connectivity.template entity_types<2>());
3050 }
3051
3052 // determine neighbors
3053 connectivity.entity_to_entities(dim, dim) =
3054 determine_neighbors(connectivity.entity_to_entities(dim, dim - 1));
3055
3056 return connectivity;
3057 }
3058
3059
3060
3064 template <int dim>
3065 Connectivity<dim>
3066 build_connectivity(const std::vector<CellData<dim>> &cells)
3067 {
3068 AssertThrow(cells.size() > 0, ExcMessage("No cells have been provided!"));
3069
3070 // determine cell types and process vertices
3071 std::vector<unsigned int> cell_vertices;
3072 cell_vertices.reserve(std::accumulate(cells.begin(),
3073 cells.end(),
3074 0u,
3075 [](const unsigned int accumulator,
3076 const CellData<dim> &cell) {
3077 return accumulator +
3078 cell.vertices.size();
3079 }));
3080
3081 std::vector<std::size_t> cell_vertices_offsets;
3082 cell_vertices_offsets.reserve(cells.size() + 1);
3083 cell_vertices_offsets.push_back(0);
3084
3085 std::vector<ReferenceCell<dim>> cell_types;
3086 cell_types.reserve(cells.size());
3087
3088 // Looping over all the cells can be expensive, so we mark the kinds of
3089 // ReferenceCells we have just once
3090 std::set<ReferenceCell<dim>> all_reference_cells;
3091 // loop over cells and create CRS
3092 for (const auto &cell : cells)
3093 {
3094 if constexpr (running_in_debug_mode())
3095 {
3096 auto vertices_unique = cell.vertices;
3097 std::sort(vertices_unique.begin(), vertices_unique.end());
3098 vertices_unique.erase(std::unique(vertices_unique.begin(),
3099 vertices_unique.end()),
3100 vertices_unique.end());
3101
3102 Assert(
3103 vertices_unique.size() == cell.vertices.size(),
3104 ExcMessage(
3105 "The definition of a cell refers to the same vertex several "
3106 "times. This is not possible. A common reason is that "
3107 "CellData::vertices has a size that does not match the "
3108 "size expected from the reference cell. Please resize "
3109 "CellData::vertices or use the appropriate constructor of "
3110 "CellData."));
3111 }
3112
3113 cell_types.push_back(
3114 ReferenceCells::n_vertices_to_reference_cell<dim>(
3115 cell.vertices.size()));
3116 all_reference_cells.insert(cell_types.back());
3117
3118 // create CRS of vertices (to remove template argument dim)
3119 cell_vertices.insert(cell_vertices.end(),
3120 cell.vertices.begin(),
3121 cell.vertices.end());
3122 cell_vertices_offsets.push_back(cell_vertices.size());
3123 }
3124
3125 // do the actual work
3126 return build_connectivity(cell_types,
3127 all_reference_cells,
3128 {std::move(cell_vertices_offsets),
3129 std::move(cell_vertices)});
3130 }
3131
3132
3229 {
3241 template <int dim, int spacedim>
3242 static void
3244 const Triangulation<dim, spacedim> &triangulation,
3245 const unsigned int level_objects,
3247 {
3248 using line_iterator =
3250
3251 number_cache.n_levels = 0;
3252 if (level_objects > 0)
3253 // find the last level on which there are used cells
3254 for (unsigned int level = 0; level < level_objects; ++level)
3255 if (triangulation.begin(level) != triangulation.end(level))
3256 number_cache.n_levels = level + 1;
3257
3258 // no cells at all?
3259 Assert(number_cache.n_levels > 0, ExcInternalError());
3260
3261 //---------------------------------
3262 // update the number of lines on the different levels in the
3263 // cache
3264 number_cache.n_lines = 0;
3265 number_cache.n_active_lines = 0;
3266
3267 // for 1d, lines have levels so take count the objects per
3268 // level and globally
3269 if (dim == 1)
3270 {
3271 number_cache.n_lines_level.resize(number_cache.n_levels);
3272 number_cache.n_active_lines_level.resize(number_cache.n_levels);
3273
3274 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
3275 {
3276 // count lines on this level
3277 number_cache.n_lines_level[level] = 0;
3278 number_cache.n_active_lines_level[level] = 0;
3279
3280 line_iterator line = triangulation.begin_line(level),
3281 endc =
3282 (level == number_cache.n_levels - 1 ?
3283 line_iterator(triangulation.end_line()) :
3284 triangulation.begin_line(level + 1));
3285 for (; line != endc; ++line)
3286 {
3287 ++number_cache.n_lines_level[level];
3288 if (line->has_children() == false)
3289 ++number_cache.n_active_lines_level[level];
3290 }
3291
3292 // update total number of lines
3293 number_cache.n_lines += number_cache.n_lines_level[level];
3294 number_cache.n_active_lines +=
3295 number_cache.n_active_lines_level[level];
3296 }
3297 }
3298 else
3299 {
3300 // for dim>1, there are no levels for lines
3301 number_cache.n_lines_level.clear();
3302 number_cache.n_active_lines_level.clear();
3303
3304 line_iterator line = triangulation.begin_line(),
3305 endc = triangulation.end_line();
3306 for (; line != endc; ++line)
3307 {
3308 ++number_cache.n_lines;
3309 if (line->has_children() == false)
3310 ++number_cache.n_active_lines;
3311 }
3312 }
3313 }
3314
3329 template <int dim, int spacedim>
3330 static void
3332 const Triangulation<dim, spacedim> &triangulation,
3333 const unsigned int level_objects,
3335 {
3336 // update lines and n_levels in number_cache. since we don't
3337 // access any of these numbers, we can do this in the
3338 // background
3339 Threads::Task<void> update_lines = Threads::new_task([&]() {
3340 compute_number_cache_dim(
3341 triangulation,
3342 level_objects,
3343 // Select the 1d part of the cache:
3345 &>(number_cache));
3346 });
3347
3348 using quad_iterator =
3350
3351 //---------------------------------
3352 // update the number of quads on the different levels in the
3353 // cache
3354 number_cache.n_quads = 0;
3355 number_cache.n_active_quads = 0;
3356
3357 // for 2d, quads have levels so take count the objects per
3358 // level and globally
3359 if (dim == 2)
3360 {
3361 // count the number of levels; the function we called above
3362 // on a separate Task for lines also does this and puts it into
3363 // number_cache.n_levels, but this datum may not yet be
3364 // available as we call the function on a separate task
3365 unsigned int n_levels = 0;
3366 if (level_objects > 0)
3367 // find the last level on which there are used cells
3368 for (unsigned int level = 0; level < level_objects; ++level)
3369 if (triangulation.begin(level) != triangulation.end(level))
3370 n_levels = level + 1;
3371
3372 number_cache.n_quads_level.resize(n_levels);
3373 number_cache.n_active_quads_level.resize(n_levels);
3374
3375 for (unsigned int level = 0; level < n_levels; ++level)
3376 {
3377 // count quads on this level
3378 number_cache.n_quads_level[level] = 0;
3379 number_cache.n_active_quads_level[level] = 0;
3380
3381 quad_iterator quad = triangulation.begin_quad(level),
3382 endc =
3383 (level == n_levels - 1 ?
3384 quad_iterator(triangulation.end_quad()) :
3385 triangulation.begin_quad(level + 1));
3386 for (; quad != endc; ++quad)
3387 {
3388 ++number_cache.n_quads_level[level];
3389 if (quad->has_children() == false)
3390 ++number_cache.n_active_quads_level[level];
3391 }
3392
3393 // update total number of quads
3394 number_cache.n_quads += number_cache.n_quads_level[level];
3395 number_cache.n_active_quads +=
3396 number_cache.n_active_quads_level[level];
3397 }
3398 }
3399 else
3400 {
3401 // for dim>2, there are no levels for quads
3402 number_cache.n_quads_level.clear();
3403 number_cache.n_active_quads_level.clear();
3404
3405 quad_iterator quad = triangulation.begin_quad(),
3406 endc = triangulation.end_quad();
3407 for (; quad != endc; ++quad)
3408 {
3409 ++number_cache.n_quads;
3410 if (quad->has_children() == false)
3411 ++number_cache.n_active_quads;
3412 }
3413 }
3414
3415 // wait for the background computation for lines
3416 update_lines.join();
3417 }
3418
3434 template <int dim, int spacedim>
3435 static void
3437 const Triangulation<dim, spacedim> &triangulation,
3438 const unsigned int level_objects,
3440 {
3441 // update quads, lines and n_levels in number_cache. since we
3442 // don't access any of these numbers, we can do this in the
3443 // background
3444 Threads::Task<void> update_quads_and_lines = Threads::new_task([&]() {
3445 compute_number_cache_dim(
3446 triangulation,
3447 level_objects,
3448 // Select the 1d and 2d part of the cache:
3450 &>(number_cache));
3451 });
3452
3453 using hex_iterator =
3455
3456 //---------------------------------
3457 // update the number of hexes on the different levels in the
3458 // cache
3459 number_cache.n_hexes = 0;
3460 number_cache.n_active_hexes = 0;
3461
3462 // for 3d, hexes have levels so take count the objects per
3463 // level and globally
3464 if (dim == 3)
3465 {
3466 // count the number of levels; the function we called
3467 // above on a separate Task for quads (recursively, via
3468 // the lines function) also does this and puts it into
3469 // number_cache.n_levels, but this datum may not yet be
3470 // available as we call the function on a separate task
3471 unsigned int n_levels = 0;
3472 if (level_objects > 0)
3473 // find the last level on which there are used cells
3474 for (unsigned int level = 0; level < level_objects; ++level)
3475 if (triangulation.begin(level) != triangulation.end(level))
3476 n_levels = level + 1;
3477
3478 number_cache.n_hexes_level.resize(n_levels);
3479 number_cache.n_active_hexes_level.resize(n_levels);
3480
3481 for (unsigned int level = 0; level < n_levels; ++level)
3482 {
3483 // count hexes on this level
3484 number_cache.n_hexes_level[level] = 0;
3485 number_cache.n_active_hexes_level[level] = 0;
3486
3487 hex_iterator hex = triangulation.begin_hex(level),
3488 endc = (level == n_levels - 1 ?
3489 hex_iterator(triangulation.end_hex()) :
3490 triangulation.begin_hex(level + 1));
3491 for (; hex != endc; ++hex)
3492 {
3493 ++number_cache.n_hexes_level[level];
3494 if (hex->has_children() == false)
3495 ++number_cache.n_active_hexes_level[level];
3496 }
3497
3498 // update total number of hexes
3499 number_cache.n_hexes += number_cache.n_hexes_level[level];
3500 number_cache.n_active_hexes +=
3501 number_cache.n_active_hexes_level[level];
3502 }
3503 }
3504 else
3505 {
3506 // for dim>3, there are no levels for hexes
3507 number_cache.n_hexes_level.clear();
3508 number_cache.n_active_hexes_level.clear();
3509
3510 hex_iterator hex = triangulation.begin_hex(),
3511 endc = triangulation.end_hex();
3512 for (; hex != endc; ++hex)
3513 {
3514 ++number_cache.n_hexes;
3515 if (hex->has_children() == false)
3516 ++number_cache.n_active_hexes;
3517 }
3518 }
3519
3520 // wait for the background computation for quads
3521 update_quads_and_lines.join();
3522 }
3523
3524
3525 template <int dim, int spacedim>
3526 static void
3528 const Triangulation<dim, spacedim> &triangulation,
3529 const unsigned int level_objects,
3531 {
3532 compute_number_cache_dim(triangulation, level_objects, number_cache);
3533
3534 number_cache.active_cell_index_partitioner =
3535 std::make_shared<const Utilities::MPI::Partitioner>(
3536 triangulation.n_active_cells());
3537
3538 number_cache.level_cell_index_partitioners.resize(
3539 triangulation.n_levels());
3540 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3541 number_cache.level_cell_index_partitioners[level] =
3542 std::make_shared<const Utilities::MPI::Partitioner>(
3543 triangulation.n_cells(level));
3544 }
3545
3546
3547 template <int spacedim>
3548 static void
3551
3552
3553 template <int dim, int spacedim>
3554 static void
3556 {
3557 // each face can be neighbored on two sides by cells. according to the
3558 // face's intrinsic normal we define the left neighbor as the one for
3559 // which the face normal points outward, and store that one first; the
3560 // second one is then the right neighbor for which the face normal
3561 // points inward. This information depends on the type of cell and
3562 // local number of face for the 'standard ordering and orientation' of
3563 // faces and then on the face_orientation information for the real
3564 // mesh. Set up a table to have fast access to those offsets (0 for
3565 // left and 1 for right). Some of the values are invalid as they
3566 // reference too large face numbers, but we just leave them at a zero
3567 // value.
3568 //
3569 // Note, that in 2d for lines as faces the normal direction given in
3570 // the GeometryInfo class is not consistent. We thus define here that
3571 // the normal for a line points to the right if the line points
3572 // upwards.
3573 //
3574 // There is one more point to consider, however: if we have
3575 // dim<spacedim, then we may have cases where cells are inverted. In
3576 // effect, both cells think they are the left neighbor of an edge, for
3577 // example, which leads us to forget neighborship information (a case
3578 // that shows this is codim_one/hanging_nodes_02). We store whether a
3579 // cell is inverted using the direction_flag, so if a cell has a false
3580 // direction_flag, then we need to invert our selection whether we are
3581 // a left or right neighbor in all following computations.
3582 //
3583 // first index: dimension (minus 2)
3584 // second index: local face index
3585 // third index: face_orientation (false and true)
3586 constexpr unsigned int left_right_offset[2][6][2] = {
3587 // quadrilateral
3588 {{0, 1}, // face 0, face_orientation = false and true
3589 {1, 0}, // face 1, face_orientation = false and true
3590 {1, 0}, // face 2, face_orientation = false and true
3591 {0, 1}, // face 3, face_orientation = false and true
3592 {0, 0}, // face 4, invalid face
3593 {0, 0}}, // face 5, invalid face
3594 // hexahedron
3595 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3596
3597 // now create a vector of the two active neighbors (left and right)
3598 // for each face and fill it by looping over all cells. For cases with
3599 // anisotropic refinement and more than one cell neighboring at a
3600 // given side of the face we will automatically get the active one on
3601 // the highest level as we loop over cells from lower levels first.
3602 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3603 adjacent_cells(2 * triangulation.n_raw_faces(), triangulation.end());
3604
3605 for (const auto &cell : triangulation.cell_iterators())
3606 for (auto f : cell->face_indices())
3607 {
3609 cell->face(f);
3610
3611 const unsigned int offset =
3612 (cell->direction_flag() ?
3613 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3614 1 -
3615 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3616
3617 adjacent_cells[2 * face->index() + offset] = cell;
3618
3619 // if this cell is not refined, but the face is, then we'll have
3620 // to set our cell as neighbor for the child faces as
3621 // well. Fortunately the normal orientation of children will be
3622 // just the same.
3623 if (dim == 2)
3624 {
3625 if (cell->is_active() && face->has_children())
3626 {
3627 adjacent_cells[2 * face->child(0)->index() + offset] =
3628 cell;
3629 adjacent_cells[2 * face->child(1)->index() + offset] =
3630 cell;
3631 }
3632 }
3633 else // -> dim == 3
3634 {
3635 // We need the same as in 2d here. Furthermore, if the face
3636 // is refined with cut_x or cut_y then those children again
3637 // in the other direction, and if this cell is refined
3638 // isotropically (along the face) then the neighbor will
3639 // (probably) be refined as cut_x or cut_y along the
3640 // face. For those neighboring children cells, their
3641 // neighbor will be the current, inactive cell, as our
3642 // children are too fine to be neighbors. Catch that case by
3643 // also acting on inactive cells with isotropic refinement
3644 // along the face. If the situation described is not
3645 // present, the data will be overwritten later on when we
3646 // visit cells on finer levels, so no harm will be done.
3647 if (face->has_children() &&
3648 (cell->is_active() ||
3650 cell->refinement_case(), f) ==
3652 {
3653 for (unsigned int c = 0; c < face->n_children(); ++c)
3654 adjacent_cells[2 * face->child(c)->index() + offset] =
3655 cell;
3656 if (face->child(0)->has_children())
3657 {
3658 adjacent_cells[2 * face->child(0)->child(0)->index() +
3659 offset] = cell;
3660 adjacent_cells[2 * face->child(0)->child(1)->index() +
3661 offset] = cell;
3662 }
3663 if (face->child(1)->has_children())
3664 {
3665 adjacent_cells[2 * face->child(1)->child(0)->index() +
3666 offset] = cell;
3667 adjacent_cells[2 * face->child(1)->child(1)->index() +
3668 offset] = cell;
3669 }
3670 } // if cell active and face refined
3671 } // else -> dim==3
3672 } // for all faces of all cells
3673
3674 // now loop again over all cells and set the corresponding neighbor
3675 // cell. Note, that we have to use the opposite of the
3676 // left_right_offset in this case as we want the offset of the
3677 // neighbor, not our own.
3678 for (const auto &cell : triangulation.cell_iterators())
3679 for (auto f : cell->face_indices())
3680 {
3681 const unsigned int offset =
3682 (cell->direction_flag() ?
3683 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3684 1 -
3685 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3686 cell->set_neighbor(
3687 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3688 }
3689 }
3690
3691
3695 template <int dim, int spacedim>
3696 static void
3697 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3698 const std::vector<CellData<dim>> &cells,
3699 const SubCellData &subcelldata,
3701 {
3702 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3703 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3704
3705 // Check that all cells have positive volume.
3706#ifndef _MSC_VER
3707 // TODO: The following code does not compile with MSVC. Find a way
3708 // around it
3709 if (dim == spacedim)
3710 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3711 {
3712 // If we should check for distorted cells, then we permit them
3713 // to exist. If a cell has negative measure, then it must be
3714 // distorted (the converse is not necessarily true); hence
3715 // throw an exception if no such cells should exist.
3717 {
3718 const double cell_measure = GridTools::cell_measure<spacedim>(
3719 vertices,
3720 ArrayView<const unsigned int>(cells[cell_no].vertices));
3721 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3722 }
3723 }
3724#endif
3725
3726 // copy vertices
3727 tria.vertices = vertices;
3728 tria.vertices_used.assign(vertices.size(), true);
3729
3730 // compute connectivity
3731 const auto connectivity = build_connectivity(cells);
3732 const auto n_cells = cells.size();
3733
3734 // set up reference cells for the first time
3735 const auto all_reference_cells =
3736 Utilities::MPI::compute_set_union(connectivity.all_reference_cells(),
3737 tria.get_mpi_communicator());
3738 tria.reference_cells.assign(all_reference_cells.begin(),
3739 all_reference_cells.end());
3741 tria.reference_cells);
3742
3743 // clear old content
3744 tria.levels.clear();
3745 tria.levels.push_back(
3746 std::make_unique<
3748 tria.strides.max_children_per_cell,
3749 tria.strides.max_faces_per_cell,
3750 tria.strides.max_vertices_per_cell));
3751
3752 if (dim > 1)
3753 tria.faces = std::make_unique<
3755 tria.strides.max_children_per_face,
3756 tria.strides.max_lines_per_face);
3757
3758 const ArrayOfArrays empty;
3759 const ArrayOfArrays &lines_to_vertices =
3760 dim > 1 ? connectivity.entity_to_entities(1, 0) : empty;
3761 const ArrayOfArrays &quads_to_lines =
3762 dim == 3 ? connectivity.entity_to_entities(2, 1) : empty;
3763 const auto n_lines = lines_to_vertices.size();
3765 n_lines <= std::size_t(std::numeric_limits<int>::max()),
3766 ExcMessage("The number of lines must be less than the largest int."));
3767 const auto n_quads = quads_to_lines.size();
3769 n_quads <= std::size_t(std::numeric_limits<int>::max()),
3770 ExcMessage("The number of quads must be less than the largest int."));
3771
3772 if (dim > 1)
3773 tria.faces->allocate(n_lines, n_quads);
3774
3775 // TriaObjects: lines
3776 if (dim > 1)
3777 {
3778 auto &faces = *tria.faces;
3779 // loop over lines
3780 for (int line = 0; line < int(n_lines); ++line)
3781 {
3782 const auto vertices = lines_to_vertices[line];
3783 for (unsigned int v = 0; v < vertices.size(); ++v)
3784 faces.lines.set_bounding_object(line, v, vertices[v]);
3785 }
3786 }
3787
3788 // TriaObjects: quads
3789 if constexpr (dim == 3)
3790 {
3791 auto &faces = *tria.faces;
3792 // get connectivity between quads and lines
3793
3794 // loop over all quads -> entity type, line indices/orientations
3795 for (int q = 0, k = 0; q < int(n_quads); ++q)
3796 {
3797 // set entity type of quads
3798 const auto face_reference_cell =
3799 connectivity.template entity_types<2>()[q];
3800 faces.set_quad_type(q, face_reference_cell);
3801
3802 // loop over all its lines
3803 const auto lines = quads_to_lines[q];
3804 for (unsigned int l = 0; l < lines.size(); ++l, ++k)
3805 {
3806 AssertIndexRange(l, face_reference_cell.n_lines());
3807 // set line index
3808 faces.quads.set_bounding_object(q, l, lines[l]);
3809
3810 // set line orientations
3811 faces.set_line_orientation(
3812 q, l, connectivity.entity_orientations(1)[k]);
3813 }
3814 }
3815 }
3816
3817 // TriaObjects/TriaLevel: cell
3818 {
3819 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3820 auto &level = *tria.levels[0];
3821
3822 // get connectivity between cells/faces and cells/cells
3823 const auto &cells_to_faces =
3824 connectivity.entity_to_entities(dim, dim - 1);
3825 const auto &cells_to_neighbor_cells =
3826 connectivity.entity_to_entities(dim, dim);
3827
3828 // in 2d optional: since in in pure QUAD meshes same line
3829 // orientations can be guaranteed
3830 bool orientation_needed = false;
3831 if (dim == 3)
3832 orientation_needed = true;
3833 else if (dim == 2)
3834 {
3835 const auto &orientations = connectivity.entity_orientations(1);
3836 orientation_needed = std::any_of(
3837 orientations.begin(), orientations.end(), [](const auto &a) {
3838 return a != numbers::default_geometric_orientation;
3839 });
3840 }
3841
3842 level.allocate(n_cells, orientation_needed);
3843 // loop over all cells
3844 unsigned int global_face_index = 0;
3845 for (unsigned int cell = 0; cell < n_cells; ++cell)
3846 {
3847 // set material ids
3848 cells_0.boundary_or_material_id[cell].material_id =
3849 cells[cell].material_id;
3850
3851 // set manifold ids
3852 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3853
3854 // set entity types
3855 level.reference_cell[cell] =
3856 connectivity.template entity_types<dim>()[cell];
3857 Assert(all_reference_cells.count(level.reference_cell[cell]) ==
3858 1u,
3860
3861 // loop over faces
3862 const auto faces = cells_to_faces[cell];
3863 const auto neighbors = cells_to_neighbor_cells[cell];
3864 for (unsigned int f = 0; f < faces.size();
3865 ++f, ++global_face_index)
3866 {
3867 // set neighbor if not at boundary
3868 if (neighbors[f] != numbers::invalid_unsigned_int)
3869 level.set_neighbor(cell, f, 0, neighbors[f]);
3870
3871 // set face indices
3872 cells_0.set_bounding_object(cell, f, faces[f]);
3873
3874 // set face orientation if needed
3875 if (orientation_needed)
3876 {
3877 level.face_orientations.set_combined_orientation(
3878 cell,
3879 f,
3880 connectivity.entity_orientations(dim -
3881 1)[global_face_index]);
3882 }
3883 }
3884 }
3885 }
3886
3887 // TriaFaces: boundary id of boundary faces
3888 if (dim > 1)
3889 {
3890 auto &bids_face = dim == 3 ?
3891 tria.faces->quads.boundary_or_material_id :
3892 tria.faces->lines.boundary_or_material_id;
3893
3894 // count number of cells a face is belonging to
3895 std::vector<unsigned int> count(bids_face.size(), 0);
3896
3897 // get connectivity between cells/faces
3898 const auto &cells_to_faces =
3899 connectivity.entity_to_entities(dim, dim - 1);
3900
3901 // count how many cells are adjacent to the same face
3902 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3903 for (const unsigned int face : cells_to_faces[cell])
3904 ++count[face];
3905
3906 // loop over all faces
3907 for (unsigned int face = 0; face < count.size(); ++face)
3908 {
3909 if (count[face] != 1) // inner face
3910 continue;
3911
3912 // boundary faces ...
3913 bids_face[face].boundary_id = 0;
3914
3915 if (dim != 3)
3916 continue;
3917
3918 // ... and the lines of quads in 3d
3919 const auto &quads_to_lines =
3920 connectivity.entity_to_entities(2, 1);
3921 for (const unsigned int line : quads_to_lines[face])
3922 tria.faces->lines.boundary_or_material_id[line].boundary_id =
3923 0;
3924 }
3925 }
3926 else // 1d
3927 {
3928 constexpr unsigned int t_tba = static_cast<unsigned int>(-1);
3929 constexpr unsigned int t_inner = static_cast<unsigned int>(-2);
3930
3931 std::vector<unsigned int> type(vertices.size(), t_tba);
3932
3933 const auto &cells_to_vertices =
3934 connectivity.entity_to_entities(1, 0);
3935
3936 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3937 {
3938 const auto vertices = cells_to_vertices[cell];
3939 for (unsigned int v = 0; v < vertices.size(); ++v)
3940 if (type[vertices[v]] != t_inner)
3941 type[vertices[v]] =
3942 (type[vertices[v]] == t_tba ? v : t_inner);
3943 }
3944
3945 for (unsigned int face = 0; face < type.size(); ++face)
3946 {
3947 // note: we also treat manifolds here!?
3948 (*tria.vertex_to_manifold_id_map_1d)[face] =
3950 if (type[face] != t_inner && type[face] != t_tba)
3951 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3952 }
3953 }
3954
3955 // SubCellData: line
3956 if (dim >= 2)
3957 process_subcelldata(connectivity.entity_to_entities(1, 0),
3958 tria.faces->lines,
3959 subcelldata.boundary_lines,
3960 vertices);
3961
3962 // SubCellData: quad
3963 if (dim == 3)
3964 process_subcelldata(connectivity.entity_to_entities(2, 0),
3965 tria.faces->quads,
3966 subcelldata.boundary_quads,
3967 vertices);
3968 }
3969
3970
3971 template <int structdim, int spacedim>
3972 static void
3974 const ArrayOfArrays &crs,
3975 TriaObjects &obj,
3976 const std::vector<CellData<structdim>> &boundary_objects_in,
3977 const std::vector<Point<spacedim>> &vertex_locations)
3978 {
3979 AssertDimension(obj.structdim, structdim);
3980
3981 if (boundary_objects_in.empty())
3982 return; // empty subcelldata -> nothing to do
3983
3984 // pre-sort subcelldata
3985 auto boundary_objects = boundary_objects_in;
3986
3987 // ... sort vertices
3988 for (auto &boundary_object : boundary_objects)
3989 std::sort(boundary_object.vertices.begin(),
3990 boundary_object.vertices.end());
3991
3992 // ... sort cells
3993 std::sort(boundary_objects.begin(),
3994 boundary_objects.end(),
3995 [](const auto &a, const auto &b) {
3996 return a.vertices < b.vertices;
3997 });
3998
3999 [[maybe_unused]] unsigned int counter = 0;
4000
4002 ReferenceCells::max_n_vertices<structdim>()>
4003 key;
4004
4005 for (unsigned int o = 0; o < obj.n_objects(); ++o)
4006 {
4007 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
4008 auto &manifold_id = obj.manifold_id[o];
4009
4010 // assert that object has not been visited yet and its value
4011 // has not been modified yet
4012 AssertThrow(boundary_id == 0 ||
4017
4018 // create key
4019 const ArrayView<const unsigned int> indices = crs[o];
4020 key.assign(indices.begin(), indices.end());
4021 std::sort(key.begin(), key.end());
4022
4023 // is subcelldata provided? -> binary search
4024 const auto subcell_object =
4025 std::lower_bound(boundary_objects.begin(),
4026 boundary_objects.end(),
4027 key,
4028 [&](const auto &cell, const auto &key) {
4029 return cell.vertices < key;
4030 });
4031
4032 // no subcelldata provided for this object
4033 if (subcell_object == boundary_objects.end() ||
4034 subcell_object->vertices != key)
4035 continue;
4036
4037 ++counter;
4038
4039 // set manifold id
4040 manifold_id = subcell_object->manifold_id;
4041
4042 // set boundary id
4043 if (subcell_object->boundary_id !=
4045 {
4048 ExcMessage(
4049 "The input arguments for creating a triangulation "
4050 "specified a boundary id for an internal face. This "
4051 "is not allowed."
4052 "\n\n"
4053 "The object in question has vertex indices " +
4054 [subcell_object]() {
4055 std::string s;
4056 for (const auto v : subcell_object->vertices)
4057 s += std::to_string(v) + ',';
4058 return s;
4059 }() +
4060 " which are located at coordinates " +
4061 [vertex_locations, subcell_object]() {
4062 std::ostringstream s;
4063 for (unsigned int i = 0;
4064 i < subcell_object->vertices.size();
4065 ++i)
4066 s << '('
4067 << vertex_locations[subcell_object->vertices[i]]
4068 << (i != subcell_object->vertices.size() - 1 ? "), " :
4069 ")");
4070 return s.str();
4071 }() +
4072 "."));
4073 boundary_id = subcell_object->boundary_id;
4074 }
4075 }
4076
4077 // make sure that all subcelldata entries have been processed
4078 // TODO: this is not guaranteed, why?
4079 // AssertDimension(counter, boundary_objects_in.size());
4080 }
4081
4082
4083
4099 template <int spacedim>
4100 static void
4103 std::vector<unsigned int> &,
4104 std::vector<unsigned int> &)
4105 {
4106 const unsigned int dim = 1;
4107
4108 // first we need to reset the
4109 // neighbor pointers of the
4110 // neighbors of this cell's
4111 // children to this cell. This is
4112 // different for one dimension,
4113 // since there neighbors can have a
4114 // refinement level differing from
4115 // that of this cell's children by
4116 // more than one level.
4117
4118 Assert(!cell->child(0)->has_children() &&
4119 !cell->child(1)->has_children(),
4121
4122 // first do it for the cells to the
4123 // left
4124 if (cell->neighbor(0).state() == IteratorState::valid)
4125 if (cell->neighbor(0)->has_children())
4126 {
4128 cell->neighbor(0);
4129 Assert(neighbor->level() == cell->level(), ExcInternalError());
4130
4131 // right child
4132 neighbor = neighbor->child(1);
4133 while (true)
4134 {
4135 Assert(neighbor->neighbor(1) == cell->child(0),
4137 neighbor->set_neighbor(1, cell);
4138
4139 // move on to further
4140 // children on the
4141 // boundary between this
4142 // cell and its neighbor
4143 if (neighbor->has_children())
4144 neighbor = neighbor->child(1);
4145 else
4146 break;
4147 }
4148 }
4149
4150 // now do it for the cells to the
4151 // left
4152 if (cell->neighbor(1).state() == IteratorState::valid)
4153 if (cell->neighbor(1)->has_children())
4154 {
4156 cell->neighbor(1);
4157 Assert(neighbor->level() == cell->level(), ExcInternalError());
4158
4159 // left child
4160 neighbor = neighbor->child(0);
4161 while (true)
4162 {
4163 Assert(neighbor->neighbor(0) == cell->child(1),
4165 neighbor->set_neighbor(0, cell);
4166
4167 // move on to further
4168 // children on the
4169 // boundary between this
4170 // cell and its neighbor
4171 if (neighbor->has_children())
4172 neighbor = neighbor->child(0);
4173 else
4174 break;
4175 }
4176 }
4177
4178
4179 // delete the vertex which will not
4180 // be needed anymore. This vertex
4181 // is the second of the first child
4182 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
4183
4184 // invalidate children. clear user
4185 // pointers, to avoid that they may
4186 // appear at unwanted places later
4187 // on...
4188 for (unsigned int child = 0; child < cell->n_children(); ++child)
4189 {
4190 cell->child(child)->clear_user_data();
4191 cell->child(child)->clear_user_flag();
4192 cell->child(child)->clear_used_flag();
4193 }
4194
4195
4196 // delete pointer to children
4197 cell->clear_children();
4198 cell->clear_user_flag();
4199 }
4200
4201
4202
4203 template <int spacedim>
4204 static void
4207 std::vector<unsigned int> &line_cell_count,
4208 std::vector<unsigned int> &)
4209 {
4210 const unsigned int dim = 2;
4211 const RefinementCase<dim> ref_case = cell->refinement_case();
4212
4213 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
4215
4216 // vectors to hold all lines which
4217 // may be deleted
4218 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
4219 lines_to_delete(0);
4220
4221 lines_to_delete.reserve(4 * 2 + 4);
4222
4223 // now we decrease the counters for
4224 // lines contained in the child
4225 // cells
4226 for (unsigned int c = 0; c < cell->n_children(); ++c)
4227 {
4229 cell->child(c);
4230 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
4231 --line_cell_count[child->line_index(l)];
4232 }
4233
4234
4235 // delete the vertex which will not
4236 // be needed anymore. This vertex
4237 // is the second of the second line
4238 // of the first child, if the cell
4239 // is refined with cut_xy, else there
4240 // is no inner vertex.
4241 // additionally delete unneeded inner
4242 // lines
4243 if (ref_case == RefinementCase<dim>::cut_xy)
4244 {
4245 triangulation
4246 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
4247
4248 lines_to_delete.push_back(cell->child(0)->line(1));
4249 lines_to_delete.push_back(cell->child(0)->line(3));
4250 lines_to_delete.push_back(cell->child(3)->line(0));
4251 lines_to_delete.push_back(cell->child(3)->line(2));
4252 }
4253 else
4254 {
4255 unsigned int inner_face_no =
4256 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
4257
4258 // the inner line will not be
4259 // used any more
4260 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
4261 }
4262
4263 // invalidate children
4264 for (unsigned int child = 0; child < cell->n_children(); ++child)
4265 {
4266 cell->child(child)->clear_user_data();
4267 cell->child(child)->clear_user_flag();
4268 cell->child(child)->clear_used_flag();
4269 }
4270
4271
4272 // delete pointer to children
4273 cell->clear_children();
4274 cell->clear_refinement_case();
4275 cell->clear_user_flag();
4276
4277 // look at the refinement of outer
4278 // lines. if nobody needs those
4279 // anymore we can add them to the
4280 // list of lines to be deleted.
4281 for (unsigned int line_no = 0;
4282 line_no < GeometryInfo<dim>::lines_per_cell;
4283 ++line_no)
4284 {
4286 cell->line(line_no);
4287
4288 if (line->has_children())
4289 {
4290 // if one of the cell counters is
4291 // zero, the other has to be as well
4292
4293 Assert((line_cell_count[line->child_index(0)] == 0 &&
4294 line_cell_count[line->child_index(1)] == 0) ||
4295 (line_cell_count[line->child_index(0)] > 0 &&
4296 line_cell_count[line->child_index(1)] > 0),
4298
4299 if (line_cell_count[line->child_index(0)] == 0)
4300 {
4301 for (unsigned int c = 0; c < 2; ++c)
4302 Assert(!line->child(c)->has_children(),
4304
4305 // we may delete the line's
4306 // children and the middle vertex
4307 // as no cell references them
4308 // anymore
4309 triangulation
4310 .vertices_used[line->child(0)->vertex_index(1)] = false;
4311
4312 lines_to_delete.push_back(line->child(0));
4313 lines_to_delete.push_back(line->child(1));
4314
4315 line->clear_children();
4316 }
4317 }
4318 }
4319
4320 // finally, delete unneeded lines
4321
4322 // clear user pointers, to avoid that
4323 // they may appear at unwanted places
4324 // later on...
4325 // same for user flags, then finally
4326 // delete the lines
4327 typename std::vector<
4329 line = lines_to_delete.begin(),
4330 endline = lines_to_delete.end();
4331 for (; line != endline; ++line)
4332 {
4333 (*line)->clear_user_data();
4334 (*line)->clear_user_flag();
4335 (*line)->clear_used_flag();
4336 }
4337 }
4338
4339
4340
4341 template <int spacedim>
4342 static void
4345 std::vector<unsigned int> &line_cell_count,
4346 std::vector<unsigned int> &quad_cell_count)
4347 {
4348 const unsigned int dim = 3;
4349
4350 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
4352 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
4354
4355 // first of all, we store the RefineCase of
4356 // this cell
4357 const RefinementCase<dim> ref_case = cell->refinement_case();
4358 // vectors to hold all lines and quads which
4359 // may be deleted
4360 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
4361 lines_to_delete(0);
4362 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
4363 quads_to_delete(0);
4364
4365 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
4366 quads_to_delete.reserve(6 * 4 + 12);
4367
4368 // now we decrease the counters for lines and
4369 // quads contained in the child cells
4370 for (unsigned int c = 0; c < cell->n_children(); ++c)
4371 {
4373 cell->child(c);
4374 const auto line_indices = TriaAccessorImplementation::
4375 Implementation::get_line_indices_of_cell(*child);
4376 for (const unsigned int l : cell->line_indices())
4377 --line_cell_count[line_indices[l]];
4378 for (auto f : GeometryInfo<dim>::face_indices())
4379 --quad_cell_count[child->quad_index(f)];
4380 }
4381
4382 //-------------------------------------
4383 // delete interior quads and lines and the
4384 // interior vertex, depending on the
4385 // refinement case of the cell
4386 //
4387 // for append quads and lines: only append
4388 // them to the list of objects to be deleted
4389
4390 switch (ref_case)
4391 {
4393 quads_to_delete.push_back(cell->child(0)->face(1));
4394 break;
4396 quads_to_delete.push_back(cell->child(0)->face(3));
4397 break;
4399 quads_to_delete.push_back(cell->child(0)->face(5));
4400 break;
4402 quads_to_delete.push_back(cell->child(0)->face(1));
4403 quads_to_delete.push_back(cell->child(0)->face(3));
4404 quads_to_delete.push_back(cell->child(3)->face(0));
4405 quads_to_delete.push_back(cell->child(3)->face(2));
4406
4407 lines_to_delete.push_back(cell->child(0)->line(11));
4408 break;
4410 quads_to_delete.push_back(cell->child(0)->face(1));
4411 quads_to_delete.push_back(cell->child(0)->face(5));
4412 quads_to_delete.push_back(cell->child(3)->face(0));
4413 quads_to_delete.push_back(cell->child(3)->face(4));
4414
4415 lines_to_delete.push_back(cell->child(0)->line(5));
4416 break;
4418 quads_to_delete.push_back(cell->child(0)->face(3));
4419 quads_to_delete.push_back(cell->child(0)->face(5));
4420 quads_to_delete.push_back(cell->child(3)->face(2));
4421 quads_to_delete.push_back(cell->child(3)->face(4));
4422
4423 lines_to_delete.push_back(cell->child(0)->line(7));
4424 break;
4426 quads_to_delete.push_back(cell->child(0)->face(1));
4427 quads_to_delete.push_back(cell->child(2)->face(1));
4428 quads_to_delete.push_back(cell->child(4)->face(1));
4429 quads_to_delete.push_back(cell->child(6)->face(1));
4430
4431 quads_to_delete.push_back(cell->child(0)->face(3));
4432 quads_to_delete.push_back(cell->child(1)->face(3));
4433 quads_to_delete.push_back(cell->child(4)->face(3));
4434 quads_to_delete.push_back(cell->child(5)->face(3));
4435
4436 quads_to_delete.push_back(cell->child(0)->face(5));
4437 quads_to_delete.push_back(cell->child(1)->face(5));
4438 quads_to_delete.push_back(cell->child(2)->face(5));
4439 quads_to_delete.push_back(cell->child(3)->face(5));
4440
4441 lines_to_delete.push_back(cell->child(0)->line(5));
4442 lines_to_delete.push_back(cell->child(0)->line(7));
4443 lines_to_delete.push_back(cell->child(0)->line(11));
4444 lines_to_delete.push_back(cell->child(7)->line(0));
4445 lines_to_delete.push_back(cell->child(7)->line(2));
4446 lines_to_delete.push_back(cell->child(7)->line(8));
4447 // delete the vertex which will not
4448 // be needed anymore. This vertex
4449 // is the vertex at the heart of
4450 // this cell, which is the sixth of
4451 // the first child
4452 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4453 false;
4454 break;
4455 default:
4456 // only remaining case is
4457 // no_refinement, thus an error
4459 break;
4460 }
4461
4462
4463 // invalidate children
4464 for (unsigned int child = 0; child < cell->n_children(); ++child)
4465 {
4466 cell->child(child)->clear_user_data();
4467 cell->child(child)->clear_user_flag();
4468
4469 for (auto f : GeometryInfo<dim>::face_indices())
4470 // set flags denoting deviations from standard orientation of
4471 // faces back to initialization values
4472 cell->child(child)->set_combined_face_orientation(
4474
4475 cell->child(child)->clear_used_flag();
4476 }
4477
4478
4479 // delete pointer to children
4480 cell->clear_children();
4481 cell->clear_refinement_case();
4482 cell->clear_user_flag();
4483
4484 // so far we only looked at inner quads,
4485 // lines and vertices. Now we have to
4486 // consider outer ones as well. here, we have
4487 // to check, whether there are other cells
4488 // still needing these objects. otherwise we
4489 // can delete them. first for quads (and
4490 // their inner lines).
4491
4492 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4493 {
4495 cell->face(quad_no);
4496
4497 Assert(
4498 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4499 quad->has_children()) ||
4500 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4503
4504 switch (quad->refinement_case())
4505 {
4506 case RefinementCase<dim - 1>::no_refinement:
4507 // nothing to do as the quad
4508 // is not refined
4509 break;
4510 case RefinementCase<dim - 1>::cut_x:
4511 case RefinementCase<dim - 1>::cut_y:
4512 {
4513 // if one of the cell counters is
4514 // zero, the other has to be as
4515 // well
4516 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4517 quad_cell_count[quad->child_index(1)] == 0) ||
4518 (quad_cell_count[quad->child_index(0)] > 0 &&
4519 quad_cell_count[quad->child_index(1)] > 0),
4521 // it might be, that the quad is
4522 // refined twice anisotropically,
4523 // first check, whether we may
4524 // delete possible grand_children
4525 unsigned int deleted_grandchildren = 0;
4526 unsigned int number_of_child_refinements = 0;
4527
4528 for (unsigned int c = 0; c < 2; ++c)
4529 if (quad->child(c)->has_children())
4530 {
4531 ++number_of_child_refinements;
4532 // if one of the cell counters is
4533 // zero, the other has to be as
4534 // well
4535 Assert(
4536 (quad_cell_count[quad->child(c)->child_index(0)] ==
4537 0 &&
4538 quad_cell_count[quad->child(c)->child_index(1)] ==
4539 0) ||
4540 (quad_cell_count[quad->child(c)->child_index(0)] >
4541 0 &&
4542 quad_cell_count[quad->child(c)->child_index(1)] >
4543 0),
4545 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4546 0)
4547 {
4548 // Assert, that the two
4549 // anisotropic
4550 // refinements add up to
4551 // isotropic refinement
4552 Assert(quad->refinement_case() +
4553 quad->child(c)->refinement_case() ==
4556 // we may delete the
4557 // quad's children and
4558 // the inner line as no
4559 // cell references them
4560 // anymore
4561 quads_to_delete.push_back(
4562 quad->child(c)->child(0));
4563 quads_to_delete.push_back(
4564 quad->child(c)->child(1));
4565 if (quad->child(c)->refinement_case() ==
4567 lines_to_delete.push_back(
4568 quad->child(c)->child(0)->line(1));
4569 else
4570 lines_to_delete.push_back(
4571 quad->child(c)->child(0)->line(3));
4572 quad->child(c)->clear_children();
4573 quad->child(c)->clear_refinement_case();
4574 ++deleted_grandchildren;
4575 }
4576 }
4577 // if no grandchildren are left, we
4578 // may as well delete the
4579 // refinement of the inner line
4580 // between our children and the
4581 // corresponding vertex
4582 if (number_of_child_refinements > 0 &&
4583 deleted_grandchildren == number_of_child_refinements)
4584 {
4586 middle_line;
4587 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4588 middle_line = quad->child(0)->line(1);
4589 else
4590 middle_line = quad->child(0)->line(3);
4591
4592 lines_to_delete.push_back(middle_line->child(0));
4593 lines_to_delete.push_back(middle_line->child(1));
4594 triangulation
4595 .vertices_used[middle_vertex_index<dim, spacedim>(
4596 middle_line)] = false;
4597 middle_line->clear_children();
4598 }
4599
4600 // now consider the direct children
4601 // of the given quad
4602 if (quad_cell_count[quad->child_index(0)] == 0)
4603 {
4604 // we may delete the quad's
4605 // children and the inner line
4606 // as no cell references them
4607 // anymore
4608 quads_to_delete.push_back(quad->child(0));
4609 quads_to_delete.push_back(quad->child(1));
4610 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4611 lines_to_delete.push_back(quad->child(0)->line(1));
4612 else
4613 lines_to_delete.push_back(quad->child(0)->line(3));
4614
4615 // if the counters just dropped
4616 // to zero, otherwise the
4617 // children would have been
4618 // deleted earlier, then this
4619 // cell's children must have
4620 // contained the anisotropic
4621 // quad children. thus, if
4622 // those have again anisotropic
4623 // children, which are in
4624 // effect isotropic children of
4625 // the original quad, those are
4626 // still needed by a
4627 // neighboring cell and we
4628 // cannot delete them. instead,
4629 // we have to reset this quad's
4630 // refine case to isotropic and
4631 // set the children
4632 // accordingly.
4633 if (quad->child(0)->has_children())
4634 if (quad->refinement_case() ==
4636 {
4637 // now evereything is
4638 // quite complicated. we
4639 // have the children
4640 // numbered according to
4641 //
4642 // *---*---*
4643 // |n+1|m+1|
4644 // *---*---*
4645 // | n | m |
4646 // *---*---*
4647 //
4648 // from the original
4649 // anisotropic
4650 // refinement. we have to
4651 // reorder them as
4652 //
4653 // *---*---*
4654 // | m |m+1|
4655 // *---*---*
4656 // | n |n+1|
4657 // *---*---*
4658 //
4659 // for isotropic refinement.
4660 //
4661 // this is a bit ugly, of
4662 // course: loop over all
4663 // cells on all levels
4664 // and look for faces n+1
4665 // (switch_1) and m
4666 // (switch_2).
4667 const typename Triangulation<dim, spacedim>::
4668 quad_iterator switch_1 =
4669 quad->child(0)->child(1),
4670 switch_2 =
4671 quad->child(1)->child(0);
4672
4673 Assert(!switch_1->has_children(),
4675 Assert(!switch_2->has_children(),
4677
4678 const int switch_1_index = switch_1->index();
4679 const int switch_2_index = switch_2->index();
4680 for (unsigned int l = 0;
4681 l < triangulation.levels.size();
4682 ++l)
4683 for (unsigned int h = 0;
4684 h <
4685 triangulation.levels[l]->cells.n_objects();
4686 ++h)
4687 for (const unsigned int q :
4689 {
4690 const int index =
4691 triangulation.levels[l]
4692 ->cells.get_bounding_object_indices(
4693 h)[q];
4694 if (index == switch_1_index)
4695 triangulation.levels[l]
4696 ->cells.get_bounding_object_indices(
4697 h)[q] = switch_2_index;
4698 else if (index == switch_2_index)
4699 triangulation.levels[l]
4700 ->cells.get_bounding_object_indices(
4701 h)[q] = switch_1_index;
4702 }
4703 // now we have to copy
4704 // all information of the
4705 // two quads
4706 int switch_1_lines[4], switch_2_lines[4];
4707 for (int i = 0; i < 4; ++i)
4708 {
4709 switch_1_lines[i] =
4710 switch_1->line(i)->index();
4711 switch_2_lines[i] =
4712 switch_2->line(i)->index();
4713 }
4715 switch_1_line_orientations[4] = {
4716 switch_1->line_orientation(0),
4717 switch_1->line_orientation(1),
4718 switch_1->line_orientation(2),
4719 switch_1->line_orientation(3)};
4720 const types::boundary_id switch_1_boundary_id =
4721 switch_1->boundary_id();
4722 const unsigned int switch_1_user_index =
4723 switch_1->user_index();
4724 const bool switch_1_user_flag =
4725 switch_1->user_flag_set();
4726
4727 switch_1->set_bounding_object_indices(
4728 {switch_2_lines[0],
4729 switch_2_lines[1],
4730 switch_2_lines[2],
4731 switch_2_lines[3]});
4732 switch_1->set_line_orientation(
4733 0, switch_2->line_orientation(0));
4734 switch_1->set_line_orientation(
4735 1, switch_2->line_orientation(1));
4736 switch_1->set_line_orientation(
4737 2, switch_2->line_orientation(2));
4738 switch_1->set_line_orientation(
4739 3, switch_2->line_orientation(3));
4740 switch_1->set_boundary_id_internal(
4741 switch_2->boundary_id());
4742 switch_1->set_manifold_id(
4743 switch_2->manifold_id());
4744 switch_1->set_user_index(switch_2->user_index());
4745 if (switch_2->user_flag_set())
4746 switch_1->set_user_flag();
4747 else
4748 switch_1->clear_user_flag();
4749
4750 switch_2->set_bounding_object_indices(
4751 {switch_1_lines[0],
4752 switch_1_lines[1],
4753 switch_1_lines[2],
4754 switch_1_lines[3]});
4755 switch_2->set_line_orientation(
4756 0, switch_1_line_orientations[0]);
4757 switch_2->set_line_orientation(
4758 1, switch_1_line_orientations[1]);
4759 switch_2->set_line_orientation(
4760 2, switch_1_line_orientations[2]);
4761 switch_2->set_line_orientation(
4762 3, switch_1_line_orientations[3]);
4763 switch_2->set_boundary_id_internal(
4764 switch_1_boundary_id);
4765 switch_2->set_manifold_id(
4766 switch_1->manifold_id());
4767 switch_2->set_user_index(switch_1_user_index);
4768 if (switch_1_user_flag)
4769 switch_2->set_user_flag();
4770 else
4771 switch_2->clear_user_flag();
4772
4773 const unsigned int child_0 =
4774 quad->child(0)->child_index(0);
4775 const unsigned int child_2 =
4776 quad->child(1)->child_index(0);
4777 quad->clear_children();
4778 quad->clear_refinement_case();
4779 quad->set_refinement_case(
4781 quad->set_children(0, child_0);
4782 quad->set_children(2, child_2);
4783 std::swap(quad_cell_count[child_0 + 1],
4784 quad_cell_count[child_2]);
4785 }
4786 else
4787 {
4788 // the face was refined
4789 // with cut_y, thus the
4790 // children are already
4791 // in correct order. we
4792 // only have to set them
4793 // correctly, deleting
4794 // the indirection of two
4795 // anisotropic refinement
4796 // and going directly
4797 // from the quad to
4798 // isotropic children
4799 const unsigned int child_0 =
4800 quad->child(0)->child_index(0);
4801 const unsigned int child_2 =
4802 quad->child(1)->child_index(0);
4803 quad->clear_children();
4804 quad->clear_refinement_case();
4805 quad->set_refinement_case(
4807 quad->set_children(0, child_0);
4808 quad->set_children(2, child_2);
4809 }
4810 else
4811 {
4812 quad->clear_children();
4813 quad->clear_refinement_case();
4814 }
4815 }
4816 break;
4817 }
4818 case RefinementCase<dim - 1>::cut_xy:
4819 {
4820 // if one of the cell counters is
4821 // zero, the others have to be as
4822 // well
4823
4824 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4825 quad_cell_count[quad->child_index(1)] == 0 &&
4826 quad_cell_count[quad->child_index(2)] == 0 &&
4827 quad_cell_count[quad->child_index(3)] == 0) ||
4828 (quad_cell_count[quad->child_index(0)] > 0 &&
4829 quad_cell_count[quad->child_index(1)] > 0 &&
4830 quad_cell_count[quad->child_index(2)] > 0 &&
4831 quad_cell_count[quad->child_index(3)] > 0),
4833
4834 if (quad_cell_count[quad->child_index(0)] == 0)
4835 {
4836 // we may delete the quad's
4837 // children, the inner lines
4838 // and the middle vertex as no
4839 // cell references them anymore
4840 lines_to_delete.push_back(quad->child(0)->line(1));
4841 lines_to_delete.push_back(quad->child(3)->line(0));
4842 lines_to_delete.push_back(quad->child(0)->line(3));
4843 lines_to_delete.push_back(quad->child(3)->line(2));
4844
4845 for (unsigned int child = 0; child < quad->n_children();
4846 ++child)
4847 quads_to_delete.push_back(quad->child(child));
4848
4849 triangulation
4850 .vertices_used[quad->child(0)->vertex_index(3)] =
4851 false;
4852
4853 quad->clear_children();
4854 quad->clear_refinement_case();
4855 }
4856 }
4857 break;
4858
4859 default:
4861 break;
4862 }
4863 }
4864
4865 // now we repeat a similar procedure
4866 // for the outer lines of this cell.
4867
4868 // if in debug mode: check that each
4869 // of the lines for which we consider
4870 // deleting the children in fact has
4871 // children (the bits/coarsening_3d
4872 // test tripped over this initially)
4873 for (unsigned int line_no = 0;
4874 line_no < GeometryInfo<dim>::lines_per_cell;
4875 ++line_no)
4876 {
4878 cell->line(line_no);
4879
4880 Assert(
4881 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4882 line->has_children()) ||
4883 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4886
4887 if (line->has_children())
4888 {
4889 // if one of the cell counters is
4890 // zero, the other has to be as well
4891
4892 Assert((line_cell_count[line->child_index(0)] == 0 &&
4893 line_cell_count[line->child_index(1)] == 0) ||
4894 (line_cell_count[line->child_index(0)] > 0 &&
4895 line_cell_count[line->child_index(1)] > 0),
4897
4898 if (line_cell_count[line->child_index(0)] == 0)
4899 {
4900 for (unsigned int c = 0; c < 2; ++c)
4901 Assert(!line->child(c)->has_children(),
4903
4904 // we may delete the line's
4905 // children and the middle vertex
4906 // as no cell references them
4907 // anymore
4908 triangulation
4909 .vertices_used[line->child(0)->vertex_index(1)] = false;
4910
4911 lines_to_delete.push_back(line->child(0));
4912 lines_to_delete.push_back(line->child(1));
4913
4914 line->clear_children();
4915 }
4916 }
4917 }
4918
4919 // finally, delete unneeded quads and lines
4920
4921 // clear user pointers, to avoid that
4922 // they may appear at unwanted places
4923 // later on...
4924 // same for user flags, then finally
4925 // delete the quads and lines
4926 typename std::vector<
4928 line = lines_to_delete.begin(),
4929 endline = lines_to_delete.end();
4930 for (; line != endline; ++line)
4931 {
4932 (*line)->clear_user_data();
4933 (*line)->clear_user_flag();
4934 (*line)->clear_used_flag();
4935 }
4936
4937 typename std::vector<
4939 quad = quads_to_delete.begin(),
4940 endquad = quads_to_delete.end();
4941 for (; quad != endquad; ++quad)
4942 {
4943 (*quad)->clear_user_data();
4944 (*quad)->clear_children();
4945 (*quad)->clear_refinement_case();
4946 (*quad)->clear_user_flag();
4947 (*quad)->clear_used_flag();
4948 }
4949 }
4950
4951
4969 template <int spacedim>
4970 static void
4972 Triangulation<2, spacedim> &triangulation,
4973 unsigned int &next_unused_vertex,
4975 &next_unused_line,
4977 &next_unused_cell,
4978 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4979 {
4980 const unsigned int dim = 2;
4981 // clear refinement flag
4982 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4983 cell->clear_refine_flag();
4984
4985 /* For the refinement process: since we go the levels up from the
4986 lowest, there are (unlike above) only two possibilities: a neighbor
4987 cell is on the same level or one level up (in both cases, it may or
4988 may not be refined later on, but we don't care here).
4989
4990 First:
4991 Set up an array of the 3x3 vertices, which are distributed on the
4992 cell (the array consists of indices into the @p{vertices} std::vector
4993
4994 2--7--3
4995 | | |
4996 4--8--5
4997 | | |
4998 0--6--1
4999
5000 note: in case of cut_x or cut_y not all these vertices are needed for
5001 the new cells
5002
5003 Second:
5004 Set up an array of the new lines (the array consists of iterator
5005 pointers into the lines arrays)
5006
5007 .-6-.-7-. The directions are: .->-.->-.
5008 1 9 3 ^ ^ ^
5009 .-10.11-. .->-.->-.
5010 0 8 2 ^ ^ ^
5011 .-4-.-5-. .->-.->-.
5012
5013 cut_x:
5014 .-4-.-5-.
5015 | | |
5016 0 6 1
5017 | | |
5018 .-2-.-3-.
5019
5020 cut_y:
5021 .---5---.
5022 1 3
5023 .---6---.
5024 0 2
5025 .---4---.
5026
5027
5028 Third:
5029 Set up an array of neighbors:
5030
5031 6 7
5032 .--.--.
5033 1| | |3
5034 .--.--.
5035 0| | |2
5036 .--.--.
5037 4 5
5038
5039 We need this array for two reasons: first to get the lines which will
5040 bound the four subcells (if the neighboring cell is refined, these
5041 lines already exist), and second to update neighborship information.
5042 Since if a neighbor is not refined, its neighborship record only
5043 points to the present, unrefined, cell rather than the children we
5044 are presently creating, we only need the neighborship information
5045 if the neighbor cells are refined. In all other cases, we store
5046 the unrefined neighbor address
5047
5048 We also need for every neighbor (if refined) which number among its
5049 neighbors the present (unrefined) cell has, since that number is to
5050 be replaced and because that also is the number of the subline which
5051 will be the interface between that neighbor and the to be created
5052 cell. We will store this number (between 0 and 3) in the field
5053 @p{neighbors_neighbor}.
5054
5055 It would be sufficient to use the children of the common line to the
5056 neighbor, if we only wanted to get the new sublines and the new
5057 vertex, but because we need to update the neighborship information of
5058 the two refined subcells of the neighbor, we need to search these
5059 anyway.
5060
5061 Convention:
5062 The created children are numbered like this:
5063
5064 .--.--.
5065 |2 . 3|
5066 .--.--.
5067 |0 | 1|
5068 .--.--.
5069 */
5070 // collect the indices of the eight surrounding vertices
5071 // 2--7--3
5072 // | | |
5073 // 4--8--5
5074 // | | |
5075 // 0--6--1
5076 int new_vertices[9];
5077 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
5078 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5079 for (unsigned int line_no = 0; line_no < 4; ++line_no)
5080 if (cell->line(line_no)->has_children())
5081 new_vertices[4 + line_no] =
5082 cell->line(line_no)->child(0)->vertex_index(1);
5083
5084 if (ref_case == RefinementCase<dim>::cut_xy)
5085 {
5086 // find the next
5087 // unused vertex and
5088 // allocate it for
5089 // the new vertex we
5090 // need here
5091 while (triangulation.vertices_used[next_unused_vertex] == true)
5092 ++next_unused_vertex;
5093 Assert(next_unused_vertex < triangulation.vertices.size(),
5094 ExcMessage(
5095 "Internal error: During refinement, the triangulation "
5096 "wants to access an element of the 'vertices' array "
5097 "but it turns out that the array is not large enough."));
5098 triangulation.vertices_used[next_unused_vertex] = true;
5099
5100 new_vertices[8] = next_unused_vertex;
5101
5102 // determine middle vertex by transfinite interpolation to be
5103 // consistent with what happens to quads in a
5104 // Triangulation<3,3> when they are refined
5105 triangulation.vertices[next_unused_vertex] =
5106 cell->center(true, true);
5107 }
5108
5109
5110 // Now the lines:
5112 unsigned int lmin = 8;
5113 unsigned int lmax = 12;
5114 if (ref_case != RefinementCase<dim>::cut_xy)
5115 {
5116 lmin = 6;
5117 lmax = 7;
5118 }
5119
5120 for (unsigned int l = lmin; l < lmax; ++l)
5121 {
5122 while (next_unused_line->used() == true)
5123 ++next_unused_line;
5124 new_lines[l] = next_unused_line;
5125 ++next_unused_line;
5126
5127 AssertIsNotUsed(new_lines[l]);
5128 }
5129
5130 if (ref_case == RefinementCase<dim>::cut_xy)
5131 {
5132 // .-6-.-7-.
5133 // 1 9 3
5134 // .-10.11-.
5135 // 0 8 2
5136 // .-4-.-5-.
5137
5138 // lines 0-7 already exist, create only the four interior
5139 // lines 8-11
5140 unsigned int l = 0;
5141 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
5142 for (unsigned int c = 0; c < 2; ++c, ++l)
5143 new_lines[l] = cell->line(face_no)->child(c);
5144 Assert(l == 8, ExcInternalError());
5145
5146 new_lines[8]->set_bounding_object_indices(
5147 {new_vertices[6], new_vertices[8]});
5148 new_lines[9]->set_bounding_object_indices(
5149 {new_vertices[8], new_vertices[7]});
5150 new_lines[10]->set_bounding_object_indices(
5151 {new_vertices[4], new_vertices[8]});
5152 new_lines[11]->set_bounding_object_indices(
5153 {new_vertices[8], new_vertices[5]});
5154 }
5155 else if (ref_case == RefinementCase<dim>::cut_x)
5156 {
5157 // .-4-.-5-.
5158 // | | |
5159 // 0 6 1
5160 // | | |
5161 // .-2-.-3-.
5162 new_lines[0] = cell->line(0);
5163 new_lines[1] = cell->line(1);
5164 new_lines[2] = cell->line(2)->child(0);
5165 new_lines[3] = cell->line(2)->child(1);
5166 new_lines[4] = cell->line(3)->child(0);
5167 new_lines[5] = cell->line(3)->child(1);
5168 new_lines[6]->set_bounding_object_indices(
5169 {new_vertices[6], new_vertices[7]});
5170 }
5171 else
5172 {
5174 // .---5---.
5175 // 1 3
5176 // .---6---.
5177 // 0 2
5178 // .---4---.
5179 new_lines[0] = cell->line(0)->child(0);
5180 new_lines[1] = cell->line(0)->child(1);
5181 new_lines[2] = cell->line(1)->child(0);
5182 new_lines[3] = cell->line(1)->child(1);
5183 new_lines[4] = cell->line(2);
5184 new_lines[5] = cell->line(3);
5185 new_lines[6]->set_bounding_object_indices(
5186 {new_vertices[4], new_vertices[5]});
5187 }
5188
5189 for (unsigned int l = lmin; l < lmax; ++l)
5190 {
5191 new_lines[l]->set_used_flag();
5192 new_lines[l]->clear_user_flag();
5193 new_lines[l]->clear_user_data();
5194 new_lines[l]->clear_children();
5195 // interior line
5196 new_lines[l]->set_boundary_id_internal(
5198 new_lines[l]->set_manifold_id(cell->manifold_id());
5199 }
5200
5201 // Now add the four (two)
5202 // new cells!
5204 subcells[ReferenceCells::max_n_children<dim>()];
5205 while (next_unused_cell->used() == true)
5206 ++next_unused_cell;
5207
5208 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
5209 for (unsigned int i = 0; i < n_children; ++i)
5210 {
5211 AssertIsNotUsed(next_unused_cell);
5212 subcells[i] = next_unused_cell;
5213 ++next_unused_cell;
5214 if (i % 2 == 1 && i < n_children - 1)
5215 while (next_unused_cell->used() == true)
5216 ++next_unused_cell;
5217 }
5218
5219 if (ref_case == RefinementCase<dim>::cut_xy)
5220 {
5221 // children:
5222 // .--.--.
5223 // |2 . 3|
5224 // .--.--.
5225 // |0 | 1|
5226 // .--.--.
5227 // lines:
5228 // .-6-.-7-.
5229 // 1 9 3
5230 // .-10.11-.
5231 // 0 8 2
5232 // .-4-.-5-.
5233 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5234 new_lines[8]->index(),
5235 new_lines[4]->index(),
5236 new_lines[10]->index()});
5237 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
5238 new_lines[2]->index(),
5239 new_lines[5]->index(),
5240 new_lines[11]->index()});
5241 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
5242 new_lines[9]->index(),
5243 new_lines[10]->index(),
5244 new_lines[6]->index()});
5245 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
5246 new_lines[3]->index(),
5247 new_lines[11]->index(),
5248 new_lines[7]->index()});
5249 }
5250 else if (ref_case == RefinementCase<dim>::cut_x)
5251 {
5252 // children:
5253 // .--.--.
5254 // | . |
5255 // .0 . 1.
5256 // | | |
5257 // .--.--.
5258 // lines:
5259 // .-4-.-5-.
5260 // | | |
5261 // 0 6 1
5262 // | | |
5263 // .-2-.-3-.
5264 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5265 new_lines[6]->index(),
5266 new_lines[2]->index(),
5267 new_lines[4]->index()});
5268 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
5269 new_lines[1]->index(),
5270 new_lines[3]->index(),
5271 new_lines[5]->index()});
5272 }
5273 else
5274 {
5276 // children:
5277 // .-----.
5278 // | 1 |
5279 // .-----.
5280 // | 0 |
5281 // .-----.
5282 // lines:
5283 // .---5---.
5284 // 1 3
5285 // .---6---.
5286 // 0 2
5287 // .---4---.
5288 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5289 new_lines[2]->index(),
5290 new_lines[4]->index(),
5291 new_lines[6]->index()});
5292 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
5293 new_lines[3]->index(),
5294 new_lines[6]->index(),
5295 new_lines[5]->index()});
5296 }
5297
5298 types::subdomain_id subdomainid = cell->subdomain_id();
5299
5300 for (unsigned int i = 0; i < n_children; ++i)
5301 {
5302 subcells[i]->set_used_flag();
5303 subcells[i]->clear_refine_flag();
5304 subcells[i]->clear_user_flag();
5305 subcells[i]->clear_user_data();
5306 subcells[i]->clear_children();
5307 // inherit material properties
5308 subcells[i]->set_material_id(cell->material_id());
5309 subcells[i]->set_manifold_id(cell->manifold_id());
5310 subcells[i]->set_subdomain_id(subdomainid);
5311
5312 // We only store the parent for every second cell. That's because
5313 // cells are created during refinement in multiples of two, and so
5314 // two successive cells always share the same parent. As a
5315 // consequence, we can save a bit of work by skipping setting parent
5316 // indices for the odd children.
5317 if (i % 2 == 0)
5318 subcells[i]->set_parent(cell->index());
5319 }
5320
5321
5322
5323 // set child index for even children i=0,2 (0)
5324 for (unsigned int i = 0; i < n_children / 2; ++i)
5325 cell->set_children(2 * i, subcells[2 * i]->index());
5326 // set the refine case
5327 cell->set_refinement_case(ref_case);
5328
5329 // note that the
5330 // refinement flag was
5331 // already cleared at the
5332 // beginning of this function
5333
5334 if (dim == spacedim - 1)
5335 for (unsigned int c = 0; c < n_children; ++c)
5336 cell->child(c)->set_direction_flag(cell->direction_flag());
5337 }
5338
5339
5340
5341 template <int spacedim>
5344 Triangulation<1, spacedim> & /*triangulation*/,
5345 const bool /*check_for_distorted_cells*/)
5346 {
5348 }
5349
5350
5351
5352 template <int spacedim>
5355 const bool check_for_distorted_cells)
5356 {
5357 constexpr int dim = 2;
5358
5359 // Check whether a new level is needed. We have to check for
5360 // this on the highest level only
5361 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5362 triangulation.levels.size() - 1))
5363 if (cell->refine_flag_set())
5364 {
5365 triangulation.levels.push_back(
5366 std::make_unique<internal::TriangulationImplementation::
5368 triangulation.strides.max_children_per_cell,
5369 triangulation.strides.max_faces_per_cell,
5370 triangulation.strides.max_vertices_per_cell));
5371 break;
5372 }
5373
5375 triangulation.begin_line();
5376 line != triangulation.end_line();
5377 ++line)
5378 {
5379 line->clear_user_flag();
5380 line->clear_user_data();
5381 }
5382
5383 unsigned int n_single_lines = 0;
5384 unsigned int n_lines_in_pairs = 0;
5385 unsigned int needed_vertices = 0;
5386
5387 const bool orientation_needed =
5388 !triangulation.all_reference_cells_are_hyper_cube();
5389
5390 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
5391 --level_no)
5392 {
5393 // count number of flagged cells on this level and compute
5394 // how many new vertices and new lines will be needed
5395 std::size_t needed_cells = 0;
5396
5397 for (const auto &cell :
5398 triangulation.active_cell_iterators_on_level(level_no))
5399 if (cell->refine_flag_set())
5400 {
5401 if (cell->reference_cell() == ReferenceCells::Triangle)
5402 {
5403 needed_cells += 4;
5404 needed_vertices += 0;
5405 n_single_lines += 3;
5406 }
5407 else if (cell->reference_cell() ==
5409 {
5410 needed_cells += 4;
5411 needed_vertices += 1;
5412 n_single_lines += 4;
5413 }
5414 else
5415 {
5417 }
5418
5419 for (const auto line_no : cell->face_indices())
5420 {
5421 auto line = cell->line(line_no);
5422 if (line->has_children() == false)
5423 line->set_user_flag();
5424 }
5425 }
5426
5427 // count number of used cells on the next higher level
5428 auto &next_level = *triangulation.levels[level_no + 1];
5429 const auto used_cells = std::count(next_level.cells.used.begin(),
5430 next_level.cells.used.end(),
5431 true);
5432
5433 if (used_cells + needed_cells > next_level.size())
5434 next_level.allocate_end((used_cells + needed_cells) -
5435 next_level.size(),
5436 orientation_needed,
5437 // We are in 2d so there are no tetrahedra
5438 false);
5439
5440 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
5441 next_level.cells.allocate_end(needed_cells, 0);
5442 }
5443
5444 for (auto line = triangulation.begin_line();
5445 line != triangulation.end_line();
5446 ++line)
5447 if (line->user_flag_set())
5448 {
5449 Assert(line->has_children() == false, ExcInternalError());
5450 n_lines_in_pairs += 2;
5451 needed_vertices += 1;
5452 }
5453
5454 triangulation.faces->lines.allocate_end(n_lines_in_pairs, 0);
5455
5456 needed_vertices += std::count(triangulation.vertices_used.begin(),
5457 triangulation.vertices_used.end(),
5458 true);
5459
5460 if (needed_vertices > triangulation.vertices.size())
5461 {
5462 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5463 triangulation.vertices_used.resize(needed_vertices, false);
5464 }
5465
5466 unsigned int next_unused_vertex = 0;
5467
5468 {
5470 line = triangulation.begin_active_line(),
5471 endl = triangulation.end_line();
5473 next_unused_line = triangulation.begin_raw_line();
5474
5475 for (; line != endl; ++line)
5476 if (line->user_flag_set())
5477 {
5478 // This line needs to be refined. Find the next unused vertex
5479 // and set it appropriately
5480 while (triangulation.vertices_used[next_unused_vertex] == true)
5481 ++next_unused_vertex;
5482 Assert(next_unused_vertex < triangulation.vertices.size(),
5483 ExcMessage(
5484 "Internal error: During refinement, the triangulation "
5485 "wants to access an element of the 'vertices' array "
5486 "but it turns out that the array is not large "
5487 "enough."));
5488 triangulation.vertices_used[next_unused_vertex] = true;
5489
5490 triangulation.vertices[next_unused_vertex] = line->center(true);
5491
5492 bool pair_found = false;
5493 for (; next_unused_line != endl; ++next_unused_line)
5494 if (!next_unused_line->used() &&
5495 !(++next_unused_line)->used())
5496 {
5497 --next_unused_line;
5498 pair_found = true;
5499 break;
5500 }
5501 Assert(pair_found, ExcInternalError());
5502
5503 line->set_children(0, next_unused_line->index());
5504
5506 children[2] = {next_unused_line, ++next_unused_line};
5507
5508 AssertIsNotUsed(children[0]);
5509 AssertIsNotUsed(children[1]);
5510
5511 children[0]->set_bounding_object_indices(
5512 {line->vertex_index(0), next_unused_vertex});
5513 children[1]->set_bounding_object_indices(
5514 {next_unused_vertex, line->vertex_index(1)});
5515
5516 for (auto &child : children)
5517 {
5518 child->set_used_flag();
5519 child->clear_children();
5520 child->clear_user_data();
5521 child->clear_user_flag();
5522 child->set_boundary_id_internal(line->boundary_id());
5523 child->set_manifold_id(line->manifold_id());
5524 // Line orientation is relative to the cell it is on so
5525 // those cannot be set at this point.
5526 }
5527
5528 line->clear_user_flag();
5529 }
5530 }
5531
5532 triangulation.faces->lines.allocate_end(0, n_single_lines);
5533
5534
5536 cells_with_distorted_children;
5537
5539 next_unused_line = triangulation.begin_raw_line();
5540
5541 const auto create_children = [](auto &triangulation,
5542 unsigned int &next_unused_vertex,
5543 auto &next_unused_line,
5544 auto &next_unused_cell,
5545 const auto &cell) {
5546 const auto ref_case = cell->refine_flag_set();
5547 cell->clear_refine_flag();
5548
5549 unsigned int n_new_vertices = 0;
5550 if (cell->reference_cell() == ReferenceCells::Triangle)
5551 n_new_vertices = 6;
5552 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5553 n_new_vertices = 9;
5554 else
5556
5558 n_new_vertices, numbers::invalid_unsigned_int);
5559 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5560 ++vertex_no)
5561 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5562 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5563 if (cell->line(line_no)->has_children())
5564 new_vertices[cell->n_vertices() + line_no] =
5565 cell->line(line_no)->child(0)->vertex_index(1);
5566
5567 if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5568 {
5569 while (triangulation.vertices_used[next_unused_vertex] == true)
5570 ++next_unused_vertex;
5571 Assert(
5572 next_unused_vertex < triangulation.vertices.size(),
5573 ExcMessage(
5574 "Internal error: During refinement, the triangulation wants "
5575 "to access an element of the 'vertices' array but it turns "
5576 "out that the array is not large enough."));
5577 triangulation.vertices_used[next_unused_vertex] = true;
5578
5579 new_vertices[8] = next_unused_vertex;
5580
5581 triangulation.vertices[next_unused_vertex] =
5582 cell->center(true, true);
5583 }
5584
5585 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5586 12>
5587 new_lines;
5588 std::array<types::geometric_orientation, 12> inherited_orientations;
5589 inherited_orientations.fill(numbers::default_geometric_orientation);
5590 unsigned int lmin = 0;
5591 unsigned int lmax = 0;
5592
5593 if (cell->reference_cell() == ReferenceCells::Triangle)
5594 {
5595 lmin = 6;
5596 lmax = 9;
5597 // For triangles, the innermost faces are always reversed for the
5598 // first three children and are in the standard orientation for
5599 // the last one.
5600 std::fill(inherited_orientations.begin() + lmin,
5601 inherited_orientations.begin() + lmax,
5603 }
5604 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5605 {
5606 lmin = 8;
5607 lmax = 12;
5608 }
5609 else
5610 {
5612 }
5613
5614 for (unsigned int l = lmin; l < lmax; ++l)
5615 {
5616 while (next_unused_line->used() == true)
5617 ++next_unused_line;
5618 new_lines[l] = next_unused_line;
5619 ++next_unused_line;
5620
5621 AssertIsNotUsed(new_lines[l]);
5622 }
5623
5624 // set up lines which have parents:
5625 for (const unsigned int face_no : cell->face_indices())
5626 {
5627 // Check the face (line) orientation to ensure that the (six or
5628 // eight) outer lines in new_lines are indexed in the default
5629 // orientation. This way we can index into this array in the
5630 // without special casing orientations (e.g., quadrilateral child
5631 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5632 const auto combined_orientation =
5633 cell->combined_face_orientation(face_no);
5634 Assert(combined_orientation ==
5636 combined_orientation ==
5639 for (unsigned int c = 0; c < 2; ++c)
5640 {
5641 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5642 inherited_orientations[2 * face_no + c] =
5643 cell->combined_face_orientation(face_no);
5644 }
5645 if (combined_orientation == numbers::reverse_line_orientation)
5646 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5647 }
5648
5649 // set up lines which do not have parents:
5650 if (cell->reference_cell() == ReferenceCells::Triangle)
5651 {
5652 new_lines[6]->set_bounding_object_indices(
5653 {new_vertices[3], new_vertices[4]});
5654 new_lines[7]->set_bounding_object_indices(
5655 {new_vertices[4], new_vertices[5]});
5656 new_lines[8]->set_bounding_object_indices(
5657 {new_vertices[5], new_vertices[3]});
5658 }
5659 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5660 {
5661 new_lines[8]->set_bounding_object_indices(
5662 {new_vertices[6], new_vertices[8]});
5663 new_lines[9]->set_bounding_object_indices(
5664 {new_vertices[8], new_vertices[7]});
5665 new_lines[10]->set_bounding_object_indices(
5666 {new_vertices[4], new_vertices[8]});
5667 new_lines[11]->set_bounding_object_indices(
5668 {new_vertices[8], new_vertices[5]});
5669 }
5670 else
5671 {
5673 }
5674
5675 for (unsigned int l = lmin; l < lmax; ++l)
5676 {
5677 new_lines[l]->set_used_flag();
5678 new_lines[l]->clear_user_flag();
5679 new_lines[l]->clear_user_data();
5680 new_lines[l]->clear_children();
5681 // new lines are always internal.
5682 new_lines[l]->set_boundary_id_internal(
5684 new_lines[l]->set_manifold_id(cell->manifold_id());
5685 }
5686
5688 subcells[ReferenceCells::max_n_children<dim>()];
5689 while (next_unused_cell->used() == true)
5690 ++next_unused_cell;
5691
5692 unsigned int n_children = 0;
5693 if (cell->reference_cell() == ReferenceCells::Triangle)
5694 n_children = 4;
5695 else if (cell->reference_cell() == ReferenceCells::Quadrilateral)
5696 n_children = 4;
5697 else
5699
5700 for (unsigned int i = 0; i < n_children; ++i)
5701 {
5702 AssertIsNotUsed(next_unused_cell);
5703 subcells[i] = next_unused_cell;
5704 ++next_unused_cell;
5705 if (i % 2 == 1 && i < n_children - 1)
5706 while (next_unused_cell->used() == true)
5707 ++next_unused_cell;
5708 }
5709
5710 // Assign lines to child cells:
5711 constexpr unsigned int X = numbers::invalid_unsigned_int;
5712 constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines = {
5713 {{{0, 8, 5, X}}, //
5714 {{1, 2, 6, X}}, //
5715 {{7, 3, 4, X}}, //
5716 {{6, 7, 8, X}}}};
5717 constexpr ::ndarray<unsigned int, 4, 4> quad_child_lines = {
5718 {{{0, 8, 4, 10}},
5719 {{8, 2, 5, 11}},
5720 {{1, 9, 10, 6}},
5721 {{9, 3, 11, 7}}}};
5722 // Here and below we assume that child cells have the same reference
5723 // cell type as the parent.
5724 const auto &child_lines =
5725 cell->reference_cell() == ReferenceCells::Triangle ?
5726 tri_child_lines :
5727 quad_child_lines;
5728 for (unsigned int i = 0; i < n_children; ++i)
5729 {
5730 if (cell->reference_cell() == ReferenceCells::Triangle)
5731 subcells[i]->set_bounding_object_indices(
5732 {new_lines[child_lines[i][0]]->index(),
5733 new_lines[child_lines[i][1]]->index(),
5734 new_lines[child_lines[i][2]]->index()});
5735 else
5736 subcells[i]->set_bounding_object_indices(
5737 {new_lines[child_lines[i][0]]->index(),
5738 new_lines[child_lines[i][1]]->index(),
5739 new_lines[child_lines[i][2]]->index(),
5740 new_lines[child_lines[i][3]]->index()});
5741
5742 subcells[i]->set_used_flag();
5743 subcells[i]->clear_refine_flag();
5744 subcells[i]->clear_user_flag();
5745 subcells[i]->clear_user_data();
5746 subcells[i]->clear_children();
5747 // inherit material properties
5748 subcells[i]->set_material_id(cell->material_id());
5749 subcells[i]->set_manifold_id(cell->manifold_id());
5750 subcells[i]->set_subdomain_id(cell->subdomain_id());
5751
5752 triangulation.levels[subcells[i]->level()]
5753 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5754
5755 // Finally, now that children are marked as used, we can set
5756 // orientation flags (if needed):
5757 if (triangulation.levels[subcells[i]->level()]
5758 ->face_orientations.n_objects() > 0)
5759 for (unsigned int face_no : cell->face_indices())
5760 subcells[i]->set_combined_face_orientation(
5761 face_no, inherited_orientations[child_lines[i][face_no]]);
5762 else
5763 // It should not be possible to inherit a nonstandard
5764 // orientation when orientations are not set up
5765 for (unsigned int face_no : cell->face_indices())
5766 Assert(inherited_orientations[child_lines[i][face_no]] ==
5769
5770 // We only store the parent for every second cell. That's because
5771 // cells are created during refinement in multiples of two, and so
5772 // two successive cells always share the same parent. As a
5773 // consequence, we can save a bit of work by skipping setting
5774 // parent indices for the odd children.
5775 if (i % 2 == 0)
5776 subcells[i]->set_parent(cell->index());
5777 }
5778
5779 // Unlike the same lines on other children, the innermost triangle's
5780 // faces are all in the default orientation:
5781 if (cell->reference_cell() == ReferenceCells::Triangle)
5782 for (unsigned int face_no : cell->face_indices())
5783 subcells[3]->set_combined_face_orientation(
5785
5786 for (unsigned int i = 0; i < n_children / 2; ++i)
5787 cell->set_children(2 * i, subcells[2 * i]->index());
5788
5789 cell->set_refinement_case(ref_case);
5790
5791 if (dim == spacedim - 1)
5792 for (unsigned int c = 0; c < n_children; ++c)
5793 cell->child(c)->set_direction_flag(cell->direction_flag());
5794 };
5795
5796 for (int level = 0;
5797 level < static_cast<int>(triangulation.levels.size()) - 1;
5798 ++level)
5799 {
5801 next_unused_cell = triangulation.begin_raw(level + 1);
5802
5803 for (const auto &cell :
5805 if (cell->refine_flag_set())
5806 {
5807 create_children(triangulation,
5808 next_unused_vertex,
5809 next_unused_line,
5810 next_unused_cell,
5811 cell);
5812
5813 if (cell->reference_cell() == ReferenceCells::Quadrilateral &&
5814 check_for_distorted_cells &&
5815 has_distorted_children<dim, spacedim>(cell))
5816 cells_with_distorted_children.distorted_cells.push_back(
5817 cell);
5818
5819 triangulation.signals.post_refinement_on_cell(cell);
5820 }
5821 }
5822
5823 return cells_with_distorted_children;
5824 }
5825
5826
5827
5832 template <int spacedim>
5835 const bool /*check_for_distorted_cells*/)
5836 {
5837 const unsigned int dim = 1;
5838
5839 // Check whether a new level is needed. We have to check for
5840 // this on the highest level only
5841 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5842 triangulation.levels.size() - 1))
5843 if (cell->refine_flag_set())
5844 {
5845 triangulation.levels.push_back(
5846 std::make_unique<internal::TriangulationImplementation::
5848 triangulation.strides.max_children_per_cell,
5849 triangulation.strides.max_faces_per_cell,
5850 triangulation.strides.max_vertices_per_cell));
5851 break;
5852 }
5853
5854 // check how much space is needed on every level. We need not
5855 // check the highest level since either - on the highest level
5856 // no cells are flagged for refinement - there are, but
5857 // prepare_refinement added another empty level
5858 std::size_t needed_vertices = 0;
5859 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
5860 --level_no)
5861 {
5862 std::size_t needed_cells = 0;
5863
5864 for (const auto &cell :
5865 triangulation.active_cell_iterators_on_level(level_no))
5866 if (cell->refine_flag_set())
5867 needed_cells += ReferenceCells::Line.n_isotropic_children();
5868
5869 // count number of used cells on the next higher level
5870 auto &next_level = *triangulation.levels[level_no + 1];
5871 const auto used_cells = std::count(next_level.cells.used.begin(),
5872 next_level.cells.used.end(),
5873 true);
5874
5875 if (used_cells + needed_cells > next_level.size())
5876 next_level.allocate_end((used_cells + needed_cells) -
5877 next_level.size(),
5878 // We are in 1d so there are no tetrahedra
5879 // and we do not need the orientation
5880 false,
5881 false);
5882
5883 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
5884 next_level.cells.allocate_end(needed_cells, 0);
5885 needed_vertices += needed_cells / 2;
5886 }
5887
5888 // add to needed vertices how many
5889 // vertices are already in use
5890 needed_vertices += std::count(triangulation.vertices_used.begin(),
5891 triangulation.vertices_used.end(),
5892 true);
5893 // if we need more vertices: create them, if not: leave the
5894 // array as is, since shrinking is not really possible because
5895 // some of the vertices at the end may be in use
5896 if (needed_vertices > triangulation.vertices.size())
5897 {
5898 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5899 triangulation.vertices_used.resize(needed_vertices, false);
5900 }
5901
5902
5903 // Do REFINEMENT on every level; exclude highest level as
5904 // above
5905
5906 // index of next unused vertex
5907 unsigned int next_unused_vertex = 0;
5908
5909 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5910 {
5912 next_unused_cell = triangulation.begin_raw(level + 1);
5913
5914 for (const auto &cell :
5916 if (cell->refine_flag_set())
5917 {
5918 // clear refinement flag
5919 cell->clear_refine_flag();
5920
5921 // search for next unused
5922 // vertex
5923 while (triangulation.vertices_used[next_unused_vertex] ==
5924 true)
5925 ++next_unused_vertex;
5926 Assert(
5927 next_unused_vertex < triangulation.vertices.size(),
5928 ExcMessage(
5929 "Internal error: During refinement, the triangulation "
5930 "wants to access an element of the 'vertices' array "
5931 "but it turns out that the array is not large enough."));
5932
5933 // Now we always ask the cell itself where to put
5934 // the new point. The cell in turn will query the
5935 // manifold object internally.
5936 triangulation.vertices[next_unused_vertex] =
5937 cell->center(true);
5938
5939 triangulation.vertices_used[next_unused_vertex] = true;
5940
5941 // search for next two unused cell (++ takes care of
5942 // the end of the vector)
5944 first_child,
5945 second_child;
5946 while (next_unused_cell->used() == true)
5947 ++next_unused_cell;
5948 first_child = next_unused_cell;
5949 first_child->set_used_flag();
5950 first_child->clear_user_data();
5951 ++next_unused_cell;
5952 AssertIsNotUsed(next_unused_cell);
5953 second_child = next_unused_cell;
5954 second_child->set_used_flag();
5955 second_child->clear_user_data();
5956
5957 types::subdomain_id subdomainid = cell->subdomain_id();
5958
5959 // insert first child
5960 cell->set_children(0, first_child->index());
5961 first_child->clear_children();
5962 first_child->set_bounding_object_indices(
5963 {cell->vertex_index(0), next_unused_vertex});
5964 first_child->set_material_id(cell->material_id());
5965 first_child->set_manifold_id(cell->manifold_id());
5966 first_child->set_subdomain_id(subdomainid);
5967 if (dim == spacedim - 1)
5968 first_child->set_direction_flag(cell->direction_flag());
5969
5970 // We only store the parent for every second cell. That's
5971 // because cells are created during refinement in multiples of
5972 // two, and so two successive cells always share the same
5973 // parent. As a consequence, we can save a bit of work by
5974 // skipping setting parent indices for the second child.
5975 first_child->set_parent(cell->index());
5976
5977 // Set manifold id of the right face. Only do this
5978 // on the first child.
5979 first_child->face(1)->set_manifold_id(cell->manifold_id());
5980
5981 // reset neighborship info (refer to
5982 // internal::TriangulationImplementation::TriaLevel for
5983 // details)
5984 first_child->set_neighbor(1, second_child);
5985 if (cell->neighbor(0).state() != IteratorState::valid)
5986 first_child->set_neighbor(0, cell->neighbor(0));
5987 else if (cell->neighbor(0)->is_active())
5988 {
5989 // since the neighbors level is always <=level,
5990 // if the cell is active, then there are no
5991 // cells to the left which may want to know
5992 // about this new child cell.
5993 Assert(cell->neighbor(0)->level() <= cell->level(),
5995 first_child->set_neighbor(0, cell->neighbor(0));
5996 }
5997 else
5998 // left neighbor is refined
5999 {
6000 // set neighbor to cell on same level
6001 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
6002 first_child->set_neighbor(0,
6003 cell->neighbor(0)->child(nbnb));
6004
6005 // reset neighbor info of all right descendant
6006 // of the left neighbor of cell
6008 left_neighbor = cell->neighbor(0);
6009 while (left_neighbor->has_children())
6010 {
6011 left_neighbor = left_neighbor->child(nbnb);
6012 left_neighbor->set_neighbor(nbnb, first_child);
6013 }
6014 }
6015
6016 // insert second child
6017 second_child->clear_children();
6018 second_child->set_bounding_object_indices(
6019 {next_unused_vertex, cell->vertex_index(1)});
6020 second_child->set_neighbor(0, first_child);
6021 second_child->set_material_id(cell->material_id());
6022 second_child->set_manifold_id(cell->manifold_id());
6023 second_child->set_subdomain_id(subdomainid);
6024 if (dim == spacedim - 1)
6025 second_child->set_direction_flag(cell->direction_flag());
6026
6027 if (cell->neighbor(1).state() != IteratorState::valid)
6028 second_child->set_neighbor(1, cell->neighbor(1));
6029 else if (cell->neighbor(1)->is_active())
6030 {
6031 Assert(cell->neighbor(1)->level() <= cell->level(),
6033 second_child->set_neighbor(1, cell->neighbor(1));
6034 }
6035 else
6036 // right neighbor is refined same as above
6037 {
6038 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
6039 second_child->set_neighbor(
6040 1, cell->neighbor(1)->child(nbnb));
6041
6043 right_neighbor = cell->neighbor(1);
6044 while (right_neighbor->has_children())
6045 {
6046 right_neighbor = right_neighbor->child(nbnb);
6047 right_neighbor->set_neighbor(nbnb, second_child);
6048 }
6049 }
6050 // inform all listeners that cell refinement is done
6051 triangulation.signals.post_refinement_on_cell(cell);
6052 }
6053 }
6054
6055 // in 1d, we can not have distorted children unless the parent
6056 // was already distorted (that is because we don't use
6057 // boundary information for 1d triangulations). so return an
6058 // empty list
6060 }
6061
6062
6067 template <int spacedim>
6070 const bool check_for_distorted_cells)
6071 {
6072 const unsigned int dim = 2;
6073
6074 // First check whether we can get away with isotropic refinement, or
6075 // whether we need to run through the full anisotropic algorithm
6076 bool do_isotropic_refinement = true;
6077 for (const auto &cell : triangulation.active_cell_iterators())
6078 if (cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
6079 cell->refine_flag_set() == RefinementCase<dim>::cut_y)
6080 {
6081 do_isotropic_refinement = false;
6082 break;
6083 }
6084
6085 if (do_isotropic_refinement)
6086 return execute_refinement_isotropic(triangulation,
6087 check_for_distorted_cells);
6088 else
6089 {
6090 // If we get here, we are doing anisotropic refinement.
6091
6092 // Check whether a new level is needed. We have to check for
6093 // this on the highest level only
6094 for (const auto &cell :
6095 triangulation.active_cell_iterators_on_level(
6096 triangulation.levels.size() - 1))
6097 if (cell->refine_flag_set())
6098 {
6099 triangulation.levels.push_back(
6100 std::make_unique<internal::TriangulationImplementation::
6102 triangulation.strides.max_children_per_cell,
6103 triangulation.strides.max_faces_per_cell,
6104 triangulation.strides.max_vertices_per_cell));
6105 break;
6106 }
6107
6108 // TODO[WB]: we clear user flags and pointers of lines; we're going
6109 // to use them to flag which lines need refinement
6111 triangulation.begin_line();
6112 line != triangulation.end_line();
6113 ++line)
6114 {
6115 line->clear_user_flag();
6116 line->clear_user_data();
6117 }
6118
6119 // running over all cells and lines count the number
6120 // n_single_lines of lines which can be stored as single
6121 // lines, e.g. inner lines
6122 unsigned int n_single_lines = 0;
6123
6124 // New lines to be created: number lines which are stored in
6125 // pairs (the children of lines must be stored in pairs)
6126 unsigned int n_lines_in_pairs = 0;
6127
6128 // check how much space is needed on every level. We need not
6129 // check the highest level since either - on the highest level
6130 // no cells are flagged for refinement - there are, but
6131 // prepare_refinement added another empty level
6132 unsigned int needed_vertices = 0;
6133
6134 const bool orientation_needed =
6135 !triangulation.all_reference_cells_are_hyper_cube();
6136
6137 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
6138 --level_no)
6139 {
6140 // count number of flagged cells on this level and compute
6141 // how many new vertices and new lines will be needed
6142 std::size_t needed_cells = 0;
6143
6144 for (const auto &cell :
6145 triangulation.active_cell_iterators_on_level(level_no))
6146 if (cell->refine_flag_set())
6147 {
6148 Assert(cell->reference_cell().is_hyper_cube(),
6150 if (cell->refine_flag_set() ==
6152 {
6153 needed_cells += 4;
6154
6155 // new vertex at center of cell is needed in any
6156 // case
6157 ++needed_vertices;
6158
6159 // the four inner lines can be stored as singles
6160 n_single_lines += 4;
6161 }
6162 else // cut_x || cut_y
6163 {
6164 // set the flag showing that anisotropic
6165 // refinement is used for at least one cell
6166 triangulation.anisotropic_refinement = true;
6167
6168 needed_cells += 2;
6169 // no vertex at center
6170
6171 // the inner line can be stored as single
6172 n_single_lines += 1;
6173 }
6174
6175 // mark all faces (lines) for refinement; checking
6176 // locally whether the neighbor would also like to
6177 // refine them is rather difficult for lines so we
6178 // only flag them and after visiting all cells, we
6179 // decide which lines need refinement;
6180 for (const unsigned int line_no :
6182 {
6184 cell->refine_flag_set(), line_no) ==
6186 {
6187 typename Triangulation<dim,
6188 spacedim>::line_iterator
6189 line = cell->line(line_no);
6190 if (line->has_children() == false)
6191 line->set_user_flag();
6192 }
6193 }
6194 }
6195
6196 auto &next_level = *triangulation.levels[level_no + 1];
6197 const auto used_cells =
6198 std::count(next_level.cells.used.begin(),
6199 next_level.cells.used.end(),
6200 true);
6201 if (used_cells + needed_cells > next_level.size())
6202 next_level.allocate_end(
6203 (used_cells + needed_cells) - next_level.size(),
6204 orientation_needed,
6205 // We are in 2d so there are no tetrahedra
6206 false);
6207
6208 // TODO: perhaps we can merge this with
6209 // TriaLevel::allocate_end()
6210 next_level.cells.allocate_end(needed_cells, 0);
6211 }
6212
6213 // now count the lines which were flagged for refinement
6215 triangulation.begin_line();
6216 line != triangulation.end_line();
6217 ++line)
6218 if (line->user_flag_set())
6219 {
6220 Assert(line->has_children() == false, ExcInternalError());
6221 n_lines_in_pairs += 2;
6222 needed_vertices += 1;
6223 }
6224 // reserve space for n_lines_in_pairs new lines. note, that
6225 // we can't reserve space for the single lines here as well,
6226 // as all the space reserved for lines in pairs would be
6227 // counted as unused and we would end up with too little space
6228 // to store all lines. memory reservation for n_single_lines
6229 // can only be done AFTER we refined the lines of the current
6230 // cells
6231 triangulation.faces->lines.allocate_end(n_lines_in_pairs, 0);
6232
6233 // add to needed vertices how many vertices are already in use
6234 needed_vertices += std::count(triangulation.vertices_used.begin(),
6235 triangulation.vertices_used.end(),
6236 true);
6237 // if we need more vertices: create them, if not: leave the
6238 // array as is, since shrinking is not really possible because
6239 // some of the vertices at the end may be in use
6240 if (needed_vertices > triangulation.vertices.size())
6241 {
6242 triangulation.vertices.resize(needed_vertices,
6243 Point<spacedim>());
6244 triangulation.vertices_used.resize(needed_vertices, false);
6245 }
6246
6247
6248 // Do REFINEMENT on every level; exclude highest level as
6249 // above
6250
6251 // index of next unused vertex
6252 unsigned int next_unused_vertex = 0;
6253
6254 // first the refinement of lines. children are stored
6255 // pairwise
6256 {
6257 // only active objects can be refined further
6259 line = triangulation.begin_active_line(),
6260 endl = triangulation.end_line();
6262 next_unused_line = triangulation.begin_raw_line();
6263
6264 for (; line != endl; ++line)
6265 if (line->user_flag_set())
6266 {
6267 // this line needs to be refined
6268
6269 // find the next unused vertex and set it
6270 // appropriately
6271 while (triangulation.vertices_used[next_unused_vertex] ==
6272 true)
6273 ++next_unused_vertex;
6274 Assert(
6275 next_unused_vertex < triangulation.vertices.size(),
6276 ExcMessage(
6277 "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."));
6278 triangulation.vertices_used[next_unused_vertex] = true;
6279
6280 triangulation.vertices[next_unused_vertex] =
6281 line->center(true);
6282
6283 // now that we created the right point, make up the
6284 // two child lines. To this end, find a pair of
6285 // unused lines
6286 bool pair_found = false;
6287 for (; next_unused_line != endl; ++next_unused_line)
6288 if (!next_unused_line->used() &&
6289 !(++next_unused_line)->used())
6290 {
6291 // go back to the first of the two unused
6292 // lines
6293 --next_unused_line;
6294 pair_found = true;
6295 break;
6296 }
6297 Assert(pair_found, ExcInternalError());
6298
6299 // there are now two consecutive unused lines, such
6300 // that the children of a line will be consecutive.
6301 // then set the child pointer of the present line
6302 line->set_children(0, next_unused_line->index());
6303
6304 // set the two new lines
6305 const typename Triangulation<dim,
6306 spacedim>::raw_line_iterator
6307 children[2] = {next_unused_line, ++next_unused_line};
6308 // some tests; if any of the iterators should be
6309 // invalid, then already dereferencing will fail
6310 AssertIsNotUsed(children[0]);
6311 AssertIsNotUsed(children[1]);
6312
6313 children[0]->set_bounding_object_indices(
6314 {line->vertex_index(0), next_unused_vertex});
6315 children[1]->set_bounding_object_indices(
6316 {next_unused_vertex, line->vertex_index(1)});
6317
6318 children[0]->set_used_flag();
6319 children[1]->set_used_flag();
6320 children[0]->clear_children();
6321 children[1]->clear_children();
6322 children[0]->clear_user_data();
6323 children[1]->clear_user_data();
6324 children[0]->clear_user_flag();
6325 children[1]->clear_user_flag();
6326
6327
6328 children[0]->set_boundary_id_internal(line->boundary_id());
6329 children[1]->set_boundary_id_internal(line->boundary_id());
6330
6331 children[0]->set_manifold_id(line->manifold_id());
6332 children[1]->set_manifold_id(line->manifold_id());
6333
6334 // finally clear flag indicating the need for
6335 // refinement
6336 line->clear_user_flag();
6337 }
6338 }
6339
6340
6341 // Now set up the new cells
6342
6343 // reserve space for inner lines (can be stored as single
6344 // lines)
6345 triangulation.faces->lines.allocate_end(0, n_single_lines);
6346
6348 cells_with_distorted_children;
6349
6350 // reset next_unused_line, as now also single empty places in
6351 // the vector can be used
6353 next_unused_line = triangulation.begin_raw_line();
6354
6355 for (int level = 0;
6356 level < static_cast<int>(triangulation.levels.size()) - 1;
6357 ++level)
6358 {
6360 next_unused_cell = triangulation.begin_raw(level + 1);
6361
6362 for (const auto &cell :
6364 if (cell->refine_flag_set())
6365 {
6366 // actually set up the children and update neighbor
6367 // information
6368 create_children(triangulation,
6369 next_unused_vertex,
6370 next_unused_line,
6371 next_unused_cell,
6372 cell);
6373
6374 if (check_for_distorted_cells &&
6375 has_distorted_children<dim, spacedim>(cell))
6376 cells_with_distorted_children.distorted_cells.push_back(
6377 cell);
6378 // inform all listeners that cell refinement is done
6379 triangulation.signals.post_refinement_on_cell(cell);
6380 }
6381 }
6382
6383 return cells_with_distorted_children;
6384 }
6385 }
6386
6387
6388 template <int spacedim>
6391 const bool check_for_distorted_cells)
6392 {
6393 constexpr int dim = 3;
6394 constexpr unsigned int X = numbers::invalid_unsigned_int;
6395 using raw_line_iterator =
6397 using raw_quad_iterator =
6399
6400 Assert(spacedim == 3, ExcNotImplemented());
6401
6402 Assert(triangulation.vertices.size() ==
6403 triangulation.vertices_used.size(),
6405
6406 // Check whether a new level is needed. We have to check for
6407 // this on the highest level only
6408 for (const auto &cell : triangulation.active_cell_iterators_on_level(
6409 triangulation.levels.size() - 1))
6410 if (cell->refine_flag_set())
6411 {
6413 triangulation.levels.size() < numbers::max_n_levels,
6415 triangulation.levels.push_back(
6416 std::make_unique<internal::TriangulationImplementation::
6418 triangulation.strides.max_children_per_cell,
6419 triangulation.strides.max_faces_per_cell,
6420 triangulation.strides.max_vertices_per_cell));
6421 break;
6422 }
6423
6424 // first clear user flags for quads and lines; we're going to
6425 // use them to flag which lines and quads need refinement
6426 triangulation.faces->quads.clear_user_data();
6427 triangulation.faces->lines.clear_user_flags();
6428 triangulation.faces->quads.clear_user_flags();
6429
6430 // check how much space is needed on every level. We need not
6431 // check the highest level since either
6432 // - on the highest level no cells are flagged for refinement
6433 // - there are, but prepare_refinement added another empty
6434 // level which then is the highest level
6435
6436 // Variables to hold the number of newly to be created
6437 // vertices, lines, and faces. As these are stored globally,
6438 // declare them outside the loop over all levels. We need lines
6439 // and faces in pairs for refinement of old lines/face. And lines and
6440 // faces stored individually for the ones created in the interior
6441 // of an existing cell
6442 { // STORAGE
6443 unsigned int needed_vertices = 0;
6444 unsigned int needed_lines_single = 0;
6445 unsigned int needed_faces_single = 0;
6446 unsigned int needed_lines_pair = 0;
6447 unsigned int needed_faces_pair = 0;
6448 bool contains_pyramid = false;
6449 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
6450 --level_no)
6451 {
6452 std::size_t needed_cells = 0;
6453
6454 for (const auto &cell :
6455 triangulation.active_cell_iterators_on_level(level_no))
6456 if (cell->refine_flag_set())
6457 {
6458 // Only support isotropic refinement
6459 Assert(cell->refine_flag_set() ==
6462
6463 // get reference cell type of current cell
6464 const auto cell_reference_cell = cell->reference_cell();
6465
6466 // Now count up how many new cells, faces, edges, and
6467 // vertices we will need to allocate to do this refinement.
6468 needed_cells += cell_reference_cell.n_isotropic_children();
6469
6470 switch (cell_reference_cell)
6471 {
6473 needed_lines_single += 1;
6474 needed_faces_single += 8;
6475 break;
6476
6478 // TODO: Pyramid
6479 // - No vertices (all provided by face refinement)
6480 // - 5 faces for center pyramid
6481 // - 4 times 2 for the remaining tets
6482 needed_lines_single += 4;
6483 needed_faces_single += 13;
6484 contains_pyramid = true;
6485 break;
6486
6488 // - We won't need vertices (all required vertices
6489 // will be provided by the refined faces)
6490 // - 3 lines will be required to build up the
6491 // "refined" middle triangle
6492 // - 4 faces for the new refined middle triangle + 6
6493 // faces for the quads building the wedges in
6494 // z-direction. Rest will be provided via refinement
6495 // of faces. Store them all as singles. See also
6496 // https://link.springer.com/article/10.1007/BF01221213
6497 needed_lines_single += 3;
6498 needed_faces_single += 10;
6499 break;
6500
6502 // One vertex in the center of the parent
6503 ++needed_vertices;
6504 needed_lines_single += 6;
6505 needed_faces_single += 12;
6506 break;
6507
6508 default:
6510 }
6511
6512 // Also check whether we have to refine any of the faces and
6513 // edges that bound this cell. They may of course already be
6514 // refined, so we only *mark* them for refinement by setting
6515 // the user flags
6516
6517 // Faces
6518 for (const auto face : cell->face_indices())
6519 if (cell->face(face)->n_children() == 0)
6520 cell->face(face)->set_user_flag();
6521 else
6522 // Check that the child of the cell has enough children
6523 Assert(cell->face(face)->n_children() ==
6524 cell_reference_cell.face_reference_cell(face)
6525 .n_isotropic_children(),
6527
6528 // Edges
6529 for (const auto line : cell->line_indices())
6530 if (cell->line(line)->has_children() == false)
6531 cell->line(line)->set_user_flag();
6532 else
6533 Assert(cell->line(line)->n_children() == 2,
6535 }
6536
6537 auto &next_level = *triangulation.levels[level_no + 1];
6538 const auto used_cells = std::count(next_level.cells.used.begin(),
6539 next_level.cells.used.end(),
6540 true);
6541 if (used_cells + needed_cells > next_level.size())
6542 next_level.allocate_end(
6543 (used_cells + needed_cells) - next_level.size(),
6544 // We unconditionally store the orientation in 3d
6545 true,
6546 // TODO: we can get rid of this check (i.e., we don't need to
6547 // store this value for purely wedge meshes). This will be
6548 // simpler to do once we merge IsotropicRefinementChoice and
6549 // RefinementCase.
6550 !triangulation.all_reference_cells_are_hyper_cube());
6551
6552 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
6553 next_level.cells.allocate_end(needed_cells, 0);
6554 }
6555
6556 // In case a pyramid is going to be refined we will get additional
6557 // tets in the refined triangulation, hence we need to inform the
6558 // triangulation that this happens. Note: if coarsening gets
6559 // implemented this step needs to be reverted. Maybe switch to a
6560 // refinement counter for pyramids and track its value to revert this
6561 // change.
6562 if (contains_pyramid)
6563 // Prevent multiple occurrences of tet inside the vector
6564 if (std::find(triangulation.reference_cells.begin(),
6565 triangulation.reference_cells.end(),
6567 triangulation.reference_cells.end())
6568 // Add it to start of vector to keep sorting intact.
6569 triangulation.reference_cells.insert(
6570 triangulation.reference_cells.begin(),
6572
6573 // now count the faces and lines which were flagged for
6574 // refinement
6576 triangulation.begin_quad();
6577 quad != triangulation.end_quad();
6578 ++quad)
6579 {
6580 if (quad->user_flag_set() == false)
6581 continue;
6582
6583 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6584 {
6585 needed_faces_pair += 4;
6586 needed_lines_pair += 4;
6587 needed_vertices += 1;
6588 }
6589 else if (quad->reference_cell() == ReferenceCells::Triangle)
6590 {
6591 needed_faces_pair += 4;
6592 needed_lines_single += 3;
6593 }
6594 else
6595 {
6597 }
6598 }
6599
6601 triangulation.begin_line();
6602 line != triangulation.end_line();
6603 ++line)
6604 {
6605 if (line->user_flag_set() == false)
6606 continue;
6607
6608 needed_lines_pair += 2;
6609 needed_vertices += 1;
6610 }
6611
6612 triangulation.faces->allocate_end(needed_faces_pair,
6613 needed_faces_single);
6614 triangulation.faces->lines.allocate_end(needed_lines_pair,
6615 needed_lines_single);
6616
6617 // add to needed vertices how many vertices are already in use
6618 needed_vertices += std::count(triangulation.vertices_used.begin(),
6619 triangulation.vertices_used.end(),
6620 true);
6621
6622 if (needed_vertices > triangulation.vertices.size())
6623 {
6624 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6625 triangulation.vertices_used.resize(needed_vertices, false);
6626 }
6627 } // STORAGE
6628
6629 //-----------------------------------------
6630 // Before we start with the actual refinement, we do some
6631 // sanity checks if in debug mode. especially, we try to catch
6632 // the notorious problem with lines being twice refined,
6633 // i.e. there are cells adjacent at one line ("around the
6634 // edge", but not at a face), with two cells differing by more
6635 // than one refinement level
6636 //
6637 // this check is very simple to implement here, since we have
6638 // all lines flagged if they shall be refined
6639 if constexpr (running_in_debug_mode())
6640 {
6641 for (const auto &cell : triangulation.active_cell_iterators())
6642 if (!cell->refine_flag_set())
6643 for (unsigned int line_n = 0; line_n < cell->n_lines();
6644 ++line_n)
6645 if (cell->line(line_n)->has_children())
6646 for (unsigned int c = 0; c < 2; ++c)
6647 Assert(cell->line(line_n)->child(c)->user_flag_set() ==
6648 false,
6650 }
6651
6652 unsigned int current_vertex = 0;
6653
6654 // helper function - find the next available vertex number and mark it
6655 // as used.
6656 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6657 std::vector<bool> &vertices_used) {
6658 unsigned int next_vertex = current_vertex;
6659 while (next_vertex < vertices_used.size() &&
6660 vertices_used[next_vertex] == true)
6661 ++next_vertex;
6662 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6663 vertices_used[next_vertex] = true;
6664
6665 return next_vertex;
6666 };
6667
6668
6669 { // LINES
6671 line = triangulation.begin_active_line(),
6672 endl = triangulation.end_line();
6673 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6674
6675 for (; line != endl; ++line)
6676 {
6677 if (line->user_flag_set() == false)
6678 continue;
6679
6680 next_unused_line =
6681 triangulation.faces->lines.template next_free_pair_object<1>(
6682 triangulation);
6683 Assert(next_unused_line.state() == IteratorState::valid,
6685
6686 // now we found two consecutive unused lines, such
6687 // that the children of a line will be consecutive.
6688 // then set the child pointer of the present line
6689 line->set_children(0, next_unused_line->index());
6690
6691 const std::array<raw_line_iterator, 2> children{
6692 {next_unused_line, ++next_unused_line}};
6693
6694 AssertIsNotUsed(children[0]);
6695 AssertIsNotUsed(children[1]);
6696
6697 current_vertex =
6698 get_next_unused_vertex(current_vertex,
6699 triangulation.vertices_used);
6700 triangulation.vertices[current_vertex] = line->center(true);
6701
6702 children[0]->set_bounding_object_indices(
6703 {line->vertex_index(0), current_vertex});
6704 children[1]->set_bounding_object_indices(
6705 {current_vertex, line->vertex_index(1)});
6706
6707 const auto manifold_id = line->manifold_id();
6708 const auto boundary_id = line->boundary_id();
6709 for (const auto &child : children)
6710 {
6711 child->set_used_flag();
6712 child->clear_children();
6713 child->clear_user_data();
6714 child->clear_user_flag();
6715 child->set_boundary_id_internal(boundary_id);
6716 child->set_manifold_id(manifold_id);
6717 }
6718
6719 line->clear_user_flag();
6720 }
6721 }
6722
6723 { // FACES
6724 // (i.e., quads or triangles, or both)
6726 face = triangulation.begin_face(),
6727 endf = triangulation.end_face();
6728
6729 for (; face != endf; ++face)
6730 {
6731 if (face->user_flag_set() == false)
6732 continue;
6733
6734 const auto reference_face_type = face->reference_cell();
6735 const auto n_lines_per_face = reference_face_type.n_lines();
6736
6737 // 1) Create new lines (property is set later).
6738 // Maximum of 4 new lines (4 quadrilateral, 3 triangle).
6739 std::array<raw_line_iterator, 4> new_lines;
6740 switch (reference_face_type)
6741 {
6743 for (unsigned int l = 0; l < 3; ++l)
6744 new_lines[l] =
6745 triangulation.faces->lines
6746 .template next_free_single_object<1>(triangulation);
6747 break;
6748
6750 for (unsigned int l = 0; l < 2; ++l)
6751 {
6752 auto next_unused_line =
6753 triangulation.faces->lines
6754 .template next_free_pair_object<1>(triangulation);
6755 new_lines[2 * l] = next_unused_line;
6756 new_lines[2 * l + 1] = ++next_unused_line;
6757 }
6758 break;
6759
6760 default:
6762 }
6763
6764 if constexpr (running_in_debug_mode())
6765 {
6766 for (const unsigned int line : face->line_indices())
6767 AssertIsNotUsed(new_lines[line]);
6768 }
6769
6770 // 2) Create new face (properties are set below).
6771 // Both triangles and quads are divided in four. (For historical
6772 // reasons, we only have `raw_quad_iterator`, not
6773 // `raw_face_iterator`, but the former also works if a face is
6774 // actually a triangle.)
6775 std::array<raw_quad_iterator, 4> new_faces;
6776 for (unsigned int f = 0; f < 2; ++f)
6777 {
6778 auto next_unused_quad =
6779 triangulation.faces->quads
6780 .template next_free_pair_object<2>(triangulation);
6781
6782 new_faces[2 * f] = next_unused_quad;
6783 new_faces[2 * f + 1] = ++next_unused_quad;
6784
6785 face->set_children(2 * f, new_faces[2 * f]->index());
6786 }
6787 // Tell the original face that is has been isotropically refined.
6788 face->set_refinement_case(RefinementCase<2>::cut_xy);
6789
6790 if constexpr (running_in_debug_mode())
6791 {
6792 for (const auto &quad : new_faces)
6793 AssertIsNotUsed(quad);
6794 }
6795
6796 // 3) Create an ordered list of vertices.
6797 // The order is determined by the physical position of the
6798 // vertices within the face reference cell, enabling easy
6799 // identification/lookup by the vertex's index in this list.
6800 // Additionally the center vertex required for quadrilaterals is
6801 // created.
6802
6803 // Maximum of 9 vertices per refined face (9 for Quadrilateral, 6
6804 // for Triangle)
6805 std::array<unsigned int, 9> vertex_indices = {};
6806 unsigned int k = 0;
6807 for (const auto i : face->vertex_indices())
6808 vertex_indices[k++] = face->vertex_index(i);
6809
6810 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6811 vertex_indices[k++] = face->line(l)->child(0)->vertex_index(1);
6812
6813 if (reference_face_type == ReferenceCells::Quadrilateral)
6814 {
6815 current_vertex =
6816 get_next_unused_vertex(current_vertex,
6817 triangulation.vertices_used);
6818 vertex_indices[k++] = current_vertex;
6819
6820 triangulation.vertices[current_vertex] =
6821 face->center(true, true);
6822 }
6823
6824 // 4) Set new lines on these faces and their properties.
6825 // 'magic numbers' in `line_vertices_X` are indices in the list
6826 // created in step 3).
6827 std::array<raw_line_iterator, 12> lines;
6828 unsigned int n_lines = 0;
6829 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6830 for (unsigned int c = 0; c < 2; ++c)
6831 lines[n_lines++] = face->line(l)->child(
6832 child_line_index(c, face->line_orientation(l)));
6833
6834 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6835 lines[n_lines++] = new_lines[l];
6836
6837 std::array<int, 12> line_indices;
6838 for (unsigned int i = 0; i < n_lines; ++i)
6839 line_indices[i] = lines[i]->index();
6840
6841 // 2---7---3 .-6-.-7-. .---.---.
6842 // | | | 1 9 3 | 2 | 3 |
6843 // 4---8---5 .-10.11-. .---.---.
6844 // | | | 0 8 2 | 0 | 1 |
6845 // 0---6---1 .-4-.-5-. .---.---.
6846 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_quad{
6847 {{{0, 4}},
6848 {{4, 2}},
6849 {{1, 5}},
6850 {{5, 3}},
6851 {{0, 6}},
6852 {{6, 1}},
6853 {{2, 7}},
6854 {{7, 3}},
6855 {{6, 8}},
6856 {{8, 7}},
6857 {{4, 8}},
6858 {{8, 5}}}};
6859
6860 constexpr ::ndarray<unsigned int, 4, 4> quad_lines_quad{
6861 {{{0, 8, 4, 10}},
6862 {{8, 2, 5, 11}},
6863 {{1, 9, 10, 6}},
6864 {{9, 3, 11, 7}}}};
6865
6866 // 2 * * .
6867 // |\ |\ |\ .
6868 // v ^ 4 3 | \ .
6869 // | \ | \ | 2 \ .
6870 // 5--<--4 *--7--* *-----* .
6871 // |\ |\ |\ |\ |\ 3 |\ .
6872 // v ^ ^ ^ 5 8 6 2 | \ | \ .
6873 // | \| \ | \| \ | 0 \| 1 \ .
6874 // 0-->--3-->--1 *--0--*--1--* *-----*-----* .
6875 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_tri{
6876 {{{0, 3}},
6877 {{3, 1}},
6878 {{1, 4}},
6879 {{4, 2}},
6880 {{2, 5}},
6881 {{5, 0}},
6882 {{3, 4}},
6883 {{4, 5}},
6884 {{3, 5}},
6885 {{X, X}},
6886 {{X, X}},
6887 {{X, X}}}};
6888
6889 constexpr ::ndarray<unsigned int, 4, 4> tri_lines_tri{
6890 {{{0, 8, 5, X}},
6891 {{1, 2, 6, X}},
6892 {{7, 3, 4, X}},
6893 {{6, 7, 8, X}}}};
6894
6895 // The defined lines in `line_vertices_tri` do not satisfy the
6896 // expected orientations of all the children's reference cells.
6897 // This table specifies the expected line orientations (i.e.
6898 // vertex order) necessary for `set_line_orientation(...)`.
6899 constexpr ::ndarray<unsigned int, 4, 4, 2>
6900 tri_line_vertices_tri{
6901 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6902 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6903 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6904 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6905
6906 // Select lookup table according to reference cell of parent.
6907 const auto &line_vertices =
6908 (reference_face_type == ReferenceCells::Quadrilateral) ?
6909 line_vertices_quad :
6910 line_vertices_tri;
6911 const auto &face_lines =
6912 (reference_face_type == ReferenceCells::Quadrilateral) ?
6913 quad_lines_quad :
6914 tri_lines_tri;
6915
6916 // The first 2*face->n_lines() lines are already created by
6917 // refining the original lines on the face. Therefore, only the
6918 // subsequent face->n_lines() lines need to be processed now.
6919 for (unsigned int i = 0, j = 2 * n_lines_per_face;
6920 i < n_lines_per_face;
6921 ++i, ++j)
6922 {
6923 auto &new_line = new_lines[i];
6924 new_line->set_bounding_object_indices(
6925 {vertex_indices[line_vertices[j][0]],
6926 vertex_indices[line_vertices[j][1]]});
6927 new_line->set_used_flag();
6928 new_line->clear_user_flag();
6929 new_line->clear_user_data();
6930 new_line->clear_children();
6931 new_line->set_boundary_id_internal(face->boundary_id());
6932 new_line->set_manifold_id(face->manifold_id());
6933 }
6934
6935 // 5) Set properties of faces
6936 for (unsigned int i = 0; i < new_faces.size(); ++i)
6937 {
6938 // 5.a) Create faces
6939 auto &new_face = new_faces[i];
6940
6941 // We assume here that all children have the same type as the
6942 // parent face.
6943 triangulation.faces->set_quad_type(new_face->index(),
6944 reference_face_type);
6945
6946 switch (reference_face_type)
6947 {
6949 new_face->set_bounding_object_indices(
6950 {line_indices[face_lines[i][0]],
6951 line_indices[face_lines[i][1]],
6952 line_indices[face_lines[i][2]]});
6953 break;
6954
6956 new_face->set_bounding_object_indices(
6957 {line_indices[face_lines[i][0]],
6958 line_indices[face_lines[i][1]],
6959 line_indices[face_lines[i][2]],
6960 line_indices[face_lines[i][3]]});
6961 break;
6962
6963 default:
6965 }
6966
6967 new_face->set_used_flag();
6968 new_face->clear_user_flag();
6969 new_face->clear_user_data();
6970 new_face->clear_children();
6971 new_face->set_boundary_id_internal(face->boundary_id());
6972 new_face->set_manifold_id(face->manifold_id());
6973
6974 [[maybe_unused]] std::set<unsigned int> s;
6975
6976 // 5.b.I) Fix orientation of lines of face
6977 // For triangles an expensive algorithm is used,
6978 // quadrilaterals are treated a few lines below by a cheaper
6979 // algorithm
6980 if (reference_face_type == ReferenceCells::Triangle)
6981 {
6982 for (const auto f : new_face->line_indices())
6983 {
6984 const std::array<unsigned int, 2> vertices_0 = {
6985 {lines[face_lines[i][f]]->vertex_index(0),
6986 lines[face_lines[i][f]]->vertex_index(1)}};
6987
6988 const std::array<unsigned int, 2> vertices_1 = {
6989 {vertex_indices[tri_line_vertices_tri[i][f][0]],
6990 vertex_indices[tri_line_vertices_tri[i][f][1]]}};
6991
6992 const auto orientation =
6993 ReferenceCells::Line.get_combined_orientation(
6994 make_array_view(vertices_0),
6995 make_array_view(vertices_1));
6996
6997 if constexpr (library_build_mode ==
6999 {
7000 for (const auto i : vertices_0)
7001 s.insert(i);
7002 for (const auto i : vertices_1)
7003 s.insert(i);
7004 }
7005
7006 new_face->set_line_orientation(f, orientation);
7007 }
7008 if constexpr (library_build_mode ==
7010 {
7011 AssertDimension(s.size(), 3);
7012 }
7013 }
7014 }
7015
7016 // 5.b.II) Fix orientation of lines of faces for quadrilaterals
7017 // with cheap algorithm.
7018 if (reference_face_type == ReferenceCells::Quadrilateral)
7019 {
7020 constexpr ::ndarray<unsigned int, 4, 2>
7021 quad_child_line_vertices{{{{0, 2}}, //
7022 {{1, 3}}, //
7023 {{0, 1}}, //
7024 {{2, 3}}}};
7025
7026 for (unsigned int i = 0; i < 4; ++i)
7027 for (unsigned int j = 0; j < 2; ++j)
7028 new_faces[quad_child_line_vertices[i][j]]
7029 ->set_line_orientation(i, face->line_orientation(i));
7030 }
7031
7032 face->clear_user_flag();
7033 }
7034 } // FACES
7035
7036 // Cells
7038 cells_with_distorted_children;
7039
7041 triangulation.begin_active(0);
7042 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
7043 ++level)
7044 {
7046 next_unused_cell = triangulation.begin_raw(level + 1);
7047 Assert(cell == triangulation.end() ||
7048 cell->level() >= static_cast<int>(level),
7050
7051 // Iterate over all active cells in the current level
7052 for (; cell != triangulation.end() &&
7053 cell->level() == static_cast<int>(level);
7054 ++cell)
7055 {
7056 if (cell->refine_flag_set() ==
7058 continue;
7059
7060 // Copy the requested refinement case to the cell's actual
7061 // refinement flag, informing the cell how it has been refined.
7062 const RefinementCase<dim> ref_case = cell->refine_flag_set();
7063 cell->clear_refine_flag();
7064 cell->set_refinement_case(ref_case);
7065
7066 const auto cell_reference_cell = cell->reference_cell();
7067
7068 unsigned int n_new_lines = 0;
7069 unsigned int n_new_faces = 0;
7070 const unsigned int n_new_cells =
7071 cell_reference_cell.n_isotropic_children();
7072
7073 // Must match the information used close the beginning of this
7074 // function.
7075 switch (cell_reference_cell)
7076 {
7078 n_new_lines = 1;
7079 n_new_faces = 8;
7080 break;
7081
7083 n_new_lines = 4;
7084 n_new_faces = 13;
7085 break;
7086
7088 n_new_lines = 3;
7089 n_new_faces = 10;
7090 break;
7091
7093 n_new_lines = 6;
7094 n_new_faces = 12;
7095 break;
7096
7097 default:
7099 }
7100
7101 // the following numbers should be the max numbers of the above.
7102 // They are used for sizing of arrays.
7103 constexpr unsigned int max_n_new_lines = 6;
7104 constexpr unsigned int max_n_new_faces = 13;
7105 constexpr unsigned int max_n_new_children = 10;
7106 constexpr unsigned int max_relevant_vertices = 27;
7107 constexpr unsigned int max_relevant_lines = 30;
7108 constexpr unsigned int max_face_indices = 36;
7109
7110 std::array<raw_line_iterator, max_n_new_lines> new_lines;
7111 for (unsigned int i = 0; i < n_new_lines; ++i)
7112 {
7113 new_lines[i] =
7114 triangulation.faces->lines
7115 .template next_free_single_object<1>(triangulation);
7116
7117 AssertIsNotUsed(new_lines[i]);
7118 new_lines[i]->set_used_flag();
7119 new_lines[i]->clear_user_flag();
7120 new_lines[i]->clear_user_data();
7121 new_lines[i]->clear_children();
7122 new_lines[i]->set_boundary_id_internal(
7124 new_lines[i]->set_manifold_id(cell->manifold_id());
7125 }
7126
7127 std::array<raw_quad_iterator, max_n_new_faces> new_faces;
7128 for (unsigned int i = 0; i < n_new_faces; ++i)
7129 {
7130 new_faces[i] =
7131 triangulation.faces->quads
7132 .template next_free_single_object<2>(triangulation);
7133
7134 auto &new_face = new_faces[i];
7135
7136 AssertIsNotUsed(new_face);
7137 new_face->set_used_flag();
7138 new_face->clear_user_flag();
7139 new_face->clear_user_data();
7140 new_face->clear_children();
7141 new_face->set_boundary_id_internal(
7143 new_face->set_manifold_id(cell->manifold_id());
7144
7145 // At this point the face doesn't have its ReferenceCell
7146 // set, so rely on lower-level functionality to reset
7147 // per-line data
7148 for (unsigned int j = 0;
7149 j < triangulation.faces->lines_per_quad;
7150 ++j)
7151 new_face->set_line_orientation(
7153 }
7154
7155
7156 { // CREATE_CELLS
7157 // Build a list of all relevant vertices required for
7158 // - The creation of additional faces not generated by the
7159 // refinement of the parent faces.
7160 // - The definition of the child cells.
7161 //
7162 // Number of meaningful entries in this list is
7163 // 10 Tetrahedron 18 Wedge
7164 // 14 Pyramid 27 Hexahedron
7165 // In case the maximum changes, edit `max_relevant_vertices` a
7166 // few lines above (or in case it was moved to ReferenceCell,
7167 // update it there).
7168 //
7169 // The following algorithm is used to get the vertices.
7170 // 1. Get vertices of the parent as provided.
7171 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
7172 //
7173 // 2. Get the center vertices of the (refined) bounding lines
7174 // of the parent's faces (quad and tet (i.e. all) faces)
7175 //
7176 // .---3---. .
7177 // | | /|
7178 // 0 1 or 2 1
7179 // | | / |
7180 // .---2---. .-0-. n: vertices retrieved
7181 //
7182 // 3. Get the remaining new vertices that were created in the
7183 // center of the parent's bounding faces during refinement
7184 // (quad faces)
7185 //
7186 // .-------.
7187 // | |
7188 // .---O |
7189 // | | |
7190 // .---.---. O: vertex retrieved
7191 //
7192 // 4. Get (or, better yet, create) the newly required
7193 // vertices. (i.e. the new vertex in the middle of a hex,
7194 // only relevant for hexes)
7195 //
7196 // .-------.
7197 // /| |
7198 // . | / |
7199 // | - -O |
7200 // | .--:----.
7201 // |/ : /
7202 // .-------.
7203
7204 std::array<unsigned int, max_relevant_vertices>
7205 vertex_indices = {};
7206
7207 { // GET_VERTICES
7208 // continuous counter variable
7209 unsigned int k = 0;
7210
7211 // avoid a compiler warning by fixing max number of
7212 // iterations to 8.
7213 const unsigned int n_vertices =
7214 std::min(cell->n_vertices(), 8u);
7215
7216 // Step 1 Get vertices of the parent
7217 for (unsigned int i = 0; i < n_vertices; ++i)
7218 vertex_indices[k++] = cell->vertex_index(i);
7219
7220 // Step 2 (relevant for all faces)
7221
7222 // Avoid a compiler warning by fixing the max number of loop
7223 // iterations to 12 (max number of new lines)
7224 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
7225
7226 const std::array<unsigned int, 12> line_indices =
7227 TriaAccessorImplementation::Implementation::
7228 get_line_indices_of_cell(*cell);
7229
7230 for (unsigned int l = 0; l < n_lines; ++l)
7231 {
7232 raw_line_iterator line(&triangulation,
7233 0,
7234 line_indices[l]);
7235 vertex_indices[k++] = line->child(0)->vertex_index(1);
7236 }
7237
7238 // Step 3 (depends on the reference cell type of face, only
7239 // quads affected)
7240 for (auto quad_face_index :
7241 cell_reference_cell.face_indices_by_type(
7243 {
7244 vertex_indices[k++] = cell->face(quad_face_index)
7245 ->child(0)
7246 ->vertex_index(3);
7247 }
7248
7249 // Step 4 Create the center vertex for hex cells
7250 if (cell_reference_cell == ReferenceCells::Hexahedron)
7251 {
7252 // Set single new vertex in the center
7253 current_vertex =
7254 get_next_unused_vertex(current_vertex,
7255 triangulation.vertices_used);
7256 vertex_indices[k++] = current_vertex;
7257
7258 triangulation.vertices[current_vertex] =
7259 cell->center(true, true);
7260 }
7261 } // GET_VERTICES
7262
7263
7264 unsigned int chosen_line_tetrahedron = 0;
7265
7266 // set up new lines
7267 switch (cell_reference_cell)
7268 {
7270 {
7271 // in the tetrahedron case, we have the three
7272 // possibilities (6,8), (5,7), (4,9) -> pick the
7273 // shortest line to guarantee the best possible aspect
7274 // ratios
7275 constexpr ::ndarray<unsigned int, 3, 2>
7276 new_line_vertices = {{{{6, 8}}, //
7277 {{5, 7}}, //
7278 {{4, 9}}}};
7279
7280 // choose line to cut either by refinement case or by
7281 // shortest distance between edge midpoints
7282 std::uint8_t refinement_choice =
7283 cell->refine_choice();
7284 if (refinement_choice ==
7285 static_cast<char>(IsotropicRefinementChoice::
7287 {
7288 const auto &vertices =
7289 triangulation.get_vertices();
7290 double min_distance =
7291 std::numeric_limits<double>::infinity();
7292 for (unsigned int i = 0;
7293 i < new_line_vertices.size();
7294 ++i)
7295 {
7296 const double current_distance =
7297 vertices[vertex_indices
7298 [new_line_vertices[i][0]]]
7299 .distance(
7300 vertices[vertex_indices
7301 [new_line_vertices[i][1]]]);
7302 if (current_distance < min_distance)
7303 {
7304 chosen_line_tetrahedron = i;
7305 min_distance = current_distance;
7306 }
7307 }
7308 }
7309 else if (refinement_choice ==
7310 static_cast<char>(
7312 chosen_line_tetrahedron = 0;
7313 else if (refinement_choice ==
7314 static_cast<char>(
7316 chosen_line_tetrahedron = 1;
7317 else if (refinement_choice ==
7318 static_cast<char>(
7320 chosen_line_tetrahedron = 2;
7321 else
7323
7324 cell->set_refinement_case(
7325 RefinementCase<dim>(chosen_line_tetrahedron + 1));
7326
7327 new_lines[0]->set_bounding_object_indices(
7329 [new_line_vertices[chosen_line_tetrahedron][0]],
7330 vertex_indices[new_line_vertices
7331 [chosen_line_tetrahedron][1]]});
7332 }
7333 break;
7334
7336 {
7337 // Directions so that middle bottom pyramids all have
7338 // lines with default orientation. Order as children
7339 // of refined bottom quad.
7340 static constexpr ::ndarray<unsigned int, 4, 2>
7341 new_line_vertices = {{{{13, 9}}, //
7342 {{13, 10}}, //
7343 {{13, 11}}, //
7344 {{13, 12}}}};
7345
7346 for (unsigned int i = 0; i < n_new_lines; ++i)
7347 new_lines[i]->set_bounding_object_indices(
7348 {vertex_indices[new_line_vertices[i][0]],
7349 vertex_indices[new_line_vertices[i][1]]});
7350 }
7351 break;
7352
7354 {
7355 // Directions so that middle tri looks like a 'normal'
7356 // refined tri (refined quads define outer lines)
7357 constexpr ::ndarray<unsigned int, 3, 2>
7358 new_line_vertices = {{{{15, 16}}, //
7359 {{16, 17}}, //
7360 {{15, 17}}}};
7361
7362 for (unsigned int i = 0; i < n_new_lines; ++i)
7363 new_lines[i]->set_bounding_object_indices(
7364 {vertex_indices[new_line_vertices[i][0]],
7365 vertex_indices[new_line_vertices[i][1]]});
7366 }
7367 break;
7368
7370 {
7371 constexpr ::ndarray<unsigned int, 6, 2>
7372 new_line_vertices = {{{{22, 26}},
7373 {{26, 23}},
7374 {{20, 26}},
7375 {{26, 21}},
7376 {{24, 26}},
7377 {{26, 25}}}};
7378 for (unsigned int i = 0; i < n_new_lines; ++i)
7379 new_lines[i]->set_bounding_object_indices(
7380 {vertex_indices[new_line_vertices[i][0]],
7381 vertex_indices[new_line_vertices[i][1]]});
7382 }
7383 break;
7384
7385 default:
7387 }
7388
7389 // Get the corrected orientation of the child indices of
7390 // `child` for a refined face, given the `face_ref_cell_type`
7391 // and the `face_orientation` as stored in the cell it bounds.
7392 auto standard_to_real_quad_child_index =
7393 [](const unsigned int child,
7394 const types::geometric_orientation face_orientation,
7395 const ReferenceCell<dim - 1> face_ref_cell_type) {
7396 // The parent vertex indices correlate nicely with the
7397 // child indices of a tri and quad, as shown in the
7398 // drawing for 2D face refinement (see the curly brackets
7399 // tagged {} // FACES). We can thus apply the existing
7400 // algorithm for orientation correction of vertex indices
7401 // and reinterpret the output. The only problem is child 3
7402 // in triangles. However it is always in the center so no
7403 // correction is necessary at all.
7404 switch (face_ref_cell_type)
7405 {
7407 // A complicated way to query the private attribute
7408 // `ReferenceCell::triangle_vertex_permutations[face_orientation][vertex]`
7409 if (child != 3)
7412 0,
7413 face_orientation);
7414 else
7415 return 3u;
7416
7418 // `ReferenceCell::quadrilateral_vertex_permutations[face_orientation][vertex]`.
7421 0,
7422 face_orientation);
7423 default:
7425 }
7426 };
7427
7428 // set up new faces
7429 {
7430 // Similar to `vertex_indices` above the `relevant_lines`
7431 // are filled in multiple steps. The order is once again
7432 // determined by the reference cell and the refinement
7433 // algorithms used by the faces. (For Tetrahedron
7434 // `chosen_line_tetrahedron` is also relevant).
7435 // 1. Get the lines from the faces that are Quadrilaterals.
7436 //
7437 // .- -.- -.
7438 // : 1 :
7439 // .-2-.-3-.
7440 // : 0 :
7441 // .- - - -. n: extracted lines
7442 //
7443 // 2. Get the lines from the faces that are Triangles.
7444 //
7445 // | \ .
7446 // *--1--* .
7447 // |\ |\ .
7448 // | 2 0 \ .
7449 // | \| .
7450 // *-----*--- .
7451 //
7452 // 3. Newly created lines (see above)
7453 // 4. Load indices for the extracted lines
7454 //
7455 // Number of meaningful entries in this list is
7456 // 13 Tetrahedron 21 Wedge
7457 // 20 Pyramid 30 Hexahedron
7458 // In case the maximum changes, edit `max_relevant_lines` a
7459 // few lines above (or in case it was moved to
7460 // ReferenceCell, update it there).
7461
7462 std::array<raw_line_iterator, max_relevant_lines>
7463 relevant_lines;
7464 std::array<int, max_relevant_lines> relevant_line_indices;
7465 unsigned int relevant_lines_counter = 0;
7466 // 1. Get relevant lines from quads
7467 for (auto f : cell_reference_cell.face_indices_by_type(
7469 {
7470 // To retrieve the newly created lines within a quad, it
7471 // is sufficient to query child 0 and 3 (or 1 and 2), as
7472 // they border all relevant lines. Specifically, we are
7473 // interested in lines 1 and 3 of child 0, and lines
7474 // 0 and 2 of child 3. This is currently implemented in
7475 // `quad_relevant_children_and_lines` below (where the
7476 // first index is the child and the second is the
7477 // child's line index). A more readable implementation
7478 // is provided right below. However, it cannot be
7479 // (nicely) used to mimic the existing table's behavior.
7480 // Modifications to this behavior would result in
7481 // extensive rewriting of tables in `ReferenceCell`.
7482 //
7483 // constexpr std::
7484 // pair<unsigned int, std::array<unsigned int, 2>>
7485 // quad_relevant_children_and_lines = {{0, {1, 3}},
7486 // {3, {0, 2}}};
7487 constexpr ::ndarray<unsigned int, 4, 2>
7488 quad_relevant_children_and_lines = {{{{0, 1}}, //
7489 {{3, 0}}, //
7490 {{0, 3}}, //
7491 {{3, 2}}}};
7492 for (unsigned int l = 0; l < 4;
7493 ++l, ++relevant_lines_counter)
7494 {
7495 // Use previously defined helper function to find
7496 // children in an orientation-corrected way.
7497 const unsigned int relevant_child =
7498 standard_to_real_quad_child_index(
7499 quad_relevant_children_and_lines[l][0],
7500 cell->combined_face_orientation(f),
7502
7503 // Get the orientation corrected line index of the
7504 // child while using the fact that quad children
7505 // share their physical orientation with the parent.
7506 const unsigned int relevant_child_line =
7508 .standard_to_real_face_line(
7509 quad_relevant_children_and_lines[l][1],
7510 // face irrelevant -> function doesn't use it.
7511 0,
7512 cell->combined_face_orientation(f));
7513
7514
7515 // extract and store line
7516 relevant_lines[relevant_lines_counter] =
7517 cell->face(f)
7518 ->isotropic_child(relevant_child)
7519 ->line(relevant_child_line);
7520 }
7521 }
7522
7523 // 2. Get lines from tris
7524 for (auto f : cell_reference_cell.face_indices_by_type(
7526 {
7527 for (unsigned int l = 0; l < 3;
7528 ++l, ++relevant_lines_counter)
7529 {
7530 // Permutations of reference cell indices against
7531 // real world indices given the real world
7532 // orientation of the face.
7533 const std::array<std::array<unsigned int, 3>, 6>
7534 // Extract newly created lines surrounding the
7535 // center child (child 3) of the refined
7536 // triangular faces in a predictable manner (i.e.,
7537 // the lines always appear at the same location
7538 // within the to be refined 3d reference cell),
7539 // the orientation of the face must be considered.
7540 // This orientation correction is implemented via
7541 // the table below relating the lines of the
7542 // oriented face to their counterparts on the
7543 // reference cell face.
7544 tri_line_perm = {{{{0, 1, 2}}, // 0
7545 {{1, 0, 2}},
7546 {{2, 0, 1}}, // 2
7547 {{0, 2, 1}},
7548 {{1, 2, 0}}, // 4
7549 {{2, 1, 0}}}};
7550
7551 const auto combined_orientation =
7552 cell->combined_face_orientation(f);
7553 relevant_lines[relevant_lines_counter] =
7554 cell->face(f)
7555 ->child(3 /*center triangle*/)
7556 ->line(tri_line_perm[combined_orientation][l]);
7557 }
7558 }
7559
7560 // 3. Fill end of `relevant_lines` with `new_lines`.
7561 for (unsigned int i = 0; i < n_new_lines;
7562 ++i, ++relevant_lines_counter)
7563 relevant_lines[relevant_lines_counter] = new_lines[i];
7564
7565
7566 // 4. Extract and store indices of the relevant lines.
7567 for (unsigned int i = 0; i < relevant_lines_counter; ++i)
7568 relevant_line_indices[i] = relevant_lines[i]->index();
7569
7570
7571 // New faces (internal to the parent) are required for the
7572 // creation of children. The lines bounding these new faces
7573 // are stored in `relevant_lines`. The exact assignment of
7574 // these lines is then determined using the lookup table
7575 // retrieved below, by providing the appropriate indices
7576 // into `relevant_lines`.
7577 const auto &new_face_lines =
7578 cell_reference_cell.new_isotropic_child_face_lines(
7579 chosen_line_tetrahedron);
7580
7581 // The created lines might not be oriented according to the
7582 // expectation of the face's reference cell. Consequently,
7583 // an additional lookup table is necessary to define the
7584 // correct line connectivity desired by the reference cell.
7585 // This is very similar to the refinement of triangles in 2d
7586 // where the same problem occurred.
7587 const auto &new_face_lines_vert =
7588 cell_reference_cell
7589 .new_isotropic_child_face_line_vertices(
7590 chosen_line_tetrahedron);
7591
7592 // When fixing the orientation of lines for hexes the
7593 // calculated orientation of one line can be used for some
7594 // other lines as well. This connection is described in this
7595 // table.
7596 constexpr ::ndarray<unsigned int, 4, 2>
7597 representative_lines{{{{0, 2}}, //
7598 {{2, 0}}, //
7599 {{3, 3}}, //
7600 {{1, 1}}}};
7601
7602 for (unsigned int q = 0; q < n_new_faces; ++q)
7603 {
7604 auto &new_face = new_faces[q];
7605
7606 if (new_face_lines[q][3] == X)
7607 {
7608 // Set the face type implicitly, based on whether
7609 // the fourth line is `X`.
7610 triangulation.faces->set_quad_type(
7611 new_face->index(), ReferenceCells::Triangle);
7612
7613 new_face->set_bounding_object_indices(
7614 {relevant_line_indices[new_face_lines[q][0]],
7615 relevant_line_indices[new_face_lines[q][1]],
7616 relevant_line_indices[new_face_lines[q][2]]});
7617 }
7618 else
7619 {
7620 triangulation.faces->set_quad_type(
7621 new_face->index(), ReferenceCells::Quadrilateral);
7622
7623 new_face->set_bounding_object_indices(
7624 {relevant_line_indices[new_face_lines[q][0]],
7625 relevant_line_indices[new_face_lines[q][1]],
7626 relevant_line_indices[new_face_lines[q][2]],
7627 relevant_line_indices[new_face_lines[q][3]]});
7628 }
7629
7630 // On hexes, we must only determine a single line
7631 // according to the representative_lines array above
7632 // (this saves expensive operations), for tets we do
7633 // all lines manually
7634 const unsigned int n_compute_lines =
7635 cell_reference_cell == ReferenceCells::Hexahedron ?
7636 1 :
7637 new_face->n_lines();
7638 for (unsigned int line = 0; line < n_compute_lines;
7639 ++line)
7640 {
7641 const unsigned int l =
7642 (cell_reference_cell ==
7644 representative_lines[q % 4][0] :
7645 line;
7646
7647 const std::array<unsigned int, 2> vertices_0 = {
7648 {relevant_lines[new_face_lines[q][l]]
7649 ->vertex_index(0),
7650 relevant_lines[new_face_lines[q][l]]
7651 ->vertex_index(1)}};
7652
7653 const std::array<unsigned int, 2> vertices_1 = {
7654 {vertex_indices[new_face_lines_vert[q][l][0]],
7655 vertex_indices[new_face_lines_vert[q][l][1]]}};
7656
7657 const auto orientation =
7658 ReferenceCells::Line.get_combined_orientation(
7659 make_array_view(vertices_0),
7660 make_array_view(vertices_1));
7661
7662 new_face->set_line_orientation(l, orientation);
7663
7664 // on a hex, inject the status of the current line
7665 // also to the line on the other quad along the
7666 // same direction
7667 if (cell_reference_cell ==
7669 new_faces[representative_lines[q % 4][1] + q -
7670 (q % 4)]
7671 ->set_line_orientation(l, orientation);
7672 }
7673 }
7674 }
7675
7676 // set up new cell
7677 {
7678 // Similar to the steps before we now use an algorithm to
7679 // extract all the faces.
7680 // 1. Add newly created faces to the beginning.
7681 // 2. Get children of refined quad faces.
7682 // for numbering see {} // FACE.
7683 // 3. Get children of refined tri faces.
7684 // for numbering see {} // FACE.
7685 //
7686 // Number of meaningful entries in this list is
7687 // 24 Tetrahedron 30 Wedge
7688 // 33 Pyramid 36 Hexahedron
7689 // In case the maximum changes, edit `max_face_indices` a
7690 // few lines above (or in case it was moved to
7691 // ReferenceCell, update it there).
7692
7693 std::array<int, max_face_indices> face_indices;
7694
7695 unsigned int face_indices_counter = 0;
7696
7697 // 1. Get new face's ids.
7698 for (; face_indices_counter < n_new_faces;
7699 ++face_indices_counter)
7700 face_indices[face_indices_counter] =
7701 new_faces[face_indices_counter]->index();
7702
7703 // 2. Now the faces of the parent's refined quads.
7704 for (auto f_q : cell_reference_cell.face_indices_by_type(
7706 {
7707 for (unsigned int c = 0; c < 4;
7708 ++c, ++face_indices_counter)
7709 {
7710 const auto combined_orientation =
7711 cell->combined_face_orientation(f_q);
7712
7713 // Correct once again for orientation.
7714 face_indices[face_indices_counter] =
7715 cell->face(f_q)->isotropic_child_index(
7716 standard_to_real_quad_child_index(
7717 c,
7718 combined_orientation,
7720 }
7721 }
7722
7723 // 3. Now the faces of the parent's refined tris
7724 for (auto f_t : cell_reference_cell.face_indices_by_type(
7726 {
7727 for (unsigned int c = 0; c < 4;
7728 ++c, ++face_indices_counter)
7729 {
7730 const auto combined_orientation =
7731 cell->combined_face_orientation(f_t);
7732
7733 // Correct once again for orientation.
7734 face_indices[face_indices_counter] =
7735 cell->face(f_t)->child_index(
7736 standard_to_real_quad_child_index(
7737 c,
7738 combined_orientation,
7740 }
7741 }
7742
7743 // Similar to the faces described above, we need to identify
7744 // which faces (specified by their indices in
7745 // `face_indices`) bound the new cells. This information is
7746 // stored in the ReferenceCell and retrieved here.
7747 const auto cell_faces =
7748 cell_reference_cell.new_isotropic_child_cell_faces(
7749 chosen_line_tetrahedron);
7750
7751 // We also need to account for potential orientation
7752 // mismatches between the face and the cell's ReferenceCell.
7753 // (See the discussion above in new face creation for more
7754 // details.)
7755 const auto new_cells_vertices =
7756 cell_reference_cell.new_isotropic_child_cell_vertices(
7757 chosen_line_tetrahedron);
7758
7759 // 1. Preserve data that can only be extracted from active
7760 // cells.
7761 // Parent becomes inactive after setting the first child!
7762 const ::types::subdomain_id cell_subdomain_id =
7763 cell->subdomain_id();
7764
7765 // Create the new cells
7766 std::array<
7768 max_n_new_children>
7769 new_cells;
7770 for (unsigned int c = 0; c < n_new_cells; ++c)
7771 {
7772 // Since we search for pairs of hexes (next_free_hex
7773 // returns a pair) we need to search only every other
7774 // time.
7775 if (c % 2 == 0)
7776 next_unused_cell =
7777 triangulation.levels[level + 1]
7778 ->cells.next_free_hex(triangulation, level + 1);
7779 else
7780 ++next_unused_cell;
7781
7782 new_cells[c] = next_unused_cell;
7783
7784 auto &new_cell = new_cells[c];
7785
7786 AssertIsNotUsed(new_cell);
7787
7788 // 2. Copy parent data to child.
7789 new_cell->set_used_flag();
7790 new_cell->clear_user_flag();
7791 new_cell->clear_user_data();
7792 new_cell->clear_children();
7793 new_cell->set_material_id(cell->material_id());
7794 new_cell->set_manifold_id(cell->manifold_id());
7795 new_cell->set_subdomain_id(cell_subdomain_id);
7796
7797 // 3. Setup child parent relation (can only happen after
7798 // call to `set_used_flag()`)
7799 if (c % 2 == 0)
7800 {
7801 new_cell->set_parent(cell->index());
7802 cell->set_children(c, new_cell->index());
7803 }
7804
7805 // 4.a Determine the cell reference cell using the
7806 // number of vertices it has according to
7807 // `new_cells_vertices`.
7808 const ReferenceCell child_reference_cell =
7809 (new_cells_vertices[c][4] == X) ? ReferenceCells::Tetrahedron : // Tet
7810 (new_cells_vertices[c][5] == X) ? ReferenceCells::Pyramid : // Pyramid
7811 (new_cells_vertices[c][6] == X) ? ReferenceCells::Wedge : // Wedge
7813
7814 // 4.b Set the reference cell
7815 triangulation.levels[new_cell->level()]
7816 ->reference_cell[new_cell->index()] =
7817 child_reference_cell;
7818
7819 // 5. Set the bounding faces of the new cells
7820 // This seems to be the only option since
7821 // set_bounding_object_indices() takes an
7822 // std::initializer_list as argument
7823 switch (child_reference_cell)
7824 {
7826 new_cell->set_bounding_object_indices(
7827 {face_indices[cell_faces[c][0]],
7828 face_indices[cell_faces[c][1]],
7829 face_indices[cell_faces[c][2]],
7830 face_indices[cell_faces[c][3]]});
7831 break;
7832
7833 // Pyramids and Wedges share same number of faces
7836 new_cell->set_bounding_object_indices(
7837 {face_indices[cell_faces[c][0]],
7838 face_indices[cell_faces[c][1]],
7839 face_indices[cell_faces[c][2]],
7840 face_indices[cell_faces[c][3]],
7841 face_indices[cell_faces[c][4]]});
7842 break;
7843
7845 new_cell->set_bounding_object_indices(
7846 {face_indices[cell_faces[c][0]],
7847 face_indices[cell_faces[c][1]],
7848 face_indices[cell_faces[c][2]],
7849 face_indices[cell_faces[c][3]],
7850 face_indices[cell_faces[c][4]],
7851 face_indices[cell_faces[c][5]]});
7852 break;
7853
7854 default:
7856 }
7857
7858 // 6. Fix orientation of faces.
7859 // For all reference cells except for Hexes, we need to
7860 // go through the faces and figure the orientation out
7861 // the hard way
7862
7863 // Set the orientation flag to its default state for
7864 // all faces initially. later on go the other way
7865 // round and reset faces that are at the boundary of
7866 // the mother cube.
7867 // TODO: This might only be necessary for Hexes. For
7868 // all other cells the orientation is calculated for
7869 // all faces one by one. (Only a guess though).
7870 for (const auto f : new_cell->face_indices())
7871 new_cell->set_combined_face_orientation(
7873
7874 if (child_reference_cell != ReferenceCells::Hexahedron)
7875 {
7876 for (const auto f : new_cell->face_indices())
7877 {
7878 const auto &face = new_cell->face(f);
7879
7880 // load correct vertices of cell
7881 auto new_cell_vertices = new_cells_vertices[c];
7882
7883 // Load correct indices of vertices of face `f`
7884 std::array<unsigned int, 4> vertices_0,
7885 vertices_1;
7886 vertices_0.fill(numbers::invalid_unsigned_int);
7887 vertices_1.fill(numbers::invalid_unsigned_int);
7888
7889 for (unsigned int face_vertex_no :
7890 face->vertex_indices())
7891 {
7892 // Calculate index for vertex
7893 // `face_vertex_no` of face `f` as an index
7894 // in the cells reference cells indices.
7895 const auto cell_vertex_no =
7896 child_reference_cell
7898 f,
7899 face_vertex_no,
7900 numbers::
7901 default_geometric_orientation);
7902
7903 // Get according index from
7904 // `vertex_indices`. Use `cell_vertex_no` as
7905 // the index in the table describing which
7906 // vertices belong to which cell and then
7907 // get that index. Use `cell_vertex_no` to
7908 // look up the specific vertex (more
7909 // precisely the index in `vertex_indices`)
7910 // within the cell's connectivity table
7911 // `new_cell_vertices` and retrieve the
7912 // corresponding vertex (index) from
7913 // `vertex_indices`.
7914 vertices_0[face_vertex_no] = vertex_indices
7915 [new_cell_vertices[cell_vertex_no]];
7916 }
7917
7918 // max 4 vertices (if face is quad)
7919 for (const auto i : face->vertex_indices())
7920 vertices_1[i] = face->vertex_index(i);
7921
7922 // Calculate combined orientation as permutation
7923 // of desired face vertex indices an actual
7924 // vertex indices of the face.
7925 new_cell->set_combined_face_orientation(
7926 f,
7927 face->reference_cell()
7928 .get_combined_orientation(
7929 make_array_view(vertices_0.cbegin(),
7930 vertices_0.cbegin() +
7931 face->n_vertices()),
7932 make_array_view(vertices_1.cbegin(),
7933 vertices_1.cbegin() +
7934 face->n_vertices())));
7935 }
7936 }
7937 }
7938
7939 // For hexes, we can simply inherit the orientation values
7940 // from the parent on the outer faces; the inner faces can
7941 // be skipped as their orientation is always the default
7942 // one set above.
7943 constexpr ::ndarray<unsigned int, 6, 4>
7944 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7945 {{1, 3, 5, 7}},
7946 {{0, 1, 4, 5}},
7947 {{2, 3, 6, 7}},
7948 {{0, 1, 2, 3}},
7949 {{4, 5, 6, 7}}}};
7950 if (cell_reference_cell == ReferenceCells::Hexahedron)
7951 for (const auto f : cell->face_indices())
7952 {
7953 const auto combined_orientation =
7954 cell->combined_face_orientation(f);
7955 for (unsigned int c = 0; c < 4; ++c)
7956 new_cells[face_to_child_indices_hex[f][c]]
7957 ->set_combined_face_orientation(
7958 f, combined_orientation);
7959 }
7960 }
7961 } // CREATE_CELLS
7962
7963 // Check for distorted children
7964 if (check_for_distorted_cells &&
7965 has_distorted_children<dim, spacedim>(cell))
7966 cells_with_distorted_children.distorted_cells.push_back(cell);
7967
7968 triangulation.signals.post_refinement_on_cell(cell);
7969 }
7970 }
7971
7972 triangulation.faces->quads.clear_user_data();
7973
7974 return cells_with_distorted_children;
7975 }
7976
7981 template <int spacedim>
7984 const bool check_for_distorted_cells)
7985 {
7986 const unsigned int dim = 3;
7987
7988 {
7989 bool flag_isotropic_mesh = true;
7991 cell = triangulation.begin(),
7992 endc = triangulation.end();
7993 for (; cell != endc; ++cell)
7994 if (cell->used())
7995 if (triangulation.get_anisotropic_refinement_flag() ||
7996 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7997 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7998 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7999 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
8000 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
8001 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
8002 {
8003 flag_isotropic_mesh = false;
8004 break;
8005 }
8006
8007 if (flag_isotropic_mesh)
8008 return execute_refinement_isotropic(triangulation,
8009 check_for_distorted_cells);
8010 }
8011
8012 // this function probably also works for spacedim>3 but it
8013 // isn't tested. it will probably be necessary to pull new
8014 // vertices onto the manifold just as we do for the other
8015 // functions above.
8016 Assert(spacedim == 3, ExcNotImplemented());
8017
8018 // Check whether a new level is needed. We have to check for
8019 // this on the highest level only
8020 for (const auto &cell : triangulation.active_cell_iterators_on_level(
8021 triangulation.levels.size() - 1))
8022 if (cell->refine_flag_set())
8023 {
8025 triangulation.levels.size() < numbers::max_n_levels,
8027 triangulation.levels.push_back(
8028 std::make_unique<internal::TriangulationImplementation::
8030 triangulation.strides.max_children_per_cell,
8031 triangulation.strides.max_faces_per_cell,
8032 triangulation.strides.max_vertices_per_cell));
8033 break;
8034 }
8035
8036
8037 // first clear user flags for quads and lines; we're going to
8038 // use them to flag which lines and quads need refinement
8039 triangulation.faces->quads.clear_user_data();
8040
8042 triangulation.begin_line();
8043 line != triangulation.end_line();
8044 ++line)
8045 line->clear_user_flag();
8047 triangulation.begin_quad();
8048 quad != triangulation.end_quad();
8049 ++quad)
8050 quad->clear_user_flag();
8051
8052 // create an array of face refine cases. User indices of faces
8053 // will be set to values corresponding with indices in this
8054 // array.
8055 const RefinementCase<dim - 1> face_refinement_cases[4] = {
8056 RefinementCase<dim - 1>::no_refinement,
8057 RefinementCase<dim - 1>::cut_x,
8058 RefinementCase<dim - 1>::cut_y,
8059 RefinementCase<dim - 1>::cut_xy};
8060
8061 // check how much space is needed on every level. We need not
8062 // check the highest level since either
8063 // - on the highest level no cells are flagged for refinement
8064 // - there are, but prepare_refinement added another empty
8065 // level which then is the highest level
8066
8067 // variables to hold the number of newly to be created
8068 // vertices, lines and quads. as these are stored globally,
8069 // declare them outside the loop over al levels. we need lines
8070 // and quads in pairs for refinement of old ones and lines and
8071 // quads, that can be stored as single ones, as they are newly
8072 // created in the inside of an existing cell
8073 unsigned int needed_vertices = 0;
8074 unsigned int needed_lines_single = 0;
8075 unsigned int needed_quads_single = 0;
8076 unsigned int needed_lines_pair = 0;
8077 unsigned int needed_quads_pair = 0;
8078 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
8079 --level_no)
8080 {
8081 // count number of flagged cells on this level and compute
8082 // how many new vertices and new lines will be needed
8083 std::size_t needed_cells = 0;
8084
8085 for (const auto &acell :
8086 triangulation.active_cell_iterators_on_level(level_no))
8087 if (acell->refine_flag_set())
8088 {
8089 RefinementCase<dim> ref_case = acell->refine_flag_set();
8090
8091 // now for interior vertices, lines and quads, which
8092 // are needed in any case
8093 if (ref_case == RefinementCase<dim>::cut_x ||
8094 ref_case == RefinementCase<dim>::cut_y ||
8095 ref_case == RefinementCase<dim>::cut_z)
8096 {
8097 ++needed_quads_single;
8098 needed_cells += 2;
8099 triangulation.anisotropic_refinement = true;
8100 }
8101 else if (ref_case == RefinementCase<dim>::cut_xy ||
8102 ref_case == RefinementCase<dim>::cut_xz ||
8103 ref_case == RefinementCase<dim>::cut_yz)
8104 {
8105 ++needed_lines_single;
8106 needed_quads_single += 4;
8107 needed_cells += 4;
8108 triangulation.anisotropic_refinement = true;
8109 }
8110 else if (ref_case == RefinementCase<dim>::cut_xyz)
8111 {
8112 ++needed_vertices;
8113 needed_lines_single += 6;
8114 needed_quads_single += 12;
8115 needed_cells += 8;
8116 }
8117 else
8118 {
8119 // we should never get here
8121 }
8122
8123 // mark all faces for refinement; checking locally
8124 // if and how the neighbor would like to refine
8125 // these is difficult so we only flag them and after
8126 // visiting all cells, we decide which faces need
8127 // which refinement;
8128 for (const unsigned int face :
8130 {
8132 aface = acell->face(face);
8133 // get the RefineCase this faces has for the
8134 // given RefineCase of the cell
8135 RefinementCase<dim - 1> face_ref_case =
8137 ref_case,
8138 face,
8139 acell->face_orientation(face),
8140 acell->face_flip(face),
8141 acell->face_rotation(face));
8142 // only do something, if this face has to be
8143 // refined
8144 if (face_ref_case)
8145 {
8146 if (face_ref_case ==
8148 {
8149 if (aface->n_active_descendants() < 4)
8150 // we use user_flags to denote needed
8151 // isotropic refinement
8152 aface->set_user_flag();
8153 }
8154 else if (aface->refinement_case() != face_ref_case)
8155 // we use user_indices to denote needed
8156 // anisotropic refinement. note, that we
8157 // can have at most one anisotropic
8158 // refinement case for this face, as
8159 // otherwise prepare_refinement() would
8160 // have changed one of the cells to yield
8161 // isotropic refinement at this
8162 // face. therefore we set the user_index
8163 // uniquely
8164 {
8165 Assert(aface->refinement_case() ==
8167 dim - 1>::isotropic_refinement ||
8168 aface->refinement_case() ==
8171 aface->set_user_index(face_ref_case);
8172 }
8173 }
8174 } // for all faces
8175
8176 // flag all lines, that have to be refined
8177 for (unsigned int line = 0;
8178 line < GeometryInfo<dim>::lines_per_cell;
8179 ++line)
8181 line) &&
8182 !acell->line(line)->has_children())
8183 acell->line(line)->set_user_flag();
8184
8185 } // if refine_flag set and for all cells on this level
8186
8187 // count number of used cells on the next higher level
8188 auto &next_level = *triangulation.levels[level_no + 1];
8189 const auto used_cells = std::count(next_level.cells.used.begin(),
8190 next_level.cells.used.end(),
8191 true);
8192 if (used_cells + needed_cells > next_level.size())
8193 next_level.allocate_end(
8194 (used_cells + needed_cells) - next_level.size(),
8195 // We unconditionally store the orientation in 3d
8196 true,
8197 // TODO: we can get rid of this check (i.e., we don't need to
8198 // store this value for purely wedge meshes). This will be
8199 // simpler to do once we merge IsotropicRefinementChoice and
8200 // RefinementCase.
8201 !triangulation.all_reference_cells_are_hyper_cube());
8202
8203 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
8204 next_level.cells.allocate_end(needed_cells, 0);
8205 } // for all levels
8206 // now count the quads and lines which were flagged for
8207 // refinement
8209 triangulation.begin_quad();
8210 quad != triangulation.end_quad();
8211 ++quad)
8212 {
8213 if (quad->user_flag_set())
8214 {
8215 // isotropic refinement: 1 interior vertex, 4 quads
8216 // and 4 interior lines. we store the interior lines
8217 // in pairs in case the face is already or will be
8218 // refined anisotropically
8219 needed_quads_pair += 4;
8220 needed_lines_pair += 4;
8221 needed_vertices += 1;
8222 }
8223 if (quad->user_index())
8224 {
8225 // anisotropic refinement: 1 interior
8226 // line and two quads
8227 needed_quads_pair += 2;
8228 needed_lines_single += 1;
8229 // there is a kind of complicated situation here which
8230 // requires our attention. if the quad is refined
8231 // isotropcally, two of the interior lines will get a
8232 // new mother line - the interior line of our
8233 // anisotropically refined quad. if those two lines
8234 // are not consecutive, we cannot do so and have to
8235 // replace them by two lines that are consecutive. we
8236 // try to avoid that situation, but it may happen
8237 // nevertheless through repeated refinement and
8238 // coarsening. thus we have to check here, as we will
8239 // need some additional space to store those new lines
8240 // in case we need them...
8241 if (quad->has_children())
8242 {
8243 Assert(quad->refinement_case() ==
8246 if ((face_refinement_cases[quad->user_index()] ==
8248 (quad->child(0)->line_index(1) + 1 !=
8249 quad->child(2)->line_index(1))) ||
8250 (face_refinement_cases[quad->user_index()] ==
8252 (quad->child(0)->line_index(3) + 1 !=
8253 quad->child(1)->line_index(3))))
8254 needed_lines_pair += 2;
8255 }
8256 }
8257 }
8258
8260 triangulation.begin_line();
8261 line != triangulation.end_line();
8262 ++line)
8263 if (line->user_flag_set())
8264 {
8265 needed_lines_pair += 2;
8266 needed_vertices += 1;
8267 }
8268
8269 // reserve space for needed_lines new lines stored in pairs
8270 triangulation.faces->lines.allocate_end(needed_lines_pair,
8271 needed_lines_single);
8272
8273 // reserve space for needed_quads new quads stored in pairs
8274 triangulation.faces->allocate_end(needed_quads_pair,
8275 needed_quads_single);
8276
8277 // add to needed vertices how many vertices are already in use
8278 needed_vertices += std::count(triangulation.vertices_used.begin(),
8279 triangulation.vertices_used.end(),
8280 true);
8281 // if we need more vertices: create them, if not: leave the
8282 // array as is, since shrinking is not really possible because
8283 // some of the vertices at the end may be in use
8284 if (needed_vertices > triangulation.vertices.size())
8285 {
8286 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
8287 triangulation.vertices_used.resize(needed_vertices, false);
8288 }
8289
8290
8291 //-----------------------------------------
8292 // Before we start with the actual refinement, we do some
8293 // sanity checks if in debug mode. especially, we try to catch
8294 // the notorious problem with lines being twice refined,
8295 // i.e. there are cells adjacent at one line ("around the
8296 // edge", but not at a face), with two cells differing by more
8297 // than one refinement level
8298 //
8299 // this check is very simple to implement here, since we have
8300 // all lines flagged if they shall be refined
8301 if constexpr (running_in_debug_mode())
8302 {
8303 for (const auto &cell : triangulation.active_cell_iterators())
8304 if (!cell->refine_flag_set())
8305 for (unsigned int line = 0;
8306 line < GeometryInfo<dim>::lines_per_cell;
8307 ++line)
8308 if (cell->line(line)->has_children())
8309 for (unsigned int c = 0; c < 2; ++c)
8310 Assert(cell->line(line)->child(c)->user_flag_set() ==
8311 false,
8313 }
8314
8315 //-----------------------------------------
8316 // Do refinement on every level
8317 //
8318 // To make life a bit easier, we first refine those lines and
8319 // quads that were flagged for refinement and then compose the
8320 // newly to be created cells.
8321 //
8322 // index of next unused vertex
8323 unsigned int next_unused_vertex = 0;
8324
8325 // first for lines
8326 {
8327 // only active objects can be refined further
8329 line = triangulation.begin_active_line(),
8330 endl = triangulation.end_line();
8332 next_unused_line = triangulation.begin_raw_line();
8333
8334 for (; line != endl; ++line)
8335 if (line->user_flag_set())
8336 {
8337 // this line needs to be refined
8338
8339 // find the next unused vertex and set it
8340 // appropriately
8341 while (triangulation.vertices_used[next_unused_vertex] == true)
8342 ++next_unused_vertex;
8343 Assert(
8344 next_unused_vertex < triangulation.vertices.size(),
8345 ExcMessage(
8346 "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."));
8347 triangulation.vertices_used[next_unused_vertex] = true;
8348
8349 triangulation.vertices[next_unused_vertex] = line->center(true);
8350
8351 // now that we created the right point, make up the
8352 // two child lines (++ takes care of the end of the
8353 // vector)
8354 next_unused_line =
8355 triangulation.faces->lines.template next_free_pair_object<1>(
8356 triangulation);
8357 Assert(next_unused_line.state() == IteratorState::valid,
8359
8360 // now we found two consecutive unused lines, such
8361 // that the children of a line will be consecutive.
8362 // then set the child pointer of the present line
8363 line->set_children(0, next_unused_line->index());
8364
8365 // set the two new lines
8367 children[2] = {next_unused_line, ++next_unused_line};
8368
8369 // some tests; if any of the iterators should be
8370 // invalid, then already dereferencing will fail
8371 AssertIsNotUsed(children[0]);
8372 AssertIsNotUsed(children[1]);
8373
8374 children[0]->set_bounding_object_indices(
8375 {line->vertex_index(0), next_unused_vertex});
8376 children[1]->set_bounding_object_indices(
8377 {next_unused_vertex, line->vertex_index(1)});
8378
8379 children[0]->set_used_flag();
8380 children[1]->set_used_flag();
8381 children[0]->clear_children();
8382 children[1]->clear_children();
8383 children[0]->clear_user_data();
8384 children[1]->clear_user_data();
8385 children[0]->clear_user_flag();
8386 children[1]->clear_user_flag();
8387
8388 children[0]->set_boundary_id_internal(line->boundary_id());
8389 children[1]->set_boundary_id_internal(line->boundary_id());
8390
8391 children[0]->set_manifold_id(line->manifold_id());
8392 children[1]->set_manifold_id(line->manifold_id());
8393
8394 // finally clear flag
8395 // indicating the need
8396 // for refinement
8397 line->clear_user_flag();
8398 }
8399 }
8400
8401
8402 //-------------------------------------
8403 // now refine marked quads
8404 //-------------------------------------
8405
8406 // here we encounter several cases:
8407
8408 // a) the quad is unrefined and shall be refined isotropically
8409
8410 // b) the quad is unrefined and shall be refined
8411 // anisotropically
8412
8413 // c) the quad is unrefined and shall be refined both
8414 // anisotropically and isotropically (this is reduced to case
8415 // b) and then case b) for the children again)
8416
8417 // d) the quad is refined anisotropically and shall be refined
8418 // isotropically (this is reduced to case b) for the
8419 // anisotropic children)
8420
8421 // e) the quad is refined isotropically and shall be refined
8422 // anisotropically (this is transformed to case c), however we
8423 // might have to renumber/rename children...)
8424
8425 // we need a loop in cases c) and d), as the anisotropic
8426 // children might have a lower index than the mother quad
8427 for (unsigned int loop = 0; loop < 2; ++loop)
8428 {
8429 // usually, only active objects can be refined
8430 // further. however, in cases d) and e) that is not true,
8431 // so we have to use 'normal' iterators here
8433 quad = triangulation.begin_quad(),
8434 endq = triangulation.end_quad();
8436 next_unused_line = triangulation.begin_raw_line();
8438 next_unused_quad = triangulation.begin_raw_quad();
8439
8440 for (; quad != endq; ++quad)
8441 {
8442 if (quad->user_index())
8443 {
8444 RefinementCase<dim - 1> aniso_quad_ref_case =
8445 face_refinement_cases[quad->user_index()];
8446 // there is one unlikely event here, where we
8447 // already have refind the face: if the face was
8448 // refined anisotropically and we want to refine
8449 // it isotropically, both children are flagged for
8450 // anisotropic refinement. however, if those
8451 // children were already flagged for anisotropic
8452 // refinement, they might already be processed and
8453 // refined.
8454 if (aniso_quad_ref_case == quad->refinement_case())
8455 continue;
8456
8457 Assert(quad->refinement_case() ==
8459 quad->refinement_case() ==
8462
8463 // this quad needs to be refined anisotropically
8464 Assert(quad->user_index() ==
8466 quad->user_index() ==
8469
8470 // make the new line interior to the quad
8472 new_line;
8473
8474 new_line =
8475 triangulation.faces->lines
8476 .template next_free_single_object<1>(triangulation);
8477 AssertIsNotUsed(new_line);
8478
8479 // first collect the
8480 // indices of the vertices:
8481 // *--1--*
8482 // | | |
8483 // | | | cut_x
8484 // | | |
8485 // *--0--*
8486 //
8487 // *-----*
8488 // | |
8489 // 0-----1 cut_y
8490 // | |
8491 // *-----*
8492 unsigned int vertex_indices[2];
8493 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8494 {
8495 vertex_indices[0] =
8496 quad->line(2)->child(0)->vertex_index(1);
8497 vertex_indices[1] =
8498 quad->line(3)->child(0)->vertex_index(1);
8499 }
8500 else
8501 {
8502 vertex_indices[0] =
8503 quad->line(0)->child(0)->vertex_index(1);
8504 vertex_indices[1] =
8505 quad->line(1)->child(0)->vertex_index(1);
8506 }
8507
8508 new_line->set_bounding_object_indices(
8510 new_line->set_used_flag();
8511 new_line->clear_user_flag();
8512 new_line->clear_user_data();
8513 new_line->clear_children();
8514 new_line->set_boundary_id_internal(quad->boundary_id());
8515 new_line->set_manifold_id(quad->manifold_id());
8516
8517 // find some space (consecutive) for the two newly
8518 // to be created quads.
8520 new_quads[2];
8521
8522 next_unused_quad =
8523 triangulation.faces->quads
8524 .template next_free_pair_object<2>(triangulation);
8525 new_quads[0] = next_unused_quad;
8526 AssertIsNotUsed(new_quads[0]);
8527
8528 ++next_unused_quad;
8529 new_quads[1] = next_unused_quad;
8530 AssertIsNotUsed(new_quads[1]);
8531
8532 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8533 {
8534 new_quads[0]->set_bounding_object_indices(
8535 {static_cast<int>(quad->line_index(0)),
8536 new_line->index(),
8537 quad->line(2)
8538 ->child(
8539 child_line_index(0, quad->line_orientation(2)))
8540 ->index(),
8541 quad->line(3)
8542 ->child(
8543 child_line_index(0, quad->line_orientation(3)))
8544 ->index()});
8545 new_quads[1]->set_bounding_object_indices(
8546 {new_line->index(),
8547 static_cast<int>(quad->line_index(1)),
8548 quad->line(2)
8549 ->child(
8550 child_line_index(1, quad->line_orientation(2)))
8551 ->index(),
8552 quad->line(3)
8553 ->child(
8554 child_line_index(1, quad->line_orientation(3)))
8555 ->index()});
8556 }
8557 else
8558 {
8559 new_quads[0]->set_bounding_object_indices(
8560 {quad->line(0)
8561 ->child(
8562 child_line_index(0, quad->line_orientation(0)))
8563 ->index(),
8564 quad->line(1)
8565 ->child(
8566 child_line_index(0, quad->line_orientation(1)))
8567 ->index(),
8568 static_cast<int>(quad->line_index(2)),
8569 new_line->index()});
8570 new_quads[1]->set_bounding_object_indices(
8571 {quad->line(0)
8572 ->child(
8573 child_line_index(1, quad->line_orientation(0)))
8574 ->index(),
8575 quad->line(1)
8576 ->child(
8577 child_line_index(1, quad->line_orientation(1)))
8578 ->index(),
8579 new_line->index(),
8580 static_cast<int>(quad->line_index(3))});
8581 }
8582
8583 for (const auto &new_quad : new_quads)
8584 {
8585 new_quad->set_used_flag();
8586 new_quad->clear_user_flag();
8587 new_quad->clear_user_data();
8588 new_quad->clear_children();
8589 new_quad->set_boundary_id_internal(quad->boundary_id());
8590 new_quad->set_manifold_id(quad->manifold_id());
8591 // set all line orientations to true, change
8592 // this after the loop, as we have to consider
8593 // different lines for each child
8594 for (unsigned int j = 0;
8595 j < GeometryInfo<dim>::lines_per_face;
8596 ++j)
8597 new_quad->set_line_orientation(
8599 }
8600 // now set the line orientation of children of
8601 // outer lines correctly, the lines in the
8602 // interior of the refined quad are automatically
8603 // oriented conforming to the standard
8604 new_quads[0]->set_line_orientation(
8605 0, quad->line_orientation(0));
8606 new_quads[0]->set_line_orientation(
8607 2, quad->line_orientation(2));
8608 new_quads[1]->set_line_orientation(
8609 1, quad->line_orientation(1));
8610 new_quads[1]->set_line_orientation(
8611 3, quad->line_orientation(3));
8612 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8613 {
8614 new_quads[0]->set_line_orientation(
8615 3, quad->line_orientation(3));
8616 new_quads[1]->set_line_orientation(
8617 2, quad->line_orientation(2));
8618 }
8619 else
8620 {
8621 new_quads[0]->set_line_orientation(
8622 1, quad->line_orientation(1));
8623 new_quads[1]->set_line_orientation(
8624 0, quad->line_orientation(0));
8625 }
8626
8627 // test, whether this face is refined
8628 // isotropically already. if so, set the correct
8629 // children pointers.
8630 if (quad->refinement_case() ==
8631 RefinementCase<dim - 1>::cut_xy)
8632 {
8633 // we will put a new refinemnt level of
8634 // anisotropic refinement between the
8635 // unrefined and isotropically refined quad
8636 // ending up with the same fine quads but
8637 // introducing anisotropically refined ones as
8638 // children of the unrefined quad and mother
8639 // cells of the original fine ones.
8640
8641 // this process includes the creation of a new
8642 // middle line which we will assign as the
8643 // mother line of two of the existing inner
8644 // lines. If those inner lines are not
8645 // consecutive in memory, we won't find them
8646 // later on, so we have to create new ones
8647 // instead and replace all occurrences of the
8648 // old ones with those new ones. As this is
8649 // kind of ugly, we hope we don't have to do
8650 // it often...
8652 old_child[2];
8653 if (aniso_quad_ref_case ==
8655 {
8656 old_child[0] = quad->child(0)->line(1);
8657 old_child[1] = quad->child(2)->line(1);
8658 }
8659 else
8660 {
8661 Assert(aniso_quad_ref_case ==
8664
8665 old_child[0] = quad->child(0)->line(3);
8666 old_child[1] = quad->child(1)->line(3);
8667 }
8668
8669 if (old_child[0]->index() + 1 != old_child[1]->index())
8670 {
8671 // this is exactly the ugly case we talked
8672 // about. so, no complaining, lets get
8673 // two new lines and copy all info
8674 typename Triangulation<dim,
8675 spacedim>::raw_line_iterator
8676 new_child[2];
8677
8678 new_child[0] = new_child[1] =
8679 triangulation.faces->lines
8680 .template next_free_pair_object<1>(
8681 triangulation);
8682 ++new_child[1];
8683
8684 new_child[0]->set_used_flag();
8685 new_child[1]->set_used_flag();
8686
8687 const int old_index_0 = old_child[0]->index(),
8688 old_index_1 = old_child[1]->index(),
8689 new_index_0 = new_child[0]->index(),
8690 new_index_1 = new_child[1]->index();
8691
8692 // loop over all quads and replace the old
8693 // lines
8694 for (unsigned int q = 0;
8695 q < triangulation.faces->quads.n_objects();
8696 ++q)
8697 for (unsigned int l = 0;
8698 l < GeometryInfo<dim>::lines_per_face;
8699 ++l)
8700 {
8701 const int this_index =
8702 triangulation.faces->quads
8703 .get_bounding_object_indices(q)[l];
8704 if (this_index == old_index_0)
8705 triangulation.faces->quads
8706 .get_bounding_object_indices(q)[l] =
8707 new_index_0;
8708 else if (this_index == old_index_1)
8709 triangulation.faces->quads
8710 .get_bounding_object_indices(q)[l] =
8711 new_index_1;
8712 }
8713 // now we have to copy all information of
8714 // the two lines
8715 for (unsigned int i = 0; i < 2; ++i)
8716 {
8717 Assert(!old_child[i]->has_children(),
8719
8720 new_child[i]->set_bounding_object_indices(
8721 {old_child[i]->vertex_index(0),
8722 old_child[i]->vertex_index(1)});
8723 new_child[i]->set_boundary_id_internal(
8724 old_child[i]->boundary_id());
8725 new_child[i]->set_manifold_id(
8726 old_child[i]->manifold_id());
8727 new_child[i]->set_user_index(
8728 old_child[i]->user_index());
8729 if (old_child[i]->user_flag_set())
8730 new_child[i]->set_user_flag();
8731 else
8732 new_child[i]->clear_user_flag();
8733
8734 new_child[i]->clear_children();
8735
8736 old_child[i]->clear_user_flag();
8737 old_child[i]->clear_user_index();
8738 old_child[i]->clear_used_flag();
8739 }
8740 }
8741 // now that we cared about the lines, go on
8742 // with the quads themselves, where we might
8743 // encounter similar situations...
8744 if (aniso_quad_ref_case ==
8746 {
8747 new_line->set_children(
8748 0, quad->child(0)->line_index(1));
8749 Assert(new_line->child(1) ==
8750 quad->child(2)->line(1),
8752 // now evereything is quite
8753 // complicated. we have the children
8754 // numbered according to
8755 //
8756 // *---*---*
8757 // |n+2|n+3|
8758 // *---*---*
8759 // | n |n+1|
8760 // *---*---*
8761 //
8762 // from the original isotropic
8763 // refinement. we have to reorder them as
8764 //
8765 // *---*---*
8766 // |n+1|n+3|
8767 // *---*---*
8768 // | n |n+2|
8769 // *---*---*
8770 //
8771 // such that n and n+1 are consecutive
8772 // children of m and n+2 and n+3 are
8773 // consecutive children of m+1, where m
8774 // and m+1 are given as in
8775 //
8776 // *---*---*
8777 // | | |
8778 // | m |m+1|
8779 // | | |
8780 // *---*---*
8781 //
8782 // this is a bit ugly, of course: loop
8783 // over all cells on all levels and look
8784 // for faces n+1 (switch_1) and n+2
8785 // (switch_2).
8786 const typename Triangulation<dim, spacedim>::
8787 quad_iterator switch_1 = quad->child(1),
8788 switch_2 = quad->child(2);
8789 const int switch_1_index = switch_1->index();
8790 const int switch_2_index = switch_2->index();
8791 for (unsigned int l = 0;
8792 l < triangulation.levels.size();
8793 ++l)
8794 for (unsigned int h = 0;
8795 h <
8796 triangulation.levels[l]->cells.n_objects();
8797 ++h)
8798 for (const unsigned int q :
8800 {
8801 const int face_index =
8802 triangulation.levels[l]
8803 ->cells.get_bounding_object_indices(
8804 h)[q];
8805 if (face_index == switch_1_index)
8806 triangulation.levels[l]
8807 ->cells.get_bounding_object_indices(
8808 h)[q] = switch_2_index;
8809 else if (face_index == switch_2_index)
8810 triangulation.levels[l]
8811 ->cells.get_bounding_object_indices(
8812 h)[q] = switch_1_index;
8813 }
8814 // now we have to copy all information of
8815 // the two quads
8816 int switch_1_lines[4], switch_2_lines[4];
8817 for (int i = 0; i < 4; ++i)
8818 {
8819 switch_1_lines[i] = switch_1->line(i)->index();
8820 switch_2_lines[i] = switch_2->line(i)->index();
8821 }
8823 switch_1_line_orientations[4] = {
8824 switch_1->line_orientation(0),
8825 switch_1->line_orientation(1),
8826 switch_1->line_orientation(2),
8827 switch_1->line_orientation(3)};
8828 const types::boundary_id switch_1_boundary_id =
8829 switch_1->boundary_id();
8830 const unsigned int switch_1_user_index =
8831 switch_1->user_index();
8832 const bool switch_1_user_flag =
8833 switch_1->user_flag_set();
8834 const RefinementCase<dim - 1>
8835 switch_1_refinement_case =
8836 switch_1->refinement_case();
8837 const int switch_1_first_child_pair =
8838 (switch_1_refinement_case ?
8839 switch_1->child_index(0) :
8840 -1);
8841 const int switch_1_second_child_pair =
8842 (switch_1_refinement_case ==
8843 RefinementCase<dim - 1>::cut_xy ?
8844 switch_1->child_index(2) :
8845 -1);
8846
8847 switch_1->set_bounding_object_indices(
8848 {switch_2_lines[0],
8849 switch_2_lines[1],
8850 switch_2_lines[2],
8851 switch_2_lines[3]});
8852 switch_1->set_line_orientation(
8853 0, switch_2->line_orientation(0));
8854 switch_1->set_line_orientation(
8855 1, switch_2->line_orientation(1));
8856 switch_1->set_line_orientation(
8857 2, switch_2->line_orientation(2));
8858 switch_1->set_line_orientation(
8859 3, switch_2->line_orientation(3));
8860 switch_1->set_boundary_id_internal(
8861 switch_2->boundary_id());
8862 switch_1->set_manifold_id(switch_2->manifold_id());
8863 switch_1->set_user_index(switch_2->user_index());
8864 if (switch_2->user_flag_set())
8865 switch_1->set_user_flag();
8866 else
8867 switch_1->clear_user_flag();
8868 switch_1->clear_refinement_case();
8869 switch_1->set_refinement_case(
8870 switch_2->refinement_case());
8871 switch_1->clear_children();
8872 if (switch_2->refinement_case())
8873 switch_1->set_children(0,
8874 switch_2->child_index(0));
8875 if (switch_2->refinement_case() ==
8876 RefinementCase<dim - 1>::cut_xy)
8877 switch_1->set_children(2,
8878 switch_2->child_index(2));
8879
8880 switch_2->set_bounding_object_indices(
8881 {switch_1_lines[0],
8882 switch_1_lines[1],
8883 switch_1_lines[2],
8884 switch_1_lines[3]});
8885 switch_2->set_line_orientation(
8886 0, switch_1_line_orientations[0]);
8887 switch_2->set_line_orientation(
8888 1, switch_1_line_orientations[1]);
8889 switch_2->set_line_orientation(
8890 2, switch_1_line_orientations[2]);
8891 switch_2->set_line_orientation(
8892 3, switch_1_line_orientations[3]);
8893 switch_2->set_boundary_id_internal(
8894 switch_1_boundary_id);
8895 switch_2->set_manifold_id(switch_1->manifold_id());
8896 switch_2->set_user_index(switch_1_user_index);
8897 if (switch_1_user_flag)
8898 switch_2->set_user_flag();
8899 else
8900 switch_2->clear_user_flag();
8901 switch_2->clear_refinement_case();
8902 switch_2->set_refinement_case(
8903 switch_1_refinement_case);
8904 switch_2->clear_children();
8905 switch_2->set_children(0,
8906 switch_1_first_child_pair);
8907 switch_2->set_children(2,
8908 switch_1_second_child_pair);
8909
8910 new_quads[0]->set_refinement_case(
8912 new_quads[0]->set_children(0, quad->child_index(0));
8913 new_quads[1]->set_refinement_case(
8915 new_quads[1]->set_children(0, quad->child_index(2));
8916 }
8917 else
8918 {
8919 new_quads[0]->set_refinement_case(
8921 new_quads[0]->set_children(0, quad->child_index(0));
8922 new_quads[1]->set_refinement_case(
8924 new_quads[1]->set_children(0, quad->child_index(2));
8925 new_line->set_children(
8926 0, quad->child(0)->line_index(3));
8927 Assert(new_line->child(1) ==
8928 quad->child(1)->line(3),
8930 }
8931 quad->clear_children();
8932 }
8933
8934 // note these quads as children to the present one
8935 quad->set_children(0, new_quads[0]->index());
8936
8937 quad->set_refinement_case(aniso_quad_ref_case);
8938
8939 // finally clear flag indicating the need for
8940 // refinement
8941 quad->clear_user_data();
8942 } // if (anisotropic refinement)
8943
8944 if (quad->user_flag_set())
8945 {
8946 // this quad needs to be refined isotropically
8947
8948 // first of all: we only get here in the first run
8949 // of the loop
8950 Assert(loop == 0, ExcInternalError());
8951
8952 // find the next unused vertex. we'll need this in
8953 // any case
8954 while (triangulation.vertices_used[next_unused_vertex] ==
8955 true)
8956 ++next_unused_vertex;
8957 Assert(
8958 next_unused_vertex < triangulation.vertices.size(),
8959 ExcMessage(
8960 "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."));
8961
8962 // now: if the quad is refined anisotropically
8963 // already, set the anisotropic refinement flag
8964 // for both children. Additionally, we have to
8965 // refine the inner line, as it is an outer line
8966 // of the two (anisotropic) children
8967 const RefinementCase<dim - 1> quad_ref_case =
8968 quad->refinement_case();
8969
8970 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8971 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8972 {
8973 // set the 'opposite' refine case for children
8974 quad->child(0)->set_user_index(
8975 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8976 quad->child(1)->set_user_index(
8977 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8978 // refine the inner line
8980 middle_line;
8981 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8982 middle_line = quad->child(0)->line(1);
8983 else
8984 middle_line = quad->child(0)->line(3);
8985
8986 // if the face has been refined
8987 // anisotropically in the last refinement step
8988 // it might be, that it is flagged already and
8989 // that the middle line is thus refined
8990 // already. if not create children.
8991 if (!middle_line->has_children())
8992 {
8993 // set the middle vertex
8994 // appropriately. double refinement of
8995 // quads can only happen in the interior
8996 // of the domain, so we need not care
8997 // about boundary quads here
8998 triangulation.vertices[next_unused_vertex] =
8999 middle_line->center(true);
9000 triangulation.vertices_used[next_unused_vertex] =
9001 true;
9002
9003 // now search a slot for the two
9004 // child lines
9005 next_unused_line =
9006 triangulation.faces->lines
9007 .template next_free_pair_object<1>(
9008 triangulation);
9009
9010 // set the child pointer of the present
9011 // line
9012 middle_line->set_children(
9013 0, next_unused_line->index());
9014
9015 // set the two new lines
9016 const typename Triangulation<dim, spacedim>::
9017 raw_line_iterator children[2] = {
9018 next_unused_line, ++next_unused_line};
9019
9020 // some tests; if any of the iterators
9021 // should be invalid, then already
9022 // dereferencing will fail
9023 AssertIsNotUsed(children[0]);
9024 AssertIsNotUsed(children[1]);
9025
9026 children[0]->set_bounding_object_indices(
9027 {middle_line->vertex_index(0),
9028 next_unused_vertex});
9029 children[1]->set_bounding_object_indices(
9030 {next_unused_vertex,
9031 middle_line->vertex_index(1)});
9032
9033 children[0]->set_used_flag();
9034 children[1]->set_used_flag();
9035 children[0]->clear_children();
9036 children[1]->clear_children();
9037 children[0]->clear_user_data();
9038 children[1]->clear_user_data();
9039 children[0]->clear_user_flag();
9040 children[1]->clear_user_flag();
9041
9042 children[0]->set_boundary_id_internal(
9043 middle_line->boundary_id());
9044 children[1]->set_boundary_id_internal(
9045 middle_line->boundary_id());
9046
9047 children[0]->set_manifold_id(
9048 middle_line->manifold_id());
9049 children[1]->set_manifold_id(
9050 middle_line->manifold_id());
9051 }
9052 // now remove the flag from the quad and go to
9053 // the next quad, the actual refinement of the
9054 // quad takes place later on in this pass of
9055 // the loop or in the next one
9056 quad->clear_user_flag();
9057 continue;
9058 } // if (several refinement cases)
9059
9060 // if we got here, we have an unrefined quad and
9061 // have to do the usual work like in an purely
9062 // isotropic refinement
9063 Assert(quad_ref_case ==
9066
9067 // set the middle vertex appropriately: it might be that
9068 // the quad itself is not at the boundary, but that one of
9069 // its lines actually is. in this case, the newly created
9070 // vertices at the centers of the lines are not
9071 // necessarily the mean values of the adjacent vertices,
9072 // so do not compute the new vertex as the mean value of
9073 // the 4 vertices of the face, but rather as a weighted
9074 // mean value of the 8 vertices which we already have (the
9075 // four old ones, and the four ones inserted as middle
9076 // points for the four lines). summing up some more points
9077 // is generally cheaper than first asking whether one of
9078 // the lines is at the boundary
9079 //
9080 // note that the exact weights are chosen such as to
9081 // minimize the distortion of the four new quads from the
9082 // optimal shape. their description uses the formulas
9083 // underlying the TransfiniteInterpolationManifold
9084 // implementation
9085 triangulation.vertices[next_unused_vertex] =
9086 quad->center(true, true);
9087 triangulation.vertices_used[next_unused_vertex] = true;
9088
9089 // now that we created the right point, make up
9090 // the four lines interior to the quad (++ takes
9091 // care of the end of the vector)
9093 new_lines[4];
9094
9095 for (unsigned int i = 0; i < 4; ++i)
9096 {
9097 if (i % 2 == 0)
9098 // search a free pair of lines for 0. and
9099 // 2. line, so that two of them end up
9100 // together, which is necessary if later on
9101 // we want to refine the quad
9102 // anisotropically and the two lines end up
9103 // as children of new line
9104 next_unused_line =
9105 triangulation.faces->lines
9106 .template next_free_pair_object<1>(triangulation);
9107
9108 new_lines[i] = next_unused_line;
9109 ++next_unused_line;
9110
9111 AssertIsNotUsed(new_lines[i]);
9112 }
9113
9114 // set the data of the four lines. first collect
9115 // the indices of the five vertices:
9116 //
9117 // *--3--*
9118 // | | |
9119 // 0--4--1
9120 // | | |
9121 // *--2--*
9122 //
9123 // the lines are numbered as follows:
9124 //
9125 // *--*--*
9126 // | 1 |
9127 // *2-*-3*
9128 // | 0 |
9129 // *--*--*
9130
9131 const unsigned int vertex_indices[5] = {
9132 quad->line(0)->child(0)->vertex_index(1),
9133 quad->line(1)->child(0)->vertex_index(1),
9134 quad->line(2)->child(0)->vertex_index(1),
9135 quad->line(3)->child(0)->vertex_index(1),
9136 next_unused_vertex};
9137
9138 new_lines[0]->set_bounding_object_indices(
9140 new_lines[1]->set_bounding_object_indices(
9142 new_lines[2]->set_bounding_object_indices(
9144 new_lines[3]->set_bounding_object_indices(
9146
9147 for (const auto &new_line : new_lines)
9148 {
9149 new_line->set_used_flag();
9150 new_line->clear_user_flag();
9151 new_line->clear_user_data();
9152 new_line->clear_children();
9153 new_line->set_boundary_id_internal(quad->boundary_id());
9154 new_line->set_manifold_id(quad->manifold_id());
9155 }
9156
9157 // now for the quads. again, first collect some
9158 // data about the indices of the lines, with the
9159 // following numbering:
9160 //
9161 // .-6-.-7-.
9162 // 1 9 3
9163 // .-10.11-.
9164 // 0 8 2
9165 // .-4-.-5-.
9166
9167 const int line_indices[12] = {
9168 quad->line(0)
9169 ->child(child_line_index(0, quad->line_orientation(0)))
9170 ->index(),
9171 quad->line(0)
9172 ->child(child_line_index(1, quad->line_orientation(0)))
9173 ->index(),
9174 quad->line(1)
9175 ->child(child_line_index(0, quad->line_orientation(1)))
9176 ->index(),
9177 quad->line(1)
9178 ->child(child_line_index(1, quad->line_orientation(1)))
9179 ->index(),
9180 quad->line(2)
9181 ->child(child_line_index(0, quad->line_orientation(2)))
9182 ->index(),
9183 quad->line(2)
9184 ->child(child_line_index(1, quad->line_orientation(2)))
9185 ->index(),
9186 quad->line(3)
9187 ->child(child_line_index(0, quad->line_orientation(3)))
9188 ->index(),
9189 quad->line(3)
9190 ->child(child_line_index(1, quad->line_orientation(3)))
9191 ->index(),
9192 new_lines[0]->index(),
9193 new_lines[1]->index(),
9194 new_lines[2]->index(),
9195 new_lines[3]->index()};
9196
9197 // find some space (consecutive)
9198 // for the first two newly to be
9199 // created quads.
9201 new_quads[4];
9202
9203 next_unused_quad =
9204 triangulation.faces->quads
9205 .template next_free_pair_object<2>(triangulation);
9206
9207 new_quads[0] = next_unused_quad;
9208 AssertIsNotUsed(new_quads[0]);
9209
9210 ++next_unused_quad;
9211 new_quads[1] = next_unused_quad;
9212 AssertIsNotUsed(new_quads[1]);
9213
9214 next_unused_quad =
9215 triangulation.faces->quads
9216 .template next_free_pair_object<2>(triangulation);
9217 new_quads[2] = next_unused_quad;
9218 AssertIsNotUsed(new_quads[2]);
9219
9220 ++next_unused_quad;
9221 new_quads[3] = next_unused_quad;
9222 AssertIsNotUsed(new_quads[3]);
9223
9224 // note these quads as children to the present one
9225 quad->set_children(0, new_quads[0]->index());
9226 quad->set_children(2, new_quads[2]->index());
9227 quad->set_refinement_case(RefinementCase<2>::cut_xy);
9228
9229 new_quads[0]->set_bounding_object_indices(
9230 {line_indices[0],
9231 line_indices[8],
9232 line_indices[4],
9233 line_indices[10]});
9234 new_quads[1]->set_bounding_object_indices(
9235 {line_indices[8],
9236 line_indices[2],
9237 line_indices[5],
9238 line_indices[11]});
9239 new_quads[2]->set_bounding_object_indices(
9240 {line_indices[1],
9241 line_indices[9],
9242 line_indices[10],
9243 line_indices[6]});
9244 new_quads[3]->set_bounding_object_indices(
9245 {line_indices[9],
9246 line_indices[3],
9247 line_indices[11],
9248 line_indices[7]});
9249 for (const auto &new_quad : new_quads)
9250 {
9251 new_quad->set_used_flag();
9252 new_quad->clear_user_flag();
9253 new_quad->clear_user_data();
9254 new_quad->clear_children();
9255 new_quad->set_boundary_id_internal(quad->boundary_id());
9256 new_quad->set_manifold_id(quad->manifold_id());
9257 // set all line orientations to true, change
9258 // this after the loop, as we have to consider
9259 // different lines for each child
9260 for (unsigned int j = 0;
9261 j < GeometryInfo<dim>::lines_per_face;
9262 ++j)
9263 new_quad->set_line_orientation(
9265 }
9266 // now set the line orientation of children of
9267 // outer lines correctly, the lines in the
9268 // interior of the refined quad are automatically
9269 // oriented conforming to the standard
9270 new_quads[0]->set_line_orientation(
9271 0, quad->line_orientation(0));
9272 new_quads[0]->set_line_orientation(
9273 2, quad->line_orientation(2));
9274 new_quads[1]->set_line_orientation(
9275 1, quad->line_orientation(1));
9276 new_quads[1]->set_line_orientation(
9277 2, quad->line_orientation(2));
9278 new_quads[2]->set_line_orientation(
9279 0, quad->line_orientation(0));
9280 new_quads[2]->set_line_orientation(
9281 3, quad->line_orientation(3));
9282 new_quads[3]->set_line_orientation(
9283 1, quad->line_orientation(1));
9284 new_quads[3]->set_line_orientation(
9285 3, quad->line_orientation(3));
9286
9287 // finally clear flag indicating the need for
9288 // refinement
9289 quad->clear_user_flag();
9290 } // if (isotropic refinement)
9291 } // for all quads
9292 } // looped two times over all quads, all quads refined now
9293
9294 //---------------------------------
9295 // Now, finally, set up the new
9296 // cells
9297 //---------------------------------
9298
9300 cells_with_distorted_children;
9301
9302 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
9303 ++level)
9304 {
9305 // only active objects can be refined further; remember
9306 // that we won't operate on the finest level, so
9307 // triangulation.begin_*(level+1) is allowed
9309 hex = triangulation.begin_active_hex(level),
9310 endh = triangulation.begin_active_hex(level + 1);
9312 next_unused_hex = triangulation.begin_raw_hex(level + 1);
9313
9314 for (; hex != endh; ++hex)
9315 if (hex->refine_flag_set())
9316 {
9317 // this hex needs to be refined
9318
9319 // clear flag indicating the need for refinement. do
9320 // it here already, since we can't do it anymore
9321 // once the cell has children
9322 const RefinementCase<dim> ref_case = hex->refine_flag_set();
9323 hex->clear_refine_flag();
9324 hex->set_refinement_case(ref_case);
9325
9326 // depending on the refine case we might have to
9327 // create additional vertices, lines and quads
9328 // interior of the hex before the actual children
9329 // can be set up.
9330
9331 // in a first step: reserve the needed space for
9332 // lines, quads and hexes and initialize them
9333 // correctly
9334
9335 unsigned int n_new_lines = 0;
9336 unsigned int n_new_quads = 0;
9337 unsigned int n_new_hexes = 0;
9338 switch (ref_case)
9339 {
9343 n_new_lines = 0;
9344 n_new_quads = 1;
9345 n_new_hexes = 2;
9346 break;
9350 n_new_lines = 1;
9351 n_new_quads = 4;
9352 n_new_hexes = 4;
9353 break;
9355 n_new_lines = 6;
9356 n_new_quads = 12;
9357 n_new_hexes = 8;
9358 break;
9359 default:
9361 break;
9362 }
9363
9364 // find some space for the newly to be created
9365 // interior lines and initialize them.
9366 std::vector<
9368 new_lines(n_new_lines);
9369 for (unsigned int i = 0; i < n_new_lines; ++i)
9370 {
9371 new_lines[i] =
9372 triangulation.faces->lines
9373 .template next_free_single_object<1>(triangulation);
9374
9375 AssertIsNotUsed(new_lines[i]);
9376 new_lines[i]->set_used_flag();
9377 new_lines[i]->clear_user_flag();
9378 new_lines[i]->clear_user_data();
9379 new_lines[i]->clear_children();
9380 // interior line
9381 new_lines[i]->set_boundary_id_internal(
9383 // they inherit geometry description of the hex they
9384 // belong to
9385 new_lines[i]->set_manifold_id(hex->manifold_id());
9386 }
9387
9388 // find some space for the newly to be created
9389 // interior quads and initialize them.
9390 std::vector<
9392 new_quads(n_new_quads);
9393 for (unsigned int i = 0; i < n_new_quads; ++i)
9394 {
9395 new_quads[i] =
9396 triangulation.faces->quads
9397 .template next_free_single_object<2>(triangulation);
9398
9399 AssertIsNotUsed(new_quads[i]);
9400 new_quads[i]->set_used_flag();
9401 new_quads[i]->clear_user_flag();
9402 new_quads[i]->clear_user_data();
9403 new_quads[i]->clear_children();
9404 // interior quad
9405 new_quads[i]->set_boundary_id_internal(
9407 // they inherit geometry description of the hex they
9408 // belong to
9409 new_quads[i]->set_manifold_id(hex->manifold_id());
9410 // set all line orientation flags to true by
9411 // default, change this afterwards, if necessary
9412 for (unsigned int j = 0;
9413 j < GeometryInfo<dim>::lines_per_face;
9414 ++j)
9415 new_quads[i]->set_line_orientation(
9417 }
9418
9419 types::subdomain_id subdomainid = hex->subdomain_id();
9420
9421 // find some space for the newly to be created hexes
9422 // and initialize them.
9423 std::vector<
9425 new_hexes(n_new_hexes);
9426 for (unsigned int i = 0; i < n_new_hexes; ++i)
9427 {
9428 if (i % 2 == 0)
9429 next_unused_hex =
9430 triangulation.levels[level + 1]->cells.next_free_hex(
9431 triangulation, level + 1);
9432 else
9433 ++next_unused_hex;
9434
9435 new_hexes[i] = next_unused_hex;
9436
9437 AssertIsNotUsed(new_hexes[i]);
9438 new_hexes[i]->set_used_flag();
9439 new_hexes[i]->clear_user_flag();
9440 new_hexes[i]->clear_user_data();
9441 new_hexes[i]->clear_children();
9442 // inherit material
9443 // properties
9444 new_hexes[i]->set_material_id(hex->material_id());
9445 new_hexes[i]->set_manifold_id(hex->manifold_id());
9446 new_hexes[i]->set_subdomain_id(subdomainid);
9447
9448 // We only store the parent for every second cell. That's
9449 // because cells are created during refinement in
9450 // multiples of two, and so two successive cells always
9451 // share the same parent.
9452 if (i % 2 == 0)
9453 new_hexes[i]->set_parent(hex->index());
9454
9455 // set the face_orientation flag to true for all
9456 // faces initially, as this is the default value
9457 // which is true for all faces interior to the
9458 // hex. later on go the other way round and
9459 // reset faces that are at the boundary of the
9460 // mother cube
9461 //
9462 // the same is true for the face_flip and
9463 // face_rotation flags. however, the latter two
9464 // are set to false by default as this is the
9465 // standard value
9466 for (const unsigned int f :
9468 new_hexes[i]->set_combined_face_orientation(
9470 }
9471 // note these hexes as children to the present cell
9472 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
9473 hex->set_children(2 * i, new_hexes[2 * i]->index());
9474
9475 // we have to take into account whether the
9476 // different faces are oriented correctly or in the
9477 // opposite direction, so store that up front
9478
9479 // face_orientation
9480 const bool f_or[6] = {hex->face_orientation(0),
9481 hex->face_orientation(1),
9482 hex->face_orientation(2),
9483 hex->face_orientation(3),
9484 hex->face_orientation(4),
9485 hex->face_orientation(5)};
9486
9487 // face_flip
9488 const bool f_fl[6] = {hex->face_flip(0),
9489 hex->face_flip(1),
9490 hex->face_flip(2),
9491 hex->face_flip(3),
9492 hex->face_flip(4),
9493 hex->face_flip(5)};
9494
9495 // face_rotation
9496 const bool f_ro[6] = {hex->face_rotation(0),
9497 hex->face_rotation(1),
9498 hex->face_rotation(2),
9499 hex->face_rotation(3),
9500 hex->face_rotation(4),
9501 hex->face_rotation(5)};
9502
9503 // combined orientation
9504 const types::geometric_orientation f_co[6] = {
9505 hex->combined_face_orientation(0),
9506 hex->combined_face_orientation(1),
9507 hex->combined_face_orientation(2),
9508 hex->combined_face_orientation(3),
9509 hex->combined_face_orientation(4),
9510 hex->combined_face_orientation(5)};
9511
9512 // little helper table, indicating, whether the
9513 // child with index 0 or with index 1 can be found
9514 // at the standard origin of an anisotropically
9515 // refined quads in real orientation index 1:
9516 // (RefineCase - 1) index 2: face_flip
9517
9518 // index 3: face rotation
9519 // note: face orientation has no influence
9520 const unsigned int child_at_origin[2][2][2] = {
9521 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
9522 // face_rotation=false and true
9523 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
9524 // face_rotation=false and true
9525 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
9526 // face_rotation=false and true
9527 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
9528 // face_rotation=false and true
9529
9530 //-------------------------------------
9531 //
9532 // in the following we will do the same thing for
9533 // each refinement case: create a new vertex (if
9534 // needed), create new interior lines (if needed),
9535 // create new interior quads and afterwards build
9536 // the children hexes out of these and the existing
9537 // subfaces of the outer quads (which have been
9538 // created above). However, even if the steps are
9539 // quite similar, the actual work strongly depends
9540 // on the actual refinement case. therefore, we use
9541 // separate blocks of code for each of these cases,
9542 // which hopefully increases the readability to some
9543 // extend.
9544
9545 switch (ref_case)
9546 {
9548 {
9549 //----------------------------
9550 //
9551 // RefinementCase<dim>::cut_x
9552 //
9553 // the refined cube will look
9554 // like this:
9555 //
9556 // *----*----*
9557 // / / /|
9558 // / / / |
9559 // / / / |
9560 // *----*----* |
9561 // | | | |
9562 // | | | *
9563 // | | | /
9564 // | | | /
9565 // | | |/
9566 // *----*----*
9567 //
9568 // again, first collect some data about the
9569 // indices of the lines, with the following
9570 // numbering:
9571
9572 // face 2: front plane
9573 // (note: x,y exchanged)
9574 // *---*---*
9575 // | | |
9576 // | 0 |
9577 // | | |
9578 // *---*---*
9579 // m0
9580 // face 3: back plane
9581 // (note: x,y exchanged)
9582 // m1
9583 // *---*---*
9584 // | | |
9585 // | 1 |
9586 // | | |
9587 // *---*---*
9588 // face 4: bottom plane
9589 // *---*---*
9590 // / / /
9591 // / 2 /
9592 // / / /
9593 // *---*---*
9594 // m0
9595 // face 5: top plane
9596 // m1
9597 // *---*---*
9598 // / / /
9599 // / 3 /
9600 // / / /
9601 // *---*---*
9602
9603 // set up a list of line iterators first. from
9604 // this, construct lists of line_indices and
9605 // line orientations later on
9606 const typename Triangulation<dim, spacedim>::
9607 raw_line_iterator lines[4] = {
9608 hex->face(2)->child(0)->line(
9609 (hex->face(2)->refinement_case() ==
9611 1 :
9612 3), // 0
9613 hex->face(3)->child(0)->line(
9614 (hex->face(3)->refinement_case() ==
9616 1 :
9617 3), // 1
9618 hex->face(4)->child(0)->line(
9619 (hex->face(4)->refinement_case() ==
9621 1 :
9622 3), // 2
9623 hex->face(5)->child(0)->line(
9624 (hex->face(5)->refinement_case() ==
9626 1 :
9627 3) // 3
9628 };
9629
9630 int line_indices[4];
9631 for (unsigned int i = 0; i < 4; ++i)
9632 line_indices[i] = lines[i]->index();
9633
9634 // the orientation of lines for the inner quads
9635 // is quite tricky. as these lines are newly
9636 // created ones and thus have no parents, they
9637 // cannot inherit this property. set up an array
9638 // and fill it with the respective values
9639 types::geometric_orientation line_orientation[4]{};
9640
9641 // the middle vertex marked as m0 above is the
9642 // start vertex for lines 0 and 2 in standard
9643 // orientation, whereas m1 is the end vertex of
9644 // lines 1 and 3 in standard orientation
9645 const unsigned int middle_vertices[2] = {
9646 hex->line(2)->child(0)->vertex_index(1),
9647 hex->line(7)->child(0)->vertex_index(1)};
9648
9649 for (unsigned int i = 0; i < 4; ++i)
9650 if (lines[i]->vertex_index(i % 2) ==
9651 middle_vertices[i % 2])
9652 line_orientation[i] =
9654 else
9655 {
9656 // it must be the other way round then
9657 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9658 middle_vertices[i % 2],
9660 line_orientation[i] =
9662 }
9663
9664 // set up the new quad, line numbering is as
9665 // indicated above
9666 new_quads[0]->set_bounding_object_indices(
9667 {line_indices[0],
9668 line_indices[1],
9669 line_indices[2],
9670 line_indices[3]});
9671
9672 new_quads[0]->set_line_orientation(
9673 0, line_orientation[0]);
9674 new_quads[0]->set_line_orientation(
9675 1, line_orientation[1]);
9676 new_quads[0]->set_line_orientation(
9677 2, line_orientation[2]);
9678 new_quads[0]->set_line_orientation(
9679 3, line_orientation[3]);
9680
9681 // the quads are numbered as follows:
9682 //
9683 // planes in the interior of the old hex:
9684 //
9685 // *
9686 // /|
9687 // / | x
9688 // / | *-------* *---------*
9689 // * | | | / /
9690 // | 0 | | | / /
9691 // | * | | / /
9692 // | / *-------*y *---------*x
9693 // | /
9694 // |/
9695 // *
9696 //
9697 // children of the faces of the old hex
9698 //
9699 // *---*---* *---*---*
9700 // /| | | / / /|
9701 // / | | | / 9 / 10/ |
9702 // / | 5 | 6 | / / / |
9703 // * | | | *---*---* |
9704 // | 1 *---*---* | | | 2 *
9705 // | / / / | | | /
9706 // | / 7 / 8 / | 3 | 4 | /
9707 // |/ / / | | |/
9708 // *---*---* *---*---*
9709 //
9710 // note that we have to take care of the
9711 // orientation of faces.
9712 const int quad_indices[11] = {
9713 new_quads[0]->index(), // 0
9714
9715 hex->face(0)->index(), // 1
9716
9717 hex->face(1)->index(), // 2
9718
9719 hex->face(2)->child_index(
9720 child_at_origin[hex->face(2)->refinement_case() -
9721 1][f_fl[2]][f_ro[2]]), // 3
9722 hex->face(2)->child_index(
9723 1 -
9724 child_at_origin[hex->face(2)->refinement_case() -
9725 1][f_fl[2]][f_ro[2]]),
9726
9727 hex->face(3)->child_index(
9728 child_at_origin[hex->face(3)->refinement_case() -
9729 1][f_fl[3]][f_ro[3]]), // 5
9730 hex->face(3)->child_index(
9731 1 -
9732 child_at_origin[hex->face(3)->refinement_case() -
9733 1][f_fl[3]][f_ro[3]]),
9734
9735 hex->face(4)->child_index(
9736 child_at_origin[hex->face(4)->refinement_case() -
9737 1][f_fl[4]][f_ro[4]]), // 7
9738 hex->face(4)->child_index(
9739 1 -
9740 child_at_origin[hex->face(4)->refinement_case() -
9741 1][f_fl[4]][f_ro[4]]),
9742
9743 hex->face(5)->child_index(
9744 child_at_origin[hex->face(5)->refinement_case() -
9745 1][f_fl[5]][f_ro[5]]), // 9
9746 hex->face(5)->child_index(
9747 1 -
9748 child_at_origin[hex->face(5)->refinement_case() -
9749 1][f_fl[5]][f_ro[5]])
9750
9751 };
9752
9753 new_hexes[0]->set_bounding_object_indices(
9754 {quad_indices[1],
9755 quad_indices[0],
9756 quad_indices[3],
9757 quad_indices[5],
9758 quad_indices[7],
9759 quad_indices[9]});
9760 new_hexes[1]->set_bounding_object_indices(
9761 {quad_indices[0],
9762 quad_indices[2],
9763 quad_indices[4],
9764 quad_indices[6],
9765 quad_indices[8],
9766 quad_indices[10]});
9767 break;
9768 }
9769
9771 {
9772 //----------------------------
9773 //
9774 // RefinementCase<dim>::cut_y
9775 //
9776 // the refined cube will look like this:
9777 //
9778 // *---------*
9779 // / /|
9780 // *---------* |
9781 // / /| |
9782 // *---------* | |
9783 // | | | |
9784 // | | | *
9785 // | | |/
9786 // | | *
9787 // | |/
9788 // *---------*
9789 //
9790 // again, first collect some data about the
9791 // indices of the lines, with the following
9792 // numbering:
9793
9794 // face 0: left plane
9795 // *
9796 // /|
9797 // * |
9798 // /| |
9799 // * | |
9800 // | 0 |
9801 // | | *
9802 // | |/
9803 // | *m0
9804 // |/
9805 // *
9806 // face 1: right plane
9807 // *
9808 // /|
9809 // m1* |
9810 // /| |
9811 // * | |
9812 // | 1 |
9813 // | | *
9814 // | |/
9815 // | *
9816 // |/
9817 // *
9818 // face 4: bottom plane
9819 // *-------*
9820 // / /
9821 // m0*---2---*
9822 // / /
9823 // *-------*
9824 // face 5: top plane
9825 // *-------*
9826 // / /
9827 // *---3---*m1
9828 // / /
9829 // *-------*
9830
9831 // set up a list of line iterators first. from
9832 // this, construct lists of line_indices and
9833 // line orientations later on
9834 const typename Triangulation<dim, spacedim>::
9835 raw_line_iterator lines[4] = {
9836 hex->face(0)->child(0)->line(
9837 (hex->face(0)->refinement_case() ==
9839 1 :
9840 3), // 0
9841 hex->face(1)->child(0)->line(
9842 (hex->face(1)->refinement_case() ==
9844 1 :
9845 3), // 1
9846 hex->face(4)->child(0)->line(
9847 (hex->face(4)->refinement_case() ==
9849 1 :
9850 3), // 2
9851 hex->face(5)->child(0)->line(
9852 (hex->face(5)->refinement_case() ==
9854 1 :
9855 3) // 3
9856 };
9857
9858 int line_indices[4];
9859 for (unsigned int i = 0; i < 4; ++i)
9860 line_indices[i] = lines[i]->index();
9861
9862 // the orientation of lines for the inner quads
9863 // is quite tricky. as these lines are newly
9864 // created ones and thus have no parents, they
9865 // cannot inherit this property. set up an array
9866 // and fill it with the respective values
9867 types::geometric_orientation line_orientation[4]{};
9868
9869 // the middle vertex marked as m0 above is the
9870 // start vertex for lines 0 and 2 in standard
9871 // orientation, whereas m1 is the end vertex of
9872 // lines 1 and 3 in standard orientation
9873 const unsigned int middle_vertices[2] = {
9874 hex->line(0)->child(0)->vertex_index(1),
9875 hex->line(5)->child(0)->vertex_index(1)};
9876
9877 for (unsigned int i = 0; i < 4; ++i)
9878 if (lines[i]->vertex_index(i % 2) ==
9879 middle_vertices[i % 2])
9880 line_orientation[i] =
9882 else
9883 {
9884 // it must be the other way round then
9885 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9886 middle_vertices[i % 2],
9888 line_orientation[i] =
9890 }
9891
9892 // set up the new quad, line numbering is as
9893 // indicated above
9894 new_quads[0]->set_bounding_object_indices(
9895 {line_indices[2],
9896 line_indices[3],
9897 line_indices[0],
9898 line_indices[1]});
9899
9900 new_quads[0]->set_line_orientation(
9901 0, line_orientation[2]);
9902 new_quads[0]->set_line_orientation(
9903 1, line_orientation[3]);
9904 new_quads[0]->set_line_orientation(
9905 2, line_orientation[0]);
9906 new_quads[0]->set_line_orientation(
9907 3, line_orientation[1]);
9908
9909 // the quads are numbered as follows:
9910 //
9911 // planes in the interior of the old hex:
9912 //
9913 // *
9914 // /|
9915 // / | x
9916 // / | *-------* *---------*
9917 // * | | | / /
9918 // | | | 0 | / /
9919 // | * | | / /
9920 // | / *-------*y *---------*x
9921 // | /
9922 // |/
9923 // *
9924 //
9925 // children of the faces of the old hex
9926 //
9927 // *-------* *-------*
9928 // /| | / 10 /|
9929 // * | | *-------* |
9930 // /| | 6 | / 9 /| |
9931 // * |2| | *-------* |4|
9932 // | | *-------* | | | *
9933 // |1|/ 8 / | |3|/
9934 // | *-------* | 5 | *
9935 // |/ 7 / | |/
9936 // *-------* *-------*
9937 //
9938 // note that we have to take care of the
9939 // orientation of faces.
9940 const int quad_indices[11] = {
9941 new_quads[0]->index(), // 0
9942
9943 hex->face(0)->child_index(
9944 child_at_origin[hex->face(0)->refinement_case() -
9945 1][f_fl[0]][f_ro[0]]), // 1
9946 hex->face(0)->child_index(
9947 1 -
9948 child_at_origin[hex->face(0)->refinement_case() -
9949 1][f_fl[0]][f_ro[0]]),
9950
9951 hex->face(1)->child_index(
9952 child_at_origin[hex->face(1)->refinement_case() -
9953 1][f_fl[1]][f_ro[1]]), // 3
9954 hex->face(1)->child_index(
9955 1 -
9956 child_at_origin[hex->face(1)->refinement_case() -
9957 1][f_fl[1]][f_ro[1]]),
9958
9959 hex->face(2)->index(), // 5
9960
9961 hex->face(3)->index(), // 6
9962
9963 hex->face(4)->child_index(
9964 child_at_origin[hex->face(4)->refinement_case() -
9965 1][f_fl[4]][f_ro[4]]), // 7
9966 hex->face(4)->child_index(
9967 1 -
9968 child_at_origin[hex->face(4)->refinement_case() -
9969 1][f_fl[4]][f_ro[4]]),
9970
9971 hex->face(5)->child_index(
9972 child_at_origin[hex->face(5)->refinement_case() -
9973 1][f_fl[5]][f_ro[5]]), // 9
9974 hex->face(5)->child_index(
9975 1 -
9976 child_at_origin[hex->face(5)->refinement_case() -
9977 1][f_fl[5]][f_ro[5]])
9978
9979 };
9980
9981 new_hexes[0]->set_bounding_object_indices(
9982 {quad_indices[1],
9983 quad_indices[3],
9984 quad_indices[5],
9985 quad_indices[0],
9986 quad_indices[7],
9987 quad_indices[9]});
9988 new_hexes[1]->set_bounding_object_indices(
9989 {quad_indices[2],
9990 quad_indices[4],
9991 quad_indices[0],
9992 quad_indices[6],
9993 quad_indices[8],
9994 quad_indices[10]});
9995 break;
9996 }
9997
9999 {
10000 //----------------------------
10001 //
10002 // RefinementCase<dim>::cut_z
10003 //
10004 // the refined cube will look like this:
10005 //
10006 // *---------*
10007 // / /|
10008 // / / |
10009 // / / *
10010 // *---------* /|
10011 // | | / |
10012 // | |/ *
10013 // *---------* /
10014 // | | /
10015 // | |/
10016 // *---------*
10017 //
10018 // again, first collect some data about the
10019 // indices of the lines, with the following
10020 // numbering:
10021
10022 // face 0: left plane
10023 // *
10024 // /|
10025 // / |
10026 // / *
10027 // * /|
10028 // | 0 |
10029 // |/ *
10030 // m0* /
10031 // | /
10032 // |/
10033 // *
10034 // face 1: right plane
10035 // *
10036 // /|
10037 // / |
10038 // / *m1
10039 // * /|
10040 // | 1 |
10041 // |/ *
10042 // * /
10043 // | /
10044 // |/
10045 // *
10046 // face 2: front plane
10047 // (note: x,y exchanged)
10048 // *-------*
10049 // | |
10050 // m0*---2---*
10051 // | |
10052 // *-------*
10053 // face 3: back plane
10054 // (note: x,y exchanged)
10055 // *-------*
10056 // | |
10057 // *---3---*m1
10058 // | |
10059 // *-------*
10060
10061 // set up a list of line iterators first. from
10062 // this, construct lists of line_indices and
10063 // line orientations later on
10064 const typename Triangulation<dim, spacedim>::
10065 raw_line_iterator lines[4] = {
10066 hex->face(0)->child(0)->line(
10067 (hex->face(0)->refinement_case() ==
10069 1 :
10070 3), // 0
10071 hex->face(1)->child(0)->line(
10072 (hex->face(1)->refinement_case() ==
10074 1 :
10075 3), // 1
10076 hex->face(2)->child(0)->line(
10077 (hex->face(2)->refinement_case() ==
10079 1 :
10080 3), // 2
10081 hex->face(3)->child(0)->line(
10082 (hex->face(3)->refinement_case() ==
10084 1 :
10085 3) // 3
10086 };
10087
10088 int line_indices[4];
10089 for (unsigned int i = 0; i < 4; ++i)
10090 line_indices[i] = lines[i]->index();
10091
10092 // the orientation of lines for the inner quads
10093 // is quite tricky. as these lines are newly
10094 // created ones and thus have no parents, they
10095 // cannot inherit this property. set up an array
10096 // and fill it with the respective values
10097 types::geometric_orientation line_orientation[4]{};
10098
10099 // the middle vertex marked as m0 above is the
10100 // start vertex for lines 0 and 2 in standard
10101 // orientation, whereas m1 is the end vertex of
10102 // lines 1 and 3 in standard orientation
10103 const unsigned int middle_vertices[2] = {
10104 middle_vertex_index<dim, spacedim>(hex->line(8)),
10105 middle_vertex_index<dim, spacedim>(hex->line(11))};
10106
10107 for (unsigned int i = 0; i < 4; ++i)
10108 if (lines[i]->vertex_index(i % 2) ==
10109 middle_vertices[i % 2])
10110 line_orientation[i] =
10112 else
10113 {
10114 // it must be the other way round then
10115 Assert(lines[i]->vertex_index((i + 1) % 2) ==
10116 middle_vertices[i % 2],
10118 line_orientation[i] =
10120 }
10121
10122 // set up the new quad, line numbering is as
10123 // indicated above
10124 new_quads[0]->set_bounding_object_indices(
10125 {line_indices[0],
10126 line_indices[1],
10127 line_indices[2],
10128 line_indices[3]});
10129
10130 new_quads[0]->set_line_orientation(
10131 0, line_orientation[0]);
10132 new_quads[0]->set_line_orientation(
10133 1, line_orientation[1]);
10134 new_quads[0]->set_line_orientation(
10135 2, line_orientation[2]);
10136 new_quads[0]->set_line_orientation(
10137 3, line_orientation[3]);
10138
10139 // the quads are numbered as follows:
10140 //
10141 // planes in the interior of the old hex:
10142 //
10143 // *
10144 // /|
10145 // / | x
10146 // / | *-------* *---------*
10147 // * | | | / /
10148 // | | | | / 0 /
10149 // | * | | / /
10150 // | / *-------*y *---------*x
10151 // | /
10152 // |/
10153 // *
10154 //
10155 // children of the faces of the old hex
10156 //
10157 // *---*---* *-------*
10158 // /| 8 | / /|
10159 // / | | / 10 / |
10160 // / *-------* / / *
10161 // * 2/| | *-------* 4/|
10162 // | / | 7 | | 6 | / |
10163 // |/1 *-------* | |/3 *
10164 // * / / *-------* /
10165 // | / 9 / | | /
10166 // |/ / | 5 |/
10167 // *-------* *---*---*
10168 //
10169 // note that we have to take care of the
10170 // orientation of faces.
10171 const int quad_indices[11] = {
10172 new_quads[0]->index(), // 0
10173
10174 hex->face(0)->child_index(
10175 child_at_origin[hex->face(0)->refinement_case() -
10176 1][f_fl[0]][f_ro[0]]), // 1
10177 hex->face(0)->child_index(
10178 1 -
10179 child_at_origin[hex->face(0)->refinement_case() -
10180 1][f_fl[0]][f_ro[0]]),
10181
10182 hex->face(1)->child_index(
10183 child_at_origin[hex->face(1)->refinement_case() -
10184 1][f_fl[1]][f_ro[1]]), // 3
10185 hex->face(1)->child_index(
10186 1 -
10187 child_at_origin[hex->face(1)->refinement_case() -
10188 1][f_fl[1]][f_ro[1]]),
10189
10190 hex->face(2)->child_index(
10191 child_at_origin[hex->face(2)->refinement_case() -
10192 1][f_fl[2]][f_ro[2]]), // 5
10193 hex->face(2)->child_index(
10194 1 -
10195 child_at_origin[hex->face(2)->refinement_case() -
10196 1][f_fl[2]][f_ro[2]]),
10197
10198 hex->face(3)->child_index(
10199 child_at_origin[hex->face(3)->refinement_case() -
10200 1][f_fl[3]][f_ro[3]]), // 7
10201 hex->face(3)->child_index(
10202 1 -
10203 child_at_origin[hex->face(3)->refinement_case() -
10204 1][f_fl[3]][f_ro[3]]),
10205
10206 hex->face(4)->index(), // 9
10207
10208 hex->face(5)->index() // 10
10209 };
10210
10211 new_hexes[0]->set_bounding_object_indices(
10212 {quad_indices[1],
10213 quad_indices[3],
10214 quad_indices[5],
10215 quad_indices[7],
10216 quad_indices[9],
10217 quad_indices[0]});
10218 new_hexes[1]->set_bounding_object_indices(
10219 {quad_indices[2],
10220 quad_indices[4],
10221 quad_indices[6],
10222 quad_indices[8],
10223 quad_indices[0],
10224 quad_indices[10]});
10225 break;
10226 }
10227
10229 {
10230 //----------------------------
10231 //
10232 // RefinementCase<dim>::cut_xy
10233 //
10234 // the refined cube will look like this:
10235 //
10236 // *----*----*
10237 // / / /|
10238 // *----*----* |
10239 // / / /| |
10240 // *----*----* | |
10241 // | | | | |
10242 // | | | | *
10243 // | | | |/
10244 // | | | *
10245 // | | |/
10246 // *----*----*
10247 //
10248
10249 // first, create the new internal line
10250 new_lines[0]->set_bounding_object_indices(
10251 {middle_vertex_index<dim, spacedim>(hex->face(4)),
10252 middle_vertex_index<dim, spacedim>(hex->face(5))});
10253
10254 // again, first collect some data about the
10255 // indices of the lines, with the following
10256 // numbering:
10257
10258 // face 0: left plane
10259 // *
10260 // /|
10261 // * |
10262 // /| |
10263 // * | |
10264 // | 0 |
10265 // | | *
10266 // | |/
10267 // | *
10268 // |/
10269 // *
10270 // face 1: right plane
10271 // *
10272 // /|
10273 // * |
10274 // /| |
10275 // * | |
10276 // | 1 |
10277 // | | *
10278 // | |/
10279 // | *
10280 // |/
10281 // *
10282 // face 2: front plane
10283 // (note: x,y exchanged)
10284 // *---*---*
10285 // | | |
10286 // | 2 |
10287 // | | |
10288 // *-------*
10289 // face 3: back plane
10290 // (note: x,y exchanged)
10291 // *---*---*
10292 // | | |
10293 // | 3 |
10294 // | | |
10295 // *---*---*
10296 // face 4: bottom plane
10297 // *---*---*
10298 // / 5 /
10299 // *-6-*-7-*
10300 // / 4 /
10301 // *---*---*
10302 // face 5: top plane
10303 // *---*---*
10304 // / 9 /
10305 // *10-*-11*
10306 // / 8 /
10307 // *---*---*
10308 // middle planes
10309 // *-------* *---*---*
10310 // / / | | |
10311 // / / | 12 |
10312 // / / | | |
10313 // *-------* *---*---*
10314
10315 // set up a list of line iterators first. from
10316 // this, construct lists of line_indices and
10317 // line orientations later on
10318 const typename Triangulation<
10319 dim,
10320 spacedim>::raw_line_iterator lines[13] = {
10321 hex->face(0)->child(0)->line(
10322 (hex->face(0)->refinement_case() ==
10324 1 :
10325 3), // 0
10326 hex->face(1)->child(0)->line(
10327 (hex->face(1)->refinement_case() ==
10329 1 :
10330 3), // 1
10331 hex->face(2)->child(0)->line(
10332 (hex->face(2)->refinement_case() ==
10334 1 :
10335 3), // 2
10336 hex->face(3)->child(0)->line(
10337 (hex->face(3)->refinement_case() ==
10339 1 :
10340 3), // 3
10341
10342 hex->face(4)
10343 ->isotropic_child(
10345 0, f_or[4], f_fl[4], f_ro[4]))
10346 ->line(
10348 1, f_or[4], f_fl[4], f_ro[4])), // 4
10349 hex->face(4)
10350 ->isotropic_child(
10352 3, f_or[4], f_fl[4], f_ro[4]))
10353 ->line(
10355 0, f_or[4], f_fl[4], f_ro[4])), // 5
10356 hex->face(4)
10357 ->isotropic_child(
10359 0, f_or[4], f_fl[4], f_ro[4]))
10360 ->line(
10362 3, f_or[4], f_fl[4], f_ro[4])), // 6
10363 hex->face(4)
10364 ->isotropic_child(
10366 3, f_or[4], f_fl[4], f_ro[4]))
10367 ->line(
10369 2, f_or[4], f_fl[4], f_ro[4])), // 7
10370
10371 hex->face(5)
10372 ->isotropic_child(
10374 0, f_or[5], f_fl[5], f_ro[5]))
10375 ->line(
10377 1, f_or[5], f_fl[5], f_ro[5])), // 8
10378 hex->face(5)
10379 ->isotropic_child(
10381 3, f_or[5], f_fl[5], f_ro[5]))
10382 ->line(
10384 0, f_or[5], f_fl[5], f_ro[5])), // 9
10385 hex->face(5)
10386 ->isotropic_child(
10388 0, f_or[5], f_fl[5], f_ro[5]))
10389 ->line(
10391 3, f_or[5], f_fl[5], f_ro[5])), // 10
10392 hex->face(5)
10393 ->isotropic_child(
10395 3, f_or[5], f_fl[5], f_ro[5]))
10396 ->line(
10398 2, f_or[5], f_fl[5], f_ro[5])), // 11
10399
10400 new_lines[0] // 12
10401 };
10402
10403 int line_indices[13];
10404 for (unsigned int i = 0; i < 13; ++i)
10405 line_indices[i] = lines[i]->index();
10406
10407 // the orientation of lines for the inner quads
10408 // is quite tricky. as these lines are newly
10409 // created ones and thus have no parents, they
10410 // cannot inherit this property. set up an array
10411 // and fill it with the respective values
10412 types::geometric_orientation line_orientation[13]{};
10413
10414 // the middle vertices of the lines of our
10415 // bottom face
10416 const unsigned int middle_vertices[4] = {
10417 hex->line(0)->child(0)->vertex_index(1),
10418 hex->line(1)->child(0)->vertex_index(1),
10419 hex->line(2)->child(0)->vertex_index(1),
10420 hex->line(3)->child(0)->vertex_index(1),
10421 };
10422
10423 // note: for lines 0 to 3 the orientation of the
10424 // line is 'true', if vertex 0 is on the bottom
10425 // face
10426 for (unsigned int i = 0; i < 4; ++i)
10427 if (lines[i]->vertex_index(0) == middle_vertices[i])
10428 line_orientation[i] =
10430 else
10431 {
10432 // it must be the other way round then
10433 Assert(lines[i]->vertex_index(1) ==
10434 middle_vertices[i],
10436 line_orientation[i] =
10438 }
10439
10440 // note: for lines 4 to 11 (inner lines of the
10441 // outer quads) the following holds: the second
10442 // vertex of the even lines in standard
10443 // orientation is the vertex in the middle of
10444 // the quad, whereas for odd lines the first
10445 // vertex is the same middle vertex.
10446 for (unsigned int i = 4; i < 12; ++i)
10447 if (lines[i]->vertex_index((i + 1) % 2) ==
10448 middle_vertex_index<dim, spacedim>(
10449 hex->face(3 + i / 4)))
10450 line_orientation[i] =
10452 else
10453 {
10454 // it must be the other way round then
10455 Assert(lines[i]->vertex_index(i % 2) ==
10456 (middle_vertex_index<dim, spacedim>(
10457 hex->face(3 + i / 4))),
10459 line_orientation[i] =
10461 }
10462 // for the last line the line orientation is
10463 // always true, since it was just constructed
10464 // that way
10465 line_orientation[12] =
10467
10468 // set up the 4 quads, numbered as follows (left
10469 // quad numbering, right line numbering
10470 // extracted from above)
10471 //
10472 // * *
10473 // /| 9|
10474 // * | * |
10475 // y/| | 8| 3
10476 // * |1| * | |
10477 // | | |x | 12|
10478 // |0| * | | *
10479 // | |/ 2 |5
10480 // | * | *
10481 // |/ |4
10482 // * *
10483 //
10484 // x
10485 // *---*---* *10-*-11*
10486 // | | | | | |
10487 // | 2 | 3 | 0 12 1
10488 // | | | | | |
10489 // *---*---*y *-6-*-7-*
10490
10491 new_quads[0]->set_bounding_object_indices(
10492 {line_indices[2],
10493 line_indices[12],
10494 line_indices[4],
10495 line_indices[8]});
10496 new_quads[1]->set_bounding_object_indices(
10497 {line_indices[12],
10498 line_indices[3],
10499 line_indices[5],
10500 line_indices[9]});
10501 new_quads[2]->set_bounding_object_indices(
10502 {line_indices[6],
10503 line_indices[10],
10504 line_indices[0],
10505 line_indices[12]});
10506 new_quads[3]->set_bounding_object_indices(
10507 {line_indices[7],
10508 line_indices[11],
10509 line_indices[12],
10510 line_indices[1]});
10511
10512 new_quads[0]->set_line_orientation(
10513 0, line_orientation[2]);
10514 new_quads[0]->set_line_orientation(
10515 2, line_orientation[4]);
10516 new_quads[0]->set_line_orientation(
10517 3, line_orientation[8]);
10518
10519 new_quads[1]->set_line_orientation(
10520 1, line_orientation[3]);
10521 new_quads[1]->set_line_orientation(
10522 2, line_orientation[5]);
10523 new_quads[1]->set_line_orientation(
10524 3, line_orientation[9]);
10525
10526 new_quads[2]->set_line_orientation(
10527 0, line_orientation[6]);
10528 new_quads[2]->set_line_orientation(
10529 1, line_orientation[10]);
10530 new_quads[2]->set_line_orientation(
10531 2, line_orientation[0]);
10532
10533 new_quads[3]->set_line_orientation(
10534 0, line_orientation[7]);
10535 new_quads[3]->set_line_orientation(
10536 1, line_orientation[11]);
10537 new_quads[3]->set_line_orientation(
10538 3, line_orientation[1]);
10539
10540 // the quads are numbered as follows:
10541 //
10542 // planes in the interior of the old hex:
10543 //
10544 // *
10545 // /|
10546 // * | x
10547 // /| | *---*---* *---------*
10548 // * |1| | | | / /
10549 // | | | | 2 | 3 | / /
10550 // |0| * | | | / /
10551 // | |/ *---*---*y *---------*x
10552 // | *
10553 // |/
10554 // *
10555 //
10556 // children of the faces of the old hex
10557 //
10558 // *---*---* *---*---*
10559 // /| | | /18 / 19/|
10560 // * |10 | 11| /---/---* |
10561 // /| | | | /16 / 17/| |
10562 // * |5| | | *---*---* |7|
10563 // | | *---*---* | | | | *
10564 // |4|/14 / 15/ | | |6|/
10565 // | *---/---/ | 8 | 9 | *
10566 // |/12 / 13/ | | |/
10567 // *---*---* *---*---*
10568 //
10569 // note that we have to take care of the
10570 // orientation of faces.
10571 const int quad_indices[20] = {
10572 new_quads[0]->index(), // 0
10573 new_quads[1]->index(),
10574 new_quads[2]->index(),
10575 new_quads[3]->index(),
10576
10577 hex->face(0)->child_index(
10578 child_at_origin[hex->face(0)->refinement_case() -
10579 1][f_fl[0]][f_ro[0]]), // 4
10580 hex->face(0)->child_index(
10581 1 -
10582 child_at_origin[hex->face(0)->refinement_case() -
10583 1][f_fl[0]][f_ro[0]]),
10584
10585 hex->face(1)->child_index(
10586 child_at_origin[hex->face(1)->refinement_case() -
10587 1][f_fl[1]][f_ro[1]]), // 6
10588 hex->face(1)->child_index(
10589 1 -
10590 child_at_origin[hex->face(1)->refinement_case() -
10591 1][f_fl[1]][f_ro[1]]),
10592
10593 hex->face(2)->child_index(
10594 child_at_origin[hex->face(2)->refinement_case() -
10595 1][f_fl[2]][f_ro[2]]), // 8
10596 hex->face(2)->child_index(
10597 1 -
10598 child_at_origin[hex->face(2)->refinement_case() -
10599 1][f_fl[2]][f_ro[2]]),
10600
10601 hex->face(3)->child_index(
10602 child_at_origin[hex->face(3)->refinement_case() -
10603 1][f_fl[3]][f_ro[3]]), // 10
10604 hex->face(3)->child_index(
10605 1 -
10606 child_at_origin[hex->face(3)->refinement_case() -
10607 1][f_fl[3]][f_ro[3]]),
10608
10609 hex->face(4)->isotropic_child_index(
10611 0, f_or[4], f_fl[4], f_ro[4])), // 12
10612 hex->face(4)->isotropic_child_index(
10614 1, f_or[4], f_fl[4], f_ro[4])),
10615 hex->face(4)->isotropic_child_index(
10617 2, f_or[4], f_fl[4], f_ro[4])),
10618 hex->face(4)->isotropic_child_index(
10620 3, f_or[4], f_fl[4], f_ro[4])),
10621
10622 hex->face(5)->isotropic_child_index(
10624 0, f_or[5], f_fl[5], f_ro[5])), // 16
10625 hex->face(5)->isotropic_child_index(
10627 1, f_or[5], f_fl[5], f_ro[5])),
10628 hex->face(5)->isotropic_child_index(
10630 2, f_or[5], f_fl[5], f_ro[5])),
10631 hex->face(5)->isotropic_child_index(
10633 3, f_or[5], f_fl[5], f_ro[5]))};
10634
10635 new_hexes[0]->set_bounding_object_indices(
10636 {quad_indices[4],
10637 quad_indices[0],
10638 quad_indices[8],
10639 quad_indices[2],
10640 quad_indices[12],
10641 quad_indices[16]});
10642 new_hexes[1]->set_bounding_object_indices(
10643 {quad_indices[0],
10644 quad_indices[6],
10645 quad_indices[9],
10646 quad_indices[3],
10647 quad_indices[13],
10648 quad_indices[17]});
10649 new_hexes[2]->set_bounding_object_indices(
10650 {quad_indices[5],
10651 quad_indices[1],
10652 quad_indices[2],
10653 quad_indices[10],
10654 quad_indices[14],
10655 quad_indices[18]});
10656 new_hexes[3]->set_bounding_object_indices(
10657 {quad_indices[1],
10658 quad_indices[7],
10659 quad_indices[3],
10660 quad_indices[11],
10661 quad_indices[15],
10662 quad_indices[19]});
10663 break;
10664 }
10665
10667 {
10668 //----------------------------
10669 //
10670 // RefinementCase<dim>::cut_xz
10671 //
10672 // the refined cube will look like this:
10673 //
10674 // *----*----*
10675 // / / /|
10676 // / / / |
10677 // / / / *
10678 // *----*----* /|
10679 // | | | / |
10680 // | | |/ *
10681 // *----*----* /
10682 // | | | /
10683 // | | |/
10684 // *----*----*
10685 //
10686
10687 // first, create the new internal line
10688 new_lines[0]->set_bounding_object_indices(
10689 {middle_vertex_index<dim, spacedim>(hex->face(2)),
10690 middle_vertex_index<dim, spacedim>(hex->face(3))});
10691
10692 // again, first collect some data about the
10693 // indices of the lines, with the following
10694 // numbering:
10695
10696 // face 0: left plane
10697 // *
10698 // /|
10699 // / |
10700 // / *
10701 // * /|
10702 // | 0 |
10703 // |/ *
10704 // * /
10705 // | /
10706 // |/
10707 // *
10708 // face 1: right plane
10709 // *
10710 // /|
10711 // / |
10712 // / *
10713 // * /|
10714 // | 1 |
10715 // |/ *
10716 // * /
10717 // | /
10718 // |/
10719 // *
10720 // face 2: front plane
10721 // (note: x,y exchanged)
10722 // *---*---*
10723 // | 5 |
10724 // *-6-*-7-*
10725 // | 4 |
10726 // *---*---*
10727 // face 3: back plane
10728 // (note: x,y exchanged)
10729 // *---*---*
10730 // | 9 |
10731 // *10-*-11*
10732 // | 8 |
10733 // *---*---*
10734 // face 4: bottom plane
10735 // *---*---*
10736 // / / /
10737 // / 2 /
10738 // / / /
10739 // *---*---*
10740 // face 5: top plane
10741 // *---*---*
10742 // / / /
10743 // / 3 /
10744 // / / /
10745 // *---*---*
10746 // middle planes
10747 // *---*---* *-------*
10748 // / / / | |
10749 // / 12 / | |
10750 // / / / | |
10751 // *---*---* *-------*
10752
10753 // set up a list of line iterators first. from
10754 // this, construct lists of line_indices and
10755 // line orientations later on
10756 const typename Triangulation<
10757 dim,
10758 spacedim>::raw_line_iterator lines[13] = {
10759 hex->face(0)->child(0)->line(
10760 (hex->face(0)->refinement_case() ==
10762 1 :
10763 3), // 0
10764 hex->face(1)->child(0)->line(
10765 (hex->face(1)->refinement_case() ==
10767 1 :
10768 3), // 1
10769 hex->face(4)->child(0)->line(
10770 (hex->face(4)->refinement_case() ==
10772 1 :
10773 3), // 2
10774 hex->face(5)->child(0)->line(
10775 (hex->face(5)->refinement_case() ==
10777 1 :
10778 3), // 3
10779
10780 hex->face(2)
10781 ->isotropic_child(
10783 0, f_or[2], f_fl[2], f_ro[2]))
10784 ->line(
10786 3, f_or[2], f_fl[2], f_ro[2])), // 4
10787 hex->face(2)
10788 ->isotropic_child(
10790 3, f_or[2], f_fl[2], f_ro[2]))
10791 ->line(
10793 2, f_or[2], f_fl[2], f_ro[2])), // 5
10794 hex->face(2)
10795 ->isotropic_child(
10797 0, f_or[2], f_fl[2], f_ro[2]))
10798 ->line(
10800 1, f_or[2], f_fl[2], f_ro[2])), // 6
10801 hex->face(2)
10802 ->isotropic_child(
10804 3, f_or[2], f_fl[2], f_ro[2]))
10805 ->line(
10807 0, f_or[2], f_fl[2], f_ro[2])), // 7
10808
10809 hex->face(3)
10810 ->isotropic_child(
10812 0, f_or[3], f_fl[3], f_ro[3]))
10813 ->line(
10815 3, f_or[3], f_fl[3], f_ro[3])), // 8
10816 hex->face(3)
10817 ->isotropic_child(
10819 3, f_or[3], f_fl[3], f_ro[3]))
10820 ->line(
10822 2, f_or[3], f_fl[3], f_ro[3])), // 9
10823 hex->face(3)
10824 ->isotropic_child(
10826 0, f_or[3], f_fl[3], f_ro[3]))
10827 ->line(
10829 1, f_or[3], f_fl[3], f_ro[3])), // 10
10830 hex->face(3)
10831 ->isotropic_child(
10833 3, f_or[3], f_fl[3], f_ro[3]))
10834 ->line(
10836 0, f_or[3], f_fl[3], f_ro[3])), // 11
10837
10838 new_lines[0] // 12
10839 };
10840
10841 int line_indices[13];
10842 for (unsigned int i = 0; i < 13; ++i)
10843 line_indices[i] = lines[i]->index();
10844
10845 // the orientation of lines for the inner quads
10846 // is quite tricky. as these lines are newly
10847 // created ones and thus have no parents, they
10848 // cannot inherit this property. set up an array
10849 // and fill it with the respective values
10850 types::geometric_orientation line_orientation[13]{};
10851
10852 // the middle vertices of the
10853 // lines of our front face
10854 const unsigned int middle_vertices[4] = {
10855 hex->line(8)->child(0)->vertex_index(1),
10856 hex->line(9)->child(0)->vertex_index(1),
10857 hex->line(2)->child(0)->vertex_index(1),
10858 hex->line(6)->child(0)->vertex_index(1),
10859 };
10860
10861 // note: for lines 0 to 3 the orientation of the
10862 // line is 'true', if vertex 0 is on the front
10863 for (unsigned int i = 0; i < 4; ++i)
10864 if (lines[i]->vertex_index(0) == middle_vertices[i])
10865 line_orientation[i] =
10867 else
10868 {
10869 // it must be the other way round then
10870 Assert(lines[i]->vertex_index(1) ==
10871 middle_vertices[i],
10873 line_orientation[i] =
10875 }
10876
10877 // note: for lines 4 to 11 (inner lines of the
10878 // outer quads) the following holds: the second
10879 // vertex of the even lines in standard
10880 // orientation is the vertex in the middle of
10881 // the quad, whereas for odd lines the first
10882 // vertex is the same middle vertex.
10883 for (unsigned int i = 4; i < 12; ++i)
10884 if (lines[i]->vertex_index((i + 1) % 2) ==
10885 middle_vertex_index<dim, spacedim>(
10886 hex->face(1 + i / 4)))
10887 line_orientation[i] =
10889 else
10890 {
10891 // it must be the other way
10892 // round then
10893 Assert(lines[i]->vertex_index(i % 2) ==
10894 (middle_vertex_index<dim, spacedim>(
10895 hex->face(1 + i / 4))),
10897 line_orientation[i] =
10899 }
10900 // for the last line the line orientation is
10901 // always true, since it was just constructed
10902 // that way
10903 line_orientation[12] =
10905
10906 // set up the 4 quads, numbered as follows (left
10907 // quad numbering, right line numbering
10908 // extracted from above), the drawings denote
10909 // middle planes
10910 //
10911 // * *
10912 // /| /|
10913 // / | 3 9
10914 // y/ * / *
10915 // * 3/| * /|
10916 // | / |x 5 12|8
10917 // |/ * |/ *
10918 // * 2/ * /
10919 // | / 4 2
10920 // |/ |/
10921 // * *
10922 //
10923 // y
10924 // *----*----* *-10-*-11-*
10925 // / / / / / /
10926 // / 0 / 1 / 0 12 1
10927 // / / / / / /
10928 // *----*----*x *--6-*--7-*
10929
10930 new_quads[0]->set_bounding_object_indices(
10931 {line_indices[0],
10932 line_indices[12],
10933 line_indices[6],
10934 line_indices[10]});
10935 new_quads[1]->set_bounding_object_indices(
10936 {line_indices[12],
10937 line_indices[1],
10938 line_indices[7],
10939 line_indices[11]});
10940 new_quads[2]->set_bounding_object_indices(
10941 {line_indices[4],
10942 line_indices[8],
10943 line_indices[2],
10944 line_indices[12]});
10945 new_quads[3]->set_bounding_object_indices(
10946 {line_indices[5],
10947 line_indices[9],
10948 line_indices[12],
10949 line_indices[3]});
10950
10951 new_quads[0]->set_line_orientation(
10952 0, line_orientation[0]);
10953 new_quads[0]->set_line_orientation(
10954 2, line_orientation[6]);
10955 new_quads[0]->set_line_orientation(
10956 3, line_orientation[10]);
10957
10958 new_quads[1]->set_line_orientation(
10959 1, line_orientation[1]);
10960 new_quads[1]->set_line_orientation(
10961 2, line_orientation[7]);
10962 new_quads[1]->set_line_orientation(
10963 3, line_orientation[11]);
10964
10965 new_quads[2]->set_line_orientation(
10966 0, line_orientation[4]);
10967 new_quads[2]->set_line_orientation(
10968 1, line_orientation[8]);
10969 new_quads[2]->set_line_orientation(
10970 2, line_orientation[2]);
10971
10972 new_quads[3]->set_line_orientation(
10973 0, line_orientation[5]);
10974 new_quads[3]->set_line_orientation(
10975 1, line_orientation[9]);
10976 new_quads[3]->set_line_orientation(
10977 3, line_orientation[3]);
10978
10979 // the quads are numbered as follows:
10980 //
10981 // planes in the interior of the old hex:
10982 //
10983 // *
10984 // /|
10985 // / | x
10986 // /3 * *-------* *----*----*
10987 // * /| | | / / /
10988 // | / | | | / 0 / 1 /
10989 // |/ * | | / / /
10990 // * 2/ *-------*y *----*----*x
10991 // | /
10992 // |/
10993 // *
10994 //
10995 // children of the faces
10996 // of the old hex
10997 // *---*---* *---*---*
10998 // /|13 | 15| / / /|
10999 // / | | | /18 / 19/ |
11000 // / *---*---* / / / *
11001 // * 5/| | | *---*---* 7/|
11002 // | / |12 | 14| | 9 | 11| / |
11003 // |/4 *---*---* | | |/6 *
11004 // * / / / *---*---* /
11005 // | /16 / 17/ | | | /
11006 // |/ / / | 8 | 10|/
11007 // *---*---* *---*---*
11008 //
11009 // note that we have to take care of the
11010 // orientation of faces.
11011 const int quad_indices[20] = {
11012 new_quads[0]->index(), // 0
11013 new_quads[1]->index(),
11014 new_quads[2]->index(),
11015 new_quads[3]->index(),
11016
11017 hex->face(0)->child_index(
11018 child_at_origin[hex->face(0)->refinement_case() -
11019 1][f_fl[0]][f_ro[0]]), // 4
11020 hex->face(0)->child_index(
11021 1 -
11022 child_at_origin[hex->face(0)->refinement_case() -
11023 1][f_fl[0]][f_ro[0]]),
11024
11025 hex->face(1)->child_index(
11026 child_at_origin[hex->face(1)->refinement_case() -
11027 1][f_fl[1]][f_ro[1]]), // 6
11028 hex->face(1)->child_index(
11029 1 -
11030 child_at_origin[hex->face(1)->refinement_case() -
11031 1][f_fl[1]][f_ro[1]]),
11032
11033 hex->face(2)->isotropic_child_index(
11035 0, f_or[2], f_fl[2], f_ro[2])), // 8
11036 hex->face(2)->isotropic_child_index(
11038 1, f_or[2], f_fl[2], f_ro[2])),
11039 hex->face(2)->isotropic_child_index(
11041 2, f_or[2], f_fl[2], f_ro[2])),
11042 hex->face(2)->isotropic_child_index(
11044 3, f_or[2], f_fl[2], f_ro[2])),
11045
11046 hex->face(3)->isotropic_child_index(
11048 0, f_or[3], f_fl[3], f_ro[3])), // 12
11049 hex->face(3)->isotropic_child_index(
11051 1, f_or[3], f_fl[3], f_ro[3])),
11052 hex->face(3)->isotropic_child_index(
11054 2, f_or[3], f_fl[3], f_ro[3])),
11055 hex->face(3)->isotropic_child_index(
11057 3, f_or[3], f_fl[3], f_ro[3])),
11058
11059 hex->face(4)->child_index(
11060 child_at_origin[hex->face(4)->refinement_case() -
11061 1][f_fl[4]][f_ro[4]]), // 16
11062 hex->face(4)->child_index(
11063 1 -
11064 child_at_origin[hex->face(4)->refinement_case() -
11065 1][f_fl[4]][f_ro[4]]),
11066
11067 hex->face(5)->child_index(
11068 child_at_origin[hex->face(5)->refinement_case() -
11069 1][f_fl[5]][f_ro[5]]), // 18
11070 hex->face(5)->child_index(
11071 1 -
11072 child_at_origin[hex->face(5)->refinement_case() -
11073 1][f_fl[5]][f_ro[5]])};
11074
11075 // due to the exchange of x and y for the front
11076 // and back face, we order the children
11077 // according to
11078 //
11079 // *---*---*
11080 // | 1 | 3 |
11081 // *---*---*
11082 // | 0 | 2 |
11083 // *---*---*
11084 new_hexes[0]->set_bounding_object_indices(
11085 {quad_indices[4],
11086 quad_indices[2],
11087 quad_indices[8],
11088 quad_indices[12],
11089 quad_indices[16],
11090 quad_indices[0]});
11091 new_hexes[1]->set_bounding_object_indices(
11092 {quad_indices[5],
11093 quad_indices[3],
11094 quad_indices[9],
11095 quad_indices[13],
11096 quad_indices[0],
11097 quad_indices[18]});
11098 new_hexes[2]->set_bounding_object_indices(
11099 {quad_indices[2],
11100 quad_indices[6],
11101 quad_indices[10],
11102 quad_indices[14],
11103 quad_indices[17],
11104 quad_indices[1]});
11105 new_hexes[3]->set_bounding_object_indices(
11106 {quad_indices[3],
11107 quad_indices[7],
11108 quad_indices[11],
11109 quad_indices[15],
11110 quad_indices[1],
11111 quad_indices[19]});
11112 break;
11113 }
11114
11116 {
11117 //----------------------------
11118 //
11119 // RefinementCase<dim>::cut_yz
11120 //
11121 // the refined cube will look like this:
11122 //
11123 // *---------*
11124 // / /|
11125 // *---------* |
11126 // / /| |
11127 // *---------* |/|
11128 // | | * |
11129 // | |/| *
11130 // *---------* |/
11131 // | | *
11132 // | |/
11133 // *---------*
11134 //
11135
11136 // first, create the new
11137 // internal line
11138 new_lines[0]->set_bounding_object_indices(
11139
11140 {middle_vertex_index<dim, spacedim>(hex->face(0)),
11141 middle_vertex_index<dim, spacedim>(hex->face(1))});
11142
11143 // again, first collect some data about the
11144 // indices of the lines, with the following
11145 // numbering: (note that face 0 and 1 each are
11146 // shown twice for better readability)
11147
11148 // face 0: left plane
11149 // * *
11150 // /| /|
11151 // * | * |
11152 // /| * /| *
11153 // * 5/| * |7|
11154 // | * | | * |
11155 // |/| * |6| *
11156 // * 4/ * |/
11157 // | * | *
11158 // |/ |/
11159 // * *
11160 // face 1: right plane
11161 // * *
11162 // /| /|
11163 // * | * |
11164 // /| * /| *
11165 // * 9/| * |11
11166 // | * | | * |
11167 // |/| * |10 *
11168 // * 8/ * |/
11169 // | * | *
11170 // |/ |/
11171 // * *
11172 // face 2: front plane
11173 // (note: x,y exchanged)
11174 // *-------*
11175 // | |
11176 // *---0---*
11177 // | |
11178 // *-------*
11179 // face 3: back plane
11180 // (note: x,y exchanged)
11181 // *-------*
11182 // | |
11183 // *---1---*
11184 // | |
11185 // *-------*
11186 // face 4: bottom plane
11187 // *-------*
11188 // / /
11189 // *---2---*
11190 // / /
11191 // *-------*
11192 // face 5: top plane
11193 // *-------*
11194 // / /
11195 // *---3---*
11196 // / /
11197 // *-------*
11198 // middle planes
11199 // *-------* *-------*
11200 // / / | |
11201 // *---12--* | |
11202 // / / | |
11203 // *-------* *-------*
11204
11205 // set up a list of line iterators first. from
11206 // this, construct lists of line_indices and
11207 // line orientations later on
11208 const typename Triangulation<
11209 dim,
11210 spacedim>::raw_line_iterator lines[13] = {
11211 hex->face(2)->child(0)->line(
11212 (hex->face(2)->refinement_case() ==
11214 1 :
11215 3), // 0
11216 hex->face(3)->child(0)->line(
11217 (hex->face(3)->refinement_case() ==
11219 1 :
11220 3), // 1
11221 hex->face(4)->child(0)->line(
11222 (hex->face(4)->refinement_case() ==
11224 1 :
11225 3), // 2
11226 hex->face(5)->child(0)->line(
11227 (hex->face(5)->refinement_case() ==
11229 1 :
11230 3), // 3
11231
11232 hex->face(0)
11233 ->isotropic_child(
11235 0, f_or[0], f_fl[0], f_ro[0]))
11236 ->line(
11238 1, f_or[0], f_fl[0], f_ro[0])), // 4
11239 hex->face(0)
11240 ->isotropic_child(
11242 3, f_or[0], f_fl[0], f_ro[0]))
11243 ->line(
11245 0, f_or[0], f_fl[0], f_ro[0])), // 5
11246 hex->face(0)
11247 ->isotropic_child(
11249 0, f_or[0], f_fl[0], f_ro[0]))
11250 ->line(
11252 3, f_or[0], f_fl[0], f_ro[0])), // 6
11253 hex->face(0)
11254 ->isotropic_child(
11256 3, f_or[0], f_fl[0], f_ro[0]))
11257 ->line(
11259 2, f_or[0], f_fl[0], f_ro[0])), // 7
11260
11261 hex->face(1)
11262 ->isotropic_child(
11264 0, f_or[1], f_fl[1], f_ro[1]))
11265 ->line(
11267 1, f_or[1], f_fl[1], f_ro[1])), // 8
11268 hex->face(1)
11269 ->isotropic_child(
11271 3, f_or[1], f_fl[1], f_ro[1]))
11272 ->line(
11274 0, f_or[1], f_fl[1], f_ro[1])), // 9
11275 hex->face(1)
11276 ->isotropic_child(
11278 0, f_or[1], f_fl[1], f_ro[1]))
11279 ->line(
11281 3, f_or[1], f_fl[1], f_ro[1])), // 10
11282 hex->face(1)
11283 ->isotropic_child(
11285 3, f_or[1], f_fl[1], f_ro[1]))
11286 ->line(
11288 2, f_or[1], f_fl[1], f_ro[1])), // 11
11289
11290 new_lines[0] // 12
11291 };
11292
11293 int line_indices[13];
11294 for (unsigned int i = 0; i < 13; ++i)
11295 line_indices[i] = lines[i]->index();
11296
11297 // the orientation of lines for the inner quads
11298 // is quite tricky. as these lines are newly
11299 // created ones and thus have no parents, they
11300 // cannot inherit this property. set up an array
11301 // and fill it with the respective values
11302 types::geometric_orientation line_orientation[13]{};
11303
11304 // the middle vertices of the lines of our front
11305 // face
11306 const unsigned int middle_vertices[4] = {
11307 hex->line(8)->child(0)->vertex_index(1),
11308 hex->line(10)->child(0)->vertex_index(1),
11309 hex->line(0)->child(0)->vertex_index(1),
11310 hex->line(4)->child(0)->vertex_index(1),
11311 };
11312
11313 // note: for lines 0 to 3 the orientation of the
11314 // line is 'true', if vertex 0 is on the front
11315 for (unsigned int i = 0; i < 4; ++i)
11316 if (lines[i]->vertex_index(0) == middle_vertices[i])
11317 line_orientation[i] =
11319 else
11320 {
11321 // it must be the other way round then
11322 Assert(lines[i]->vertex_index(1) ==
11323 middle_vertices[i],
11325 line_orientation[i] =
11327 }
11328
11329 // note: for lines 4 to 11 (inner lines of the
11330 // outer quads) the following holds: the second
11331 // vertex of the even lines in standard
11332 // orientation is the vertex in the middle of
11333 // the quad, whereas for odd lines the first
11334 // vertex is the same middle vertex.
11335 for (unsigned int i = 4; i < 12; ++i)
11336 if (lines[i]->vertex_index((i + 1) % 2) ==
11337 middle_vertex_index<dim, spacedim>(
11338 hex->face(i / 4 - 1)))
11339 line_orientation[i] =
11341 else
11342 {
11343 // it must be the other way round then
11344 Assert(lines[i]->vertex_index(i % 2) ==
11345 (middle_vertex_index<dim, spacedim>(
11346 hex->face(i / 4 - 1))),
11348 line_orientation[i] =
11350 }
11351 // for the last line the line orientation is always
11352 // the default, since it was just constructed that way
11353 line_orientation[12] =
11355
11356 // set up the 4 quads, numbered as follows (left
11357 // quad numbering, right line numbering
11358 // extracted from above)
11359 //
11360 // x
11361 // *-------* *---3---*
11362 // | 3 | 5 9
11363 // *-------* *---12--*
11364 // | 2 | 4 8
11365 // *-------*y *---2---*
11366 //
11367 // y
11368 // *---------* *----1----*
11369 // / 1 / 7 11
11370 // *---------* *----12---*
11371 // / 0 / 6 10
11372 // *---------*x *----0----*
11373
11374 new_quads[0]->set_bounding_object_indices(
11375 {line_indices[6],
11376 line_indices[10],
11377 line_indices[0],
11378 line_indices[12]});
11379 new_quads[1]->set_bounding_object_indices(
11380 {line_indices[7],
11381 line_indices[11],
11382 line_indices[12],
11383 line_indices[1]});
11384 new_quads[2]->set_bounding_object_indices(
11385 {line_indices[2],
11386 line_indices[12],
11387 line_indices[4],
11388 line_indices[8]});
11389 new_quads[3]->set_bounding_object_indices(
11390 {line_indices[12],
11391 line_indices[3],
11392 line_indices[5],
11393 line_indices[9]});
11394
11395 new_quads[0]->set_line_orientation(
11396 0, line_orientation[6]);
11397 new_quads[0]->set_line_orientation(
11398 1, line_orientation[10]);
11399 new_quads[0]->set_line_orientation(
11400 2, line_orientation[0]);
11401
11402 new_quads[1]->set_line_orientation(
11403 0, line_orientation[7]);
11404 new_quads[1]->set_line_orientation(
11405 1, line_orientation[11]);
11406 new_quads[1]->set_line_orientation(
11407 3, line_orientation[1]);
11408
11409 new_quads[2]->set_line_orientation(
11410 0, line_orientation[2]);
11411 new_quads[2]->set_line_orientation(
11412 2, line_orientation[4]);
11413 new_quads[2]->set_line_orientation(
11414 3, line_orientation[8]);
11415
11416 new_quads[3]->set_line_orientation(
11417 1, line_orientation[3]);
11418 new_quads[3]->set_line_orientation(
11419 2, line_orientation[5]);
11420 new_quads[3]->set_line_orientation(
11421 3, line_orientation[9]);
11422
11423 // the quads are numbered as follows:
11424 //
11425 // planes in the interior of the old hex:
11426 //
11427 // *
11428 // /|
11429 // / | x
11430 // / | *-------* *---------*
11431 // * | | 3 | / 1 /
11432 // | | *-------* *---------*
11433 // | * | 2 | / 0 /
11434 // | / *-------*y *---------*x
11435 // | /
11436 // |/
11437 // *
11438 //
11439 // children of the faces
11440 // of the old hex
11441 // *-------* *-------*
11442 // /| | / 19 /|
11443 // * | 15 | *-------* |
11444 // /|7*-------* / 18 /|11
11445 // * |/| | *-------* |/|
11446 // |6* | 14 | | 10* |
11447 // |/|5*-------* | 13 |/|9*
11448 // * |/ 17 / *-------* |/
11449 // |4*-------* | |8*
11450 // |/ 16 / | 12 |/
11451 // *-------* *-------*
11452 //
11453 // note that we have to take care of the
11454 // orientation of faces.
11455 const int quad_indices[20] = {
11456 new_quads[0]->index(), // 0
11457 new_quads[1]->index(),
11458 new_quads[2]->index(),
11459 new_quads[3]->index(),
11460
11461 hex->face(0)->isotropic_child_index(
11463 0, f_or[0], f_fl[0], f_ro[0])), // 4
11464 hex->face(0)->isotropic_child_index(
11466 1, f_or[0], f_fl[0], f_ro[0])),
11467 hex->face(0)->isotropic_child_index(
11469 2, f_or[0], f_fl[0], f_ro[0])),
11470 hex->face(0)->isotropic_child_index(
11472 3, f_or[0], f_fl[0], f_ro[0])),
11473
11474 hex->face(1)->isotropic_child_index(
11476 0, f_or[1], f_fl[1], f_ro[1])), // 8
11477 hex->face(1)->isotropic_child_index(
11479 1, f_or[1], f_fl[1], f_ro[1])),
11480 hex->face(1)->isotropic_child_index(
11482 2, f_or[1], f_fl[1], f_ro[1])),
11483 hex->face(1)->isotropic_child_index(
11485 3, f_or[1], f_fl[1], f_ro[1])),
11486
11487 hex->face(2)->child_index(
11488 child_at_origin[hex->face(2)->refinement_case() -
11489 1][f_fl[2]][f_ro[2]]), // 12
11490 hex->face(2)->child_index(
11491 1 -
11492 child_at_origin[hex->face(2)->refinement_case() -
11493 1][f_fl[2]][f_ro[2]]),
11494
11495 hex->face(3)->child_index(
11496 child_at_origin[hex->face(3)->refinement_case() -
11497 1][f_fl[3]][f_ro[3]]), // 14
11498 hex->face(3)->child_index(
11499 1 -
11500 child_at_origin[hex->face(3)->refinement_case() -
11501 1][f_fl[3]][f_ro[3]]),
11502
11503 hex->face(4)->child_index(
11504 child_at_origin[hex->face(4)->refinement_case() -
11505 1][f_fl[4]][f_ro[4]]), // 16
11506 hex->face(4)->child_index(
11507 1 -
11508 child_at_origin[hex->face(4)->refinement_case() -
11509 1][f_fl[4]][f_ro[4]]),
11510
11511 hex->face(5)->child_index(
11512 child_at_origin[hex->face(5)->refinement_case() -
11513 1][f_fl[5]][f_ro[5]]), // 18
11514 hex->face(5)->child_index(
11515 1 -
11516 child_at_origin[hex->face(5)->refinement_case() -
11517 1][f_fl[5]][f_ro[5]])};
11518
11519 new_hexes[0]->set_bounding_object_indices(
11520 {quad_indices[4],
11521 quad_indices[8],
11522 quad_indices[12],
11523 quad_indices[2],
11524 quad_indices[16],
11525 quad_indices[0]});
11526 new_hexes[1]->set_bounding_object_indices(
11527 {quad_indices[5],
11528 quad_indices[9],
11529 quad_indices[2],
11530 quad_indices[14],
11531 quad_indices[17],
11532 quad_indices[1]});
11533 new_hexes[2]->set_bounding_object_indices(
11534 {quad_indices[6],
11535 quad_indices[10],
11536 quad_indices[13],
11537 quad_indices[3],
11538 quad_indices[0],
11539 quad_indices[18]});
11540 new_hexes[3]->set_bounding_object_indices(
11541 {quad_indices[7],
11542 quad_indices[11],
11543 quad_indices[3],
11544 quad_indices[15],
11545 quad_indices[1],
11546 quad_indices[19]});
11547 break;
11548 }
11549
11551 {
11552 //----------------------------
11553 //
11554 // RefinementCase<dim>::cut_xyz
11555 // isotropic refinement
11556 //
11557 // the refined cube will look
11558 // like this:
11559 //
11560 // *----*----*
11561 // / / /|
11562 // *----*----* |
11563 // / / /| *
11564 // *----*----* |/|
11565 // | | | * |
11566 // | | |/| *
11567 // *----*----* |/
11568 // | | | *
11569 // | | |/
11570 // *----*----*
11571 //
11572
11573 // find the next unused vertex and set it
11574 // appropriately
11575 while (
11576 triangulation.vertices_used[next_unused_vertex] ==
11577 true)
11578 ++next_unused_vertex;
11579 Assert(
11580 next_unused_vertex < triangulation.vertices.size(),
11581 ExcMessage(
11582 "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."));
11583 triangulation.vertices_used[next_unused_vertex] =
11584 true;
11585
11586 // the new vertex is definitely in the interior,
11587 // so we need not worry about the
11588 // boundary. However we need to worry about
11589 // Manifolds. Let the cell compute its own
11590 // center, by querying the underlying manifold
11591 // object.
11592 triangulation.vertices[next_unused_vertex] =
11593 hex->center(true, true);
11594
11595 // set the data of the six lines. first collect
11596 // the indices of the seven vertices (consider
11597 // the two planes to be crossed to form the
11598 // planes cutting the hex in two vertically and
11599 // horizontally)
11600 //
11601 // *--3--* *--5--*
11602 // / / / | | |
11603 // 0--6--1 0--6--1
11604 // / / / | | |
11605 // *--2--* *--4--*
11606 // the lines are numbered
11607 // as follows:
11608 // *--*--* *--*--*
11609 // / 1 / | 5 |
11610 // *2-*-3* *2-*-3*
11611 // / 0 / | 4 |
11612 // *--*--* *--*--*
11613 //
11614 const unsigned int vertex_indices[7] = {
11615 middle_vertex_index<dim, spacedim>(hex->face(0)),
11616 middle_vertex_index<dim, spacedim>(hex->face(1)),
11617 middle_vertex_index<dim, spacedim>(hex->face(2)),
11618 middle_vertex_index<dim, spacedim>(hex->face(3)),
11619 middle_vertex_index<dim, spacedim>(hex->face(4)),
11620 middle_vertex_index<dim, spacedim>(hex->face(5)),
11621 next_unused_vertex};
11622
11623 new_lines[0]->set_bounding_object_indices(
11625 new_lines[1]->set_bounding_object_indices(
11627 new_lines[2]->set_bounding_object_indices(
11629 new_lines[3]->set_bounding_object_indices(
11631 new_lines[4]->set_bounding_object_indices(
11633 new_lines[5]->set_bounding_object_indices(
11635
11636 // again, first collect some data about the
11637 // indices of the lines, with the following
11638 // numbering: (note that face 0 and 1 each are
11639 // shown twice for better readability)
11640
11641 // face 0: left plane
11642 // * *
11643 // /| /|
11644 // * | * |
11645 // /| * /| *
11646 // * 1/| * |3|
11647 // | * | | * |
11648 // |/| * |2| *
11649 // * 0/ * |/
11650 // | * | *
11651 // |/ |/
11652 // * *
11653 // face 1: right plane
11654 // * *
11655 // /| /|
11656 // * | * |
11657 // /| * /| *
11658 // * 5/| * |7|
11659 // | * | | * |
11660 // |/| * |6| *
11661 // * 4/ * |/
11662 // | * | *
11663 // |/ |/
11664 // * *
11665 // face 2: front plane
11666 // (note: x,y exchanged)
11667 // *---*---*
11668 // | 11 |
11669 // *-8-*-9-*
11670 // | 10 |
11671 // *---*---*
11672 // face 3: back plane
11673 // (note: x,y exchanged)
11674 // *---*---*
11675 // | 15 |
11676 // *12-*-13*
11677 // | 14 |
11678 // *---*---*
11679 // face 4: bottom plane
11680 // *---*---*
11681 // / 17 /
11682 // *18-*-19*
11683 // / 16 /
11684 // *---*---*
11685 // face 5: top plane
11686 // *---*---*
11687 // / 21 /
11688 // *22-*-23*
11689 // / 20 /
11690 // *---*---*
11691 // middle planes
11692 // *---*---* *---*---*
11693 // / 25 / | 29 |
11694 // *26-*-27* *26-*-27*
11695 // / 24 / | 28 |
11696 // *---*---* *---*---*
11697
11698 // set up a list of line iterators first. from
11699 // this, construct lists of line_indices and
11700 // line orientations later on
11701 const typename Triangulation<
11702 dim,
11703 spacedim>::raw_line_iterator lines[30] = {
11704 hex->face(0)
11705 ->isotropic_child(
11707 0, f_or[0], f_fl[0], f_ro[0]))
11708 ->line(
11710 1, f_or[0], f_fl[0], f_ro[0])), // 0
11711 hex->face(0)
11712 ->isotropic_child(
11714 3, f_or[0], f_fl[0], f_ro[0]))
11715 ->line(
11717 0, f_or[0], f_fl[0], f_ro[0])), // 1
11718 hex->face(0)
11719 ->isotropic_child(
11721 0, f_or[0], f_fl[0], f_ro[0]))
11722 ->line(
11724 3, f_or[0], f_fl[0], f_ro[0])), // 2
11725 hex->face(0)
11726 ->isotropic_child(
11728 3, f_or[0], f_fl[0], f_ro[0]))
11729 ->line(
11731 2, f_or[0], f_fl[0], f_ro[0])), // 3
11732
11733 hex->face(1)
11734 ->isotropic_child(
11736 0, f_or[1], f_fl[1], f_ro[1]))
11737 ->line(
11739 1, f_or[1], f_fl[1], f_ro[1])), // 4
11740 hex->face(1)
11741 ->isotropic_child(
11743 3, f_or[1], f_fl[1], f_ro[1]))
11744 ->line(
11746 0, f_or[1], f_fl[1], f_ro[1])), // 5
11747 hex->face(1)
11748 ->isotropic_child(
11750 0, f_or[1], f_fl[1], f_ro[1]))
11751 ->line(
11753 3, f_or[1], f_fl[1], f_ro[1])), // 6
11754 hex->face(1)
11755 ->isotropic_child(
11757 3, f_or[1], f_fl[1], f_ro[1]))
11758 ->line(
11760 2, f_or[1], f_fl[1], f_ro[1])), // 7
11761
11762 hex->face(2)
11763 ->isotropic_child(
11765 0, f_or[2], f_fl[2], f_ro[2]))
11766 ->line(
11768 1, f_or[2], f_fl[2], f_ro[2])), // 8
11769 hex->face(2)
11770 ->isotropic_child(
11772 3, f_or[2], f_fl[2], f_ro[2]))
11773 ->line(
11775 0, f_or[2], f_fl[2], f_ro[2])), // 9
11776 hex->face(2)
11777 ->isotropic_child(
11779 0, f_or[2], f_fl[2], f_ro[2]))
11780 ->line(
11782 3, f_or[2], f_fl[2], f_ro[2])), // 10
11783 hex->face(2)
11784 ->isotropic_child(
11786 3, f_or[2], f_fl[2], f_ro[2]))
11787 ->line(
11789 2, f_or[2], f_fl[2], f_ro[2])), // 11
11790
11791 hex->face(3)
11792 ->isotropic_child(
11794 0, f_or[3], f_fl[3], f_ro[3]))
11795 ->line(
11797 1, f_or[3], f_fl[3], f_ro[3])), // 12
11798 hex->face(3)
11799 ->isotropic_child(
11801 3, f_or[3], f_fl[3], f_ro[3]))
11802 ->line(
11804 0, f_or[3], f_fl[3], f_ro[3])), // 13
11805 hex->face(3)
11806 ->isotropic_child(
11808 0, f_or[3], f_fl[3], f_ro[3]))
11809 ->line(
11811 3, f_or[3], f_fl[3], f_ro[3])), // 14
11812 hex->face(3)
11813 ->isotropic_child(
11815 3, f_or[3], f_fl[3], f_ro[3]))
11816 ->line(
11818 2, f_or[3], f_fl[3], f_ro[3])), // 15
11819
11820 hex->face(4)
11821 ->isotropic_child(
11823 0, f_or[4], f_fl[4], f_ro[4]))
11824 ->line(
11826 1, f_or[4], f_fl[4], f_ro[4])), // 16
11827 hex->face(4)
11828 ->isotropic_child(
11830 3, f_or[4], f_fl[4], f_ro[4]))
11831 ->line(
11833 0, f_or[4], f_fl[4], f_ro[4])), // 17
11834 hex->face(4)
11835 ->isotropic_child(
11837 0, f_or[4], f_fl[4], f_ro[4]))
11838 ->line(
11840 3, f_or[4], f_fl[4], f_ro[4])), // 18
11841 hex->face(4)
11842 ->isotropic_child(
11844 3, f_or[4], f_fl[4], f_ro[4]))
11845 ->line(
11847 2, f_or[4], f_fl[4], f_ro[4])), // 19
11848
11849 hex->face(5)
11850 ->isotropic_child(
11852 0, f_or[5], f_fl[5], f_ro[5]))
11853 ->line(
11855 1, f_or[5], f_fl[5], f_ro[5])), // 20
11856 hex->face(5)
11857 ->isotropic_child(
11859 3, f_or[5], f_fl[5], f_ro[5]))
11860 ->line(
11862 0, f_or[5], f_fl[5], f_ro[5])), // 21
11863 hex->face(5)
11864 ->isotropic_child(
11866 0, f_or[5], f_fl[5], f_ro[5]))
11867 ->line(
11869 3, f_or[5], f_fl[5], f_ro[5])), // 22
11870 hex->face(5)
11871 ->isotropic_child(
11873 3, f_or[5], f_fl[5], f_ro[5]))
11874 ->line(
11876 2, f_or[5], f_fl[5], f_ro[5])), // 23
11877
11878 new_lines[0], // 24
11879 new_lines[1], // 25
11880 new_lines[2], // 26
11881 new_lines[3], // 27
11882 new_lines[4], // 28
11883 new_lines[5] // 29
11884 };
11885
11886 int line_indices[30];
11887 for (unsigned int i = 0; i < 30; ++i)
11888 line_indices[i] = lines[i]->index();
11889
11890 // the orientation of lines for the inner quads
11891 // is quite tricky. as these lines are newly
11892 // created ones and thus have no parents, they
11893 // cannot inherit this property. set up an array
11894 // and fill it with the respective values
11895 types::geometric_orientation line_orientation[30]{};
11896
11897 // note: for the first 24 lines (inner lines of
11898 // the outer quads) the following holds: the
11899 // second vertex of the even lines in standard
11900 // orientation is the vertex in the middle of
11901 // the quad, whereas for odd lines the first
11902 // vertex is the same middle vertex.
11903 for (unsigned int i = 0; i < 24; ++i)
11904 if (lines[i]->vertex_index((i + 1) % 2) ==
11905 vertex_indices[i / 4])
11906 line_orientation[i] =
11908 else
11909 {
11910 // it must be the other way
11911 // round then
11912 Assert(lines[i]->vertex_index(i % 2) ==
11913 vertex_indices[i / 4],
11915 line_orientation[i] =
11917 }
11918 // for the last 6 lines the line orientation is
11919 // always true, since they were just constructed
11920 // that way
11921 for (unsigned int i = 24; i < 30; ++i)
11922 line_orientation[i] =
11924
11925 // set up the 12 quads, numbered as follows
11926 // (left quad numbering, right line numbering
11927 // extracted from above)
11928 //
11929 // * *
11930 // /| 21|
11931 // * | * 15
11932 // y/|3* 20| *
11933 // * |/| * |/|
11934 // |2* |x 11 * 14
11935 // |/|1* |/| *
11936 // * |/ * |17
11937 // |0* 10 *
11938 // |/ |16
11939 // * *
11940 //
11941 // x
11942 // *---*---* *22-*-23*
11943 // | 5 | 7 | 1 29 5
11944 // *---*---* *26-*-27*
11945 // | 4 | 6 | 0 28 4
11946 // *---*---*y *18-*-19*
11947 //
11948 // y
11949 // *----*----* *-12-*-13-*
11950 // / 10 / 11 / 3 25 7
11951 // *----*----* *-26-*-27-*
11952 // / 8 / 9 / 2 24 6
11953 // *----*----*x *--8-*--9-*
11954
11955 new_quads[0]->set_bounding_object_indices(
11956 {line_indices[10],
11957 line_indices[28],
11958 line_indices[16],
11959 line_indices[24]});
11960 new_quads[1]->set_bounding_object_indices(
11961 {line_indices[28],
11962 line_indices[14],
11963 line_indices[17],
11964 line_indices[25]});
11965 new_quads[2]->set_bounding_object_indices(
11966 {line_indices[11],
11967 line_indices[29],
11968 line_indices[24],
11969 line_indices[20]});
11970 new_quads[3]->set_bounding_object_indices(
11971 {line_indices[29],
11972 line_indices[15],
11973 line_indices[25],
11974 line_indices[21]});
11975 new_quads[4]->set_bounding_object_indices(
11976 {line_indices[18],
11977 line_indices[26],
11978 line_indices[0],
11979 line_indices[28]});
11980 new_quads[5]->set_bounding_object_indices(
11981 {line_indices[26],
11982 line_indices[22],
11983 line_indices[1],
11984 line_indices[29]});
11985 new_quads[6]->set_bounding_object_indices(
11986 {line_indices[19],
11987 line_indices[27],
11988 line_indices[28],
11989 line_indices[4]});
11990 new_quads[7]->set_bounding_object_indices(
11991 {line_indices[27],
11992 line_indices[23],
11993 line_indices[29],
11994 line_indices[5]});
11995 new_quads[8]->set_bounding_object_indices(
11996 {line_indices[2],
11997 line_indices[24],
11998 line_indices[8],
11999 line_indices[26]});
12000 new_quads[9]->set_bounding_object_indices(
12001 {line_indices[24],
12002 line_indices[6],
12003 line_indices[9],
12004 line_indices[27]});
12005 new_quads[10]->set_bounding_object_indices(
12006 {line_indices[3],
12007 line_indices[25],
12008 line_indices[26],
12009 line_indices[12]});
12010 new_quads[11]->set_bounding_object_indices(
12011 {line_indices[25],
12012 line_indices[7],
12013 line_indices[27],
12014 line_indices[13]});
12015
12016 // now reset the line_orientation flags of outer
12017 // lines as they cannot be set in a loop (at
12018 // least not easily)
12019 new_quads[0]->set_line_orientation(
12020 0, line_orientation[10]);
12021 new_quads[0]->set_line_orientation(
12022 2, line_orientation[16]);
12023
12024 new_quads[1]->set_line_orientation(
12025 1, line_orientation[14]);
12026 new_quads[1]->set_line_orientation(
12027 2, line_orientation[17]);
12028
12029 new_quads[2]->set_line_orientation(
12030 0, line_orientation[11]);
12031 new_quads[2]->set_line_orientation(
12032 3, line_orientation[20]);
12033
12034 new_quads[3]->set_line_orientation(
12035 1, line_orientation[15]);
12036 new_quads[3]->set_line_orientation(
12037 3, line_orientation[21]);
12038
12039 new_quads[4]->set_line_orientation(
12040 0, line_orientation[18]);
12041 new_quads[4]->set_line_orientation(
12042 2, line_orientation[0]);
12043
12044 new_quads[5]->set_line_orientation(
12045 1, line_orientation[22]);
12046 new_quads[5]->set_line_orientation(
12047 2, line_orientation[1]);
12048
12049 new_quads[6]->set_line_orientation(
12050 0, line_orientation[19]);
12051 new_quads[6]->set_line_orientation(
12052 3, line_orientation[4]);
12053
12054 new_quads[7]->set_line_orientation(
12055 1, line_orientation[23]);
12056 new_quads[7]->set_line_orientation(
12057 3, line_orientation[5]);
12058
12059 new_quads[8]->set_line_orientation(
12060 0, line_orientation[2]);
12061 new_quads[8]->set_line_orientation(
12062 2, line_orientation[8]);
12063
12064 new_quads[9]->set_line_orientation(
12065 1, line_orientation[6]);
12066 new_quads[9]->set_line_orientation(
12067 2, line_orientation[9]);
12068
12069 new_quads[10]->set_line_orientation(
12070 0, line_orientation[3]);
12071 new_quads[10]->set_line_orientation(
12072 3, line_orientation[12]);
12073
12074 new_quads[11]->set_line_orientation(
12075 1, line_orientation[7]);
12076 new_quads[11]->set_line_orientation(
12077 3, line_orientation[13]);
12078
12079 //-------------------------------
12080 // create the eight new hexes
12081 //
12082 // again first collect some data. here, we need
12083 // the indices of a whole lotta quads.
12084
12085 // the quads are numbered as follows:
12086 //
12087 // planes in the interior of the old hex:
12088 //
12089 // *
12090 // /|
12091 // * |
12092 // /|3* *---*---* *----*----*
12093 // * |/| | 5 | 7 | / 10 / 11 /
12094 // |2* | *---*---* *----*----*
12095 // |/|1* | 4 | 6 | / 8 / 9 /
12096 // * |/ *---*---*y *----*----*x
12097 // |0*
12098 // |/
12099 // *
12100 //
12101 // children of the faces
12102 // of the old hex
12103 // *-------* *-------*
12104 // /|25 27| /34 35/|
12105 // 15| | / /19
12106 // / | | /32 33/ |
12107 // * |24 26| *-------*18 |
12108 // 1413*-------* |21 23| 17*
12109 // | /30 31/ | | /
12110 // 12/ / | |16
12111 // |/28 29/ |20 22|/
12112 // *-------* *-------*
12113 //
12114 // note that we have to
12115 // take care of the
12116 // orientation of
12117 // faces.
12118 const int quad_indices[36] = {
12119 new_quads[0]->index(), // 0
12120 new_quads[1]->index(),
12121 new_quads[2]->index(),
12122 new_quads[3]->index(),
12123 new_quads[4]->index(),
12124 new_quads[5]->index(),
12125 new_quads[6]->index(),
12126 new_quads[7]->index(),
12127 new_quads[8]->index(),
12128 new_quads[9]->index(),
12129 new_quads[10]->index(),
12130 new_quads[11]->index(), // 11
12131
12132 hex->face(0)->isotropic_child_index(
12134 0, f_or[0], f_fl[0], f_ro[0])), // 12
12135 hex->face(0)->isotropic_child_index(
12137 1, f_or[0], f_fl[0], f_ro[0])),
12138 hex->face(0)->isotropic_child_index(
12140 2, f_or[0], f_fl[0], f_ro[0])),
12141 hex->face(0)->isotropic_child_index(
12143 3, f_or[0], f_fl[0], f_ro[0])),
12144
12145 hex->face(1)->isotropic_child_index(
12147 0, f_or[1], f_fl[1], f_ro[1])), // 16
12148 hex->face(1)->isotropic_child_index(
12150 1, f_or[1], f_fl[1], f_ro[1])),
12151 hex->face(1)->isotropic_child_index(
12153 2, f_or[1], f_fl[1], f_ro[1])),
12154 hex->face(1)->isotropic_child_index(
12156 3, f_or[1], f_fl[1], f_ro[1])),
12157
12158 hex->face(2)->isotropic_child_index(
12160 0, f_or[2], f_fl[2], f_ro[2])), // 20
12161 hex->face(2)->isotropic_child_index(
12163 1, f_or[2], f_fl[2], f_ro[2])),
12164 hex->face(2)->isotropic_child_index(
12166 2, f_or[2], f_fl[2], f_ro[2])),
12167 hex->face(2)->isotropic_child_index(
12169 3, f_or[2], f_fl[2], f_ro[2])),
12170
12171 hex->face(3)->isotropic_child_index(
12173 0, f_or[3], f_fl[3], f_ro[3])), // 24
12174 hex->face(3)->isotropic_child_index(
12176 1, f_or[3], f_fl[3], f_ro[3])),
12177 hex->face(3)->isotropic_child_index(
12179 2, f_or[3], f_fl[3], f_ro[3])),
12180 hex->face(3)->isotropic_child_index(
12182 3, f_or[3], f_fl[3], f_ro[3])),
12183
12184 hex->face(4)->isotropic_child_index(
12186 0, f_or[4], f_fl[4], f_ro[4])), // 28
12187 hex->face(4)->isotropic_child_index(
12189 1, f_or[4], f_fl[4], f_ro[4])),
12190 hex->face(4)->isotropic_child_index(
12192 2, f_or[4], f_fl[4], f_ro[4])),
12193 hex->face(4)->isotropic_child_index(
12195 3, f_or[4], f_fl[4], f_ro[4])),
12196
12197 hex->face(5)->isotropic_child_index(
12199 0, f_or[5], f_fl[5], f_ro[5])), // 32
12200 hex->face(5)->isotropic_child_index(
12202 1, f_or[5], f_fl[5], f_ro[5])),
12203 hex->face(5)->isotropic_child_index(
12205 2, f_or[5], f_fl[5], f_ro[5])),
12206 hex->face(5)->isotropic_child_index(
12208 3, f_or[5], f_fl[5], f_ro[5]))};
12209
12210 // bottom children
12211 new_hexes[0]->set_bounding_object_indices(
12212 {quad_indices[12],
12213 quad_indices[0],
12214 quad_indices[20],
12215 quad_indices[4],
12216 quad_indices[28],
12217 quad_indices[8]});
12218 new_hexes[1]->set_bounding_object_indices(
12219 {quad_indices[0],
12220 quad_indices[16],
12221 quad_indices[22],
12222 quad_indices[6],
12223 quad_indices[29],
12224 quad_indices[9]});
12225 new_hexes[2]->set_bounding_object_indices(
12226 {quad_indices[13],
12227 quad_indices[1],
12228 quad_indices[4],
12229 quad_indices[24],
12230 quad_indices[30],
12231 quad_indices[10]});
12232 new_hexes[3]->set_bounding_object_indices(
12233 {quad_indices[1],
12234 quad_indices[17],
12235 quad_indices[6],
12236 quad_indices[26],
12237 quad_indices[31],
12238 quad_indices[11]});
12239
12240 // top children
12241 new_hexes[4]->set_bounding_object_indices(
12242 {quad_indices[14],
12243 quad_indices[2],
12244 quad_indices[21],
12245 quad_indices[5],
12246 quad_indices[8],
12247 quad_indices[32]});
12248 new_hexes[5]->set_bounding_object_indices(
12249 {quad_indices[2],
12250 quad_indices[18],
12251 quad_indices[23],
12252 quad_indices[7],
12253 quad_indices[9],
12254 quad_indices[33]});
12255 new_hexes[6]->set_bounding_object_indices(
12256 {quad_indices[15],
12257 quad_indices[3],
12258 quad_indices[5],
12259 quad_indices[25],
12260 quad_indices[10],
12261 quad_indices[34]});
12262 new_hexes[7]->set_bounding_object_indices(
12263 {quad_indices[3],
12264 quad_indices[19],
12265 quad_indices[7],
12266 quad_indices[27],
12267 quad_indices[11],
12268 quad_indices[35]});
12269 break;
12270 }
12271 default:
12272 // all refinement cases have been treated, there
12273 // only remains
12274 // RefinementCase<dim>::no_refinement as
12275 // untreated enumeration value. However, in that
12276 // case we should have aborted much
12277 // earlier. thus we should never get here
12279 break;
12280 } // switch (ref_case)
12281
12282 // and set face orientation flags. note that new
12283 // faces in the interior of the mother cell always
12284 // have a correctly oriented face, but the ones on
12285 // the outer faces will inherit this flag
12286 //
12287 // the flag have been set to true for all faces
12288 // initially, now go the other way round and reset
12289 // faces that are at the boundary of the mother cube
12290 //
12291 // the same is true for the face_flip and
12292 // face_rotation flags. however, the latter two are
12293 // set to false by default as this is the standard
12294 // value
12295
12296 // loop over all faces and all (relevant) subfaces
12297 // of that in order to set the correct values for
12298 // face_orientation, face_flip and face_rotation,
12299 // which are inherited from the corresponding face
12300 // of the mother cube
12301 for (const unsigned int f : GeometryInfo<dim>::face_indices())
12302 for (unsigned int s = 0;
12305 ref_case, f)),
12306 1U);
12307 ++s)
12308 {
12309 const unsigned int current_child =
12311 ref_case,
12312 f,
12313 s,
12314 f_or[f],
12315 f_fl[f],
12316 f_ro[f],
12318 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
12319 new_hexes[current_child]->set_combined_face_orientation(
12320 f, f_co[f]);
12321 }
12322
12323 // now see if we have created cells that are
12324 // distorted and if so add them to our list
12325 if (check_for_distorted_cells &&
12326 has_distorted_children<dim, spacedim>(hex))
12327 cells_with_distorted_children.distorted_cells.push_back(
12328 hex);
12329
12330 // note that the refinement flag was already cleared
12331 // at the beginning of this loop
12332
12333 // inform all listeners that cell refinement is done
12334 triangulation.signals.post_refinement_on_cell(hex);
12335 }
12336 }
12337
12338 // clear user data on quads. we used some of this data to
12339 // indicate anisotropic refinemnt cases on faces. all data
12340 // should be cleared by now, but the information whether we
12341 // used indices or pointers is still present. reset it now to
12342 // enable the user to use whichever they like later on.
12343 triangulation.faces->quads.clear_user_data();
12344
12345 // return the list with distorted children
12346 return cells_with_distorted_children;
12347 }
12348
12349
12362 template <int spacedim>
12363 static void
12366
12367
12368
12369 template <int dim, int spacedim>
12370 static void
12372 Triangulation<dim, spacedim> &triangulation)
12373 {
12374 // If the codimension is one, we cannot perform this check
12375 // yet.
12376 if (spacedim > dim)
12377 return;
12378
12379 for (const auto &cell : triangulation.cell_iterators())
12380 if (cell->at_boundary() && cell->refine_flag_set() &&
12381 cell->refine_flag_set() !=
12383 {
12384 // The cell is at the boundary and it is flagged for
12385 // anisotropic refinement. Therefore, we have a closer
12386 // look
12387 const RefinementCase<dim> ref_case = cell->refine_flag_set();
12388 for (const unsigned int face_no :
12390 if (cell->face(face_no)->at_boundary())
12391 {
12392 // this is the critical face at the boundary.
12394 face_no) !=
12396 {
12397 // up to now, we do not want to refine this
12398 // cell along the face under consideration
12399 // here.
12400 const typename Triangulation<dim,
12401 spacedim>::face_iterator
12402 face = cell->face(face_no);
12403 // the new point on the boundary would be this
12404 // one.
12405 const Point<spacedim> new_bound = face->center(true);
12406 // to check it, transform to the unit cell
12407 // with a linear mapping
12408 const Point<dim> new_unit =
12409 cell->reference_cell()
12410 .template get_default_linear_mapping<spacedim>()
12411 .transform_real_to_unit_cell(cell, new_bound);
12412
12413 // Now, we have to calculate the distance from
12414 // the face in the unit cell.
12415
12416 // take the correct coordinate direction (0
12417 // for faces 0 and 1, 1 for faces 2 and 3, 2
12418 // for faces 4 and 5) and subtract the correct
12419 // boundary value of the face (0 for faces 0,
12420 // 2, and 4; 1 for faces 1, 3 and 5)
12421 const double dist =
12422 std::fabs(new_unit[face_no / 2] - face_no % 2);
12423
12424 // compare this with the empirical value
12425 // allowed. if it is too big, flag the face
12426 // for isotropic refinement
12427 const double allowed = 0.25;
12428
12429 if (dist > allowed)
12430 cell->flag_for_face_refinement(face_no);
12431 } // if flagged for anistropic refinement
12432 } // if (cell->face(face)->at_boundary())
12433 } // for all cells
12434 }
12435
12436
12449 template <int dim, int spacedim>
12450 static void
12452 {
12453 Assert(dim < 3,
12454 ExcMessage("Wrong function called -- there should "
12455 "be a specialization."));
12456 }
12457
12458
12459 template <int spacedim>
12460 static void
12462 Triangulation<3, spacedim> &triangulation)
12463 {
12464 const unsigned int dim = 3;
12465 using raw_line_iterator =
12467
12468 // variable to store whether the mesh was changed in the
12469 // present loop and in the whole process
12470 bool mesh_changed = false;
12471
12472 do
12473 {
12474 mesh_changed = false;
12475
12476 // for this following, we need to know which cells are
12477 // going to be coarsened, if we had to make a
12478 // decision. the following function sets these flags:
12479 triangulation.fix_coarsen_flags();
12480
12481 // first clear flags on lines, since we need them to determine
12482 // which lines will be refined
12483 triangulation.clear_user_flags_line();
12484
12485 // flag those lines that are refined and will not be
12486 // coarsened and those that will be refined
12487 for (const auto &cell : triangulation.cell_iterators())
12488 if (cell->refine_flag_set())
12489 {
12490 const std::array<unsigned int, 12> line_indices =
12491 TriaAccessorImplementation::Implementation::
12492 get_line_indices_of_cell(*cell);
12493 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12495 cell->refine_flag_set(), l) ==
12497 {
12498 raw_line_iterator line(&triangulation,
12499 0,
12500 line_indices[l]);
12501 // flag a line, that will be refined
12502 line->set_user_flag();
12503 }
12504 }
12505 else if (cell->has_children() &&
12506 !cell->child(0)->coarsen_flag_set())
12507 {
12508 const std::array<unsigned int, 12> line_indices =
12509 TriaAccessorImplementation::Implementation::
12510 get_line_indices_of_cell(*cell);
12511 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12513 cell->refinement_case(), l) ==
12515 {
12516 raw_line_iterator line(&triangulation,
12517 0,
12518 line_indices[l]);
12519 // flag a line, that is refined and will stay so
12520 line->set_user_flag();
12521 }
12522 }
12523 else if (cell->has_children() &&
12524 cell->child(0)->coarsen_flag_set())
12525 cell->set_user_flag();
12526
12527
12528 // now check whether there are cells with lines that are
12529 // more than once refined or that will be more than once
12530 // refined. The first thing should never be the case, in
12531 // the second case we flag the cell for refinement
12533 cell = triangulation.last_active();
12534 cell != triangulation.end();
12535 --cell)
12536 {
12537 const std::array<unsigned int, 12> line_indices =
12538 TriaAccessorImplementation::Implementation::
12539 get_line_indices_of_cell(*cell);
12540 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12541 {
12542 raw_line_iterator line(&triangulation, 0, line_indices[l]);
12543 if (line->has_children())
12544 {
12545 // if this line is refined, its children should
12546 // not have further children
12547 //
12548 // however, if any of the children is flagged
12549 // for further refinement, we need to refine
12550 // this cell also (at least, if the cell is not
12551 // already flagged)
12552 bool offending_line_found = false;
12553
12554 for (unsigned int c = 0; c < 2; ++c)
12555 {
12556 Assert(line->child(c)->has_children() == false,
12558
12559 if (line->child(c)->user_flag_set() &&
12561 cell->refine_flag_set(), l) ==
12563 {
12564 // tag this cell for refinement
12565 cell->clear_coarsen_flag();
12566 // if anisotropic coarsening is allowed:
12567 // extend the refine_flag in the needed
12568 // direction, else set refine_flag
12569 // (isotropic)
12570 if (triangulation.smooth_grid &
12572 allow_anisotropic_smoothing)
12573 cell->flag_for_line_refinement(l);
12574 else
12575 cell->set_refine_flag();
12576
12577 for (unsigned int k = 0; k < cell->n_lines();
12578 ++k)
12580 cell->refine_flag_set(), l) ==
12582 // flag a line, that will be refined
12583 raw_line_iterator(&triangulation,
12584 0,
12585 line_indices[k])
12586 ->set_user_flag();
12587
12588 // note that we have changed the grid
12589 offending_line_found = true;
12590
12591 // it may save us several loop
12592 // iterations if we flag all lines of
12593 // this cell now (and not at the outset
12594 // of the next iteration) for refinement
12595 for (unsigned int k = 0; k < cell->n_lines();
12596 ++k)
12597 {
12598 const auto line =
12599 raw_line_iterator(&triangulation,
12600 0,
12601 line_indices[k]);
12602 if (!line->has_children() &&
12604 line_refinement_case(
12605 cell->refine_flag_set(), k) !=
12607 line->set_user_flag();
12608 }
12609
12610 break;
12611 }
12612 }
12613
12614 if (offending_line_found)
12615 {
12616 mesh_changed = true;
12617 break;
12618 }
12619 }
12620 }
12621 }
12622
12623
12624 // there is another thing here: if any of the lines will
12625 // be refined, then we may not coarsen the present cell
12626 // similarly, if any of the lines *is* already refined, we
12627 // may not coarsen the current cell. however, there's a
12628 // catch: if the line is refined, but the cell behind it
12629 // is going to be coarsened, then the situation
12630 // changes. if we forget this second condition, the
12631 // refine_and_coarsen_3d test will start to fail. note
12632 // that to know which cells are going to be coarsened, the
12633 // call for fix_coarsen_flags above is necessary
12635 triangulation.last();
12636 cell != triangulation.end();
12637 --cell)
12638 if (cell->user_flag_set())
12639 {
12640 const std::array<unsigned int, 12> line_indices =
12641 TriaAccessorImplementation::Implementation::
12642 get_line_indices_of_cell(*cell);
12643 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12644 {
12645 raw_line_iterator line(&triangulation,
12646 0,
12647 line_indices[l]);
12648 if (line->has_children() &&
12649 (line->child(0)->user_flag_set() ||
12650 line->child(1)->user_flag_set()))
12651 {
12652 for (unsigned int c = 0; c < cell->n_children(); ++c)
12653 cell->child(c)->clear_coarsen_flag();
12654 cell->clear_user_flag();
12655 for (unsigned int k = 0; k < cell->n_lines(); ++k)
12657 cell->refinement_case(), k) ==
12659 // flag a line, that is refined and will
12660 // stay so
12661 raw_line_iterator(&triangulation,
12662 0,
12663 line_indices[k])
12664 ->set_user_flag();
12665 mesh_changed = true;
12666 break;
12667 }
12668 }
12669 }
12670 }
12671 while (mesh_changed == true);
12672 }
12673
12674
12675
12682 template <int dim, int spacedim>
12683 static bool
12686 {
12687 // in 1d, coarsening is always allowed since we don't enforce
12688 // the 2:1 constraint there
12689 if (dim == 1)
12690 return true;
12691
12692 const RefinementCase<dim> ref_case = cell->refinement_case();
12693 for (const unsigned int n : GeometryInfo<dim>::face_indices())
12694 {
12695 // if the cell is not refined along that face, coarsening
12696 // will not change anything, so do nothing. the same
12697 // applies, if the face is at the boundary
12698 const RefinementCase<dim - 1> face_ref_case =
12699 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
12700 n);
12701
12702 const unsigned int n_subfaces =
12703 GeometryInfo<dim - 1>::n_children(face_ref_case);
12704
12705 if (n_subfaces == 0 || cell->at_boundary(n))
12706 continue;
12707 for (unsigned int c = 0; c < n_subfaces; ++c)
12708 {
12710 child = cell->child(
12712
12714 child_neighbor = child->neighbor(n);
12715 if (!child->neighbor_is_coarser(n))
12716 {
12717 // in 2d, if the child's neighbor is coarser, then it has
12718 // no children. however, in 3d it might be
12719 // otherwise. consider for example, that our face might be
12720 // refined with cut_x, but the neighbor is refined with
12721 // cut_xy at that face. then the neighbor pointers of the
12722 // children of our cell will point to the common neighbor
12723 // cell, not to its children. what we really want to know
12724 // in the following is, whether the neighbor cell is
12725 // refined twice with reference to our cell. that only
12726 // has to be asked, if the child's neighbor is not a
12727 // coarser one. we check whether some of the children on
12728 // the neighbor are not flagged for coarsening, in that
12729 // case we may not coarsen. it is enough to check the
12730 // first child because we have already fixed the coarsen
12731 // flags on finer levels
12732 if (child_neighbor->has_children() &&
12733 !(child_neighbor->child(0)->is_active() &&
12734 child_neighbor->child(0)->coarsen_flag_set()))
12735 return false;
12736
12737 // the same applies, if the neighbors children are not
12738 // refined but will be after refinement
12739 if (child_neighbor->refine_flag_set())
12740 return false;
12741 }
12742 }
12743 }
12744 return true;
12745 }
12746 };
12747
12748
12753 {
12754 template <int spacedim>
12755 static void
12758
12759 template <int dim, int spacedim>
12760 static void
12762 {
12763 std::vector<std::pair<int, int>> adjacent_cells(
12764 2 * triangulation.n_raw_faces(), {-1, -1});
12765
12766 const auto set_entry = [&](const auto &face_index, const auto &cell) {
12767 const std::pair<int, int> cell_pair = {cell->level(), cell->index()};
12768
12770 if (adjacent_cells[2 * face_index].first == -1 &&
12771 adjacent_cells[2 * face_index].second == -1)
12772 {
12773 index = 2 * face_index + 0;
12774 }
12775 else
12776 {
12777 Assert(((adjacent_cells[2 * face_index + 1].first == -1) &&
12778 (adjacent_cells[2 * face_index + 1].second == -1)),
12780 index = 2 * face_index + 1;
12781 }
12782
12783 adjacent_cells[index] = cell_pair;
12784 };
12785
12786 const auto get_entry =
12787 [&](const auto &face_index,
12788 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
12789 auto test = adjacent_cells[2 * face_index];
12790
12791 if (test == std::make_pair(cell->level(), cell->index()))
12792 test = adjacent_cells[2 * face_index + 1];
12793
12794 return TriaIterator<CellAccessor<dim, spacedim>>(&triangulation,
12795 test.first,
12796 test.second);
12797 };
12798
12799 for (const auto &cell : triangulation.cell_iterators())
12800 for (const auto &face : cell->face_iterators())
12801 {
12802 set_entry(face->index(), cell);
12803
12804 if (cell->is_active() && face->has_children())
12805 for (unsigned int c = 0; c < face->n_children(); ++c)
12806 set_entry(face->child(c)->index(), cell);
12807 }
12808
12809 for (const auto &cell : triangulation.cell_iterators())
12810 for (auto f : cell->face_indices())
12811 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
12812 }
12813
12814 template <int dim, int spacedim>
12815 static void
12817 Triangulation<dim, spacedim> & /*triangulation*/,
12819 std::vector<unsigned int> & /*line_cell_count*/,
12820 std::vector<unsigned int> & /*quad_cell_count*/)
12821 {
12823 }
12824
12825 template <int dim, int spacedim>
12828 const bool check_for_distorted_cells)
12829 {
12830 return Implementation::execute_refinement_isotropic(
12831 triangulation, check_for_distorted_cells);
12832 }
12833
12834 template <int dim, int spacedim>
12835 static void
12837 Triangulation<dim, spacedim> & /*triangulation*/)
12838 {
12839 // nothing to do since anisotropy is not supported
12840 }
12841
12842 template <int dim, int spacedim>
12843 static void
12845 Triangulation<dim, spacedim> &triangulation)
12846 {
12847 Implementation::prepare_refinement_dim_dependent(triangulation);
12848 }
12849
12850 template <int dim, int spacedim>
12851 static bool
12854 {
12856
12857 return false;
12858 }
12859 };
12860 } // namespace TriangulationImplementation
12861} // namespace internal
12862
12863#ifndef DOXYGEN
12864
12865template <int dim, int spacedim>
12868
12869
12870
12871template <int dim, int spacedim>
12874 const MeshSmoothing smooth_grid,
12875 const bool check_for_distorted_cells)
12876 : cell_attached_data({0, 0, {}, {}})
12877 , smooth_grid(smooth_grid)
12878 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12879 , anisotropic_refinement(false)
12880 , check_for_distorted_cells(check_for_distorted_cells)
12881{
12882 if (dim == 1)
12883 {
12884 vertex_to_boundary_id_map_1d =
12885 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12886 vertex_to_manifold_id_map_1d =
12887 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12888 }
12889
12890 // connect the any_change signal to the other top level signals
12891 signals.create.connect(signals.any_change);
12892 signals.post_refinement.connect(signals.any_change);
12893 signals.clear.connect(signals.any_change);
12894 signals.mesh_movement.connect(signals.any_change);
12895}
12896
12897
12898
12899template <int dim, int spacedim>
12902 Triangulation<dim, spacedim> &&tria) noexcept
12903 : EnableObserverPointer(std::move(tria))
12904 , cell_attached_data(std::move(tria.cell_attached_data))
12905 , smooth_grid(tria.smooth_grid)
12906 , reference_cells(std::move(tria.reference_cells))
12907 , strides(tria.strides)
12908 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12909 , periodic_face_map(std::move(tria.periodic_face_map))
12910 , levels(std::move(tria.levels))
12911 , faces(std::move(tria.faces))
12912 , vertices(std::move(tria.vertices))
12913 , vertices_used(std::move(tria.vertices_used))
12914 , manifolds(std::move(tria.manifolds))
12915 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12916 , anisotropic_refinement(tria.anisotropic_refinement)
12917 , check_for_distorted_cells(tria.check_for_distorted_cells)
12918 , number_cache(std::move(tria.number_cache))
12919 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12920 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12921{
12923 tria.strides = {};
12924
12925 if (tria.policy)
12926 this->policy = tria.policy->clone();
12927}
12928
12929
12930template <int dim, int spacedim>
12933 Triangulation<dim, spacedim> &&tria) noexcept
12934{
12935 EnableObserverPointer::operator=(std::move(tria));
12936
12937 cell_attached_data = std::move(tria.cell_attached_data);
12938 smooth_grid = tria.smooth_grid;
12939 reference_cells = std::move(tria.reference_cells);
12940 strides = tria.strides;
12941 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12942 periodic_face_map = std::move(tria.periodic_face_map);
12943 levels = std::move(tria.levels);
12944 faces = std::move(tria.faces);
12945 vertices = std::move(tria.vertices);
12946 vertices_used = std::move(tria.vertices_used);
12947 manifolds = std::move(tria.manifolds);
12948 anisotropic_refinement = tria.anisotropic_refinement;
12949 number_cache = tria.number_cache;
12950 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12951 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12952
12954 tria.strides = {};
12955
12956 if (tria.policy)
12957 this->policy = tria.policy->clone();
12958
12959 return *this;
12960}
12961
12962
12963
12964template <int dim, int spacedim>
12967{
12968 // notify listeners that the triangulation is going down...
12969 try
12970 {
12971 signals.clear();
12972 }
12973 catch (...)
12974 {}
12975
12976 levels.clear();
12977
12978 // the vertex_to_boundary_id_map_1d field should be unused except in
12979 // 1d. double check this here, as destruction is a good place to
12980 // ensure that what we've done over the course of the lifetime of
12981 // this object makes sense
12982 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12984
12985 // the vertex_to_manifold_id_map_1d field should be also unused
12986 // except in 1d. check this as well
12987 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12989}
12990
12991
12992
12993template <int dim, int spacedim>
12996{
12997 // notify listeners that the triangulation is going down...
12998 signals.clear();
12999
13000 // ...and then actually clear all content of it
13001 clear_despite_subscriptions();
13002 periodic_face_pairs_level_0.clear();
13003 periodic_face_map.clear();
13004 reference_cells.clear();
13005
13006 cell_attached_data = {0, 0, {}, {}};
13007 data_serializer.clear();
13008}
13009
13010template <int dim, int spacedim>
13013{
13014 return MPI_COMM_SELF;
13015}
13016
13017
13018
13019template <int dim, int spacedim>
13021std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13023{
13024 return number_cache.active_cell_index_partitioner;
13025}
13026
13027
13028
13029template <int dim, int spacedim>
13031std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13032 global_level_cell_index_partitioner(const unsigned int level) const
13033{
13034 AssertIndexRange(level, this->n_levels());
13035
13036 return number_cache.level_cell_index_partitioners[level];
13037}
13038
13039
13040
13041template <int dim, int spacedim>
13044 const MeshSmoothing mesh_smoothing)
13045{
13046 smooth_grid = mesh_smoothing;
13047}
13048
13049
13050
13051template <int dim, int spacedim>
13055{
13056 return smooth_grid;
13057}
13058
13059
13060
13061template <int dim, int spacedim>
13064 const types::manifold_id m_number,
13065 const Manifold<dim, spacedim> &manifold_object)
13066{
13068
13069 manifolds[m_number] = manifold_object.clone();
13070}
13071
13072
13073
13074template <int dim, int spacedim>
13077 const types::manifold_id m_number)
13078{
13080
13081 // delete the entry located at number.
13082 manifolds[m_number] = default_flat_manifold->clone();
13083}
13084
13085
13086template <int dim, int spacedim>
13089{
13090 for (auto &m : manifolds)
13091 m.second = default_flat_manifold->clone();
13092}
13093
13094
13095template <int dim, int spacedim>
13098 const types::manifold_id m_number)
13099{
13100 Assert(
13101 n_cells() > 0,
13102 ExcMessage(
13103 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
13104
13105 for (const auto &cell : this->active_cell_iterators())
13106 cell->set_all_manifold_ids(m_number);
13107}
13108
13109
13110template <int dim, int spacedim>
13113 const types::manifold_id m_number)
13114{
13115 Assert(
13116 n_cells() > 0,
13117 ExcMessage(
13118 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13119
13120 for (const auto &cell : this->active_cell_iterators())
13121 for (auto f : GeometryInfo<dim>::face_indices())
13122 if (cell->face(f)->at_boundary())
13123 cell->face(f)->set_all_manifold_ids(m_number);
13124}
13125
13126
13127template <int dim, int spacedim>
13130 const types::boundary_id b_id,
13131 const types::manifold_id m_number)
13132{
13133 Assert(
13134 n_cells() > 0,
13135 ExcMessage(
13136 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13137
13138 bool boundary_found = false;
13139 for (const auto &cell : this->active_cell_iterators())
13140 {
13141 // loop on faces
13142 for (auto f : GeometryInfo<dim>::face_indices())
13143 if (cell->face(f)->at_boundary() &&
13144 cell->face(f)->boundary_id() == b_id)
13145 {
13146 boundary_found = true;
13147 cell->face(f)->set_manifold_id(m_number);
13148 }
13149
13150 // loop on edges if dim >= 3
13151 if (dim >= 3)
13152 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
13153 if (cell->line(e)->at_boundary() &&
13154 cell->line(e)->boundary_id() == b_id)
13155 {
13156 boundary_found = true;
13157 cell->line(e)->set_manifold_id(m_number);
13158 }
13159 }
13160
13161 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
13162}
13163
13164
13165
13166template <int dim, int spacedim>
13169 const types::manifold_id m_number) const
13170{
13171 // check if flat manifold has been queried
13172 if (m_number == numbers::flat_manifold_id)
13173 return *default_flat_manifold;
13174
13175 // look, if there is a manifold stored at
13176 // manifold_id number.
13177 const auto it = manifolds.find(m_number);
13178
13179 if (it != manifolds.end())
13180 {
13181 // if we have found an entry, return it
13182 return *(it->second);
13183 }
13184
13185 Assert(
13186 false,
13187 ExcMessage(
13188 "No manifold of the manifold id " + std::to_string(m_number) +
13189 " has been attached to the triangulation. "
13190 "Please attach the right manifold with Triangulation::set_manifold()."));
13191
13192 return *default_flat_manifold; // never reached
13193}
13194
13195
13196
13197template <int dim, int spacedim>
13199std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
13200 const
13201{
13202 std::set<types::boundary_id> boundary_ids;
13203 for (const auto &cell : active_cell_iterators())
13204 if (cell->is_locally_owned())
13205 for (const auto &face : cell->face_indices())
13206 if (cell->at_boundary(face))
13207 boundary_ids.insert(cell->face(face)->boundary_id());
13208
13209 return {boundary_ids.begin(), boundary_ids.end()};
13210}
13211
13212
13213
13214template <int dim, int spacedim>
13216std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
13217 const
13218{
13219 std::set<types::manifold_id> m_ids;
13220 for (const auto &cell : active_cell_iterators())
13221 if (cell->is_locally_owned())
13222 {
13223 m_ids.insert(cell->manifold_id());
13224 for (const auto &face : cell->face_iterators())
13225 m_ids.insert(face->manifold_id());
13226 if (dim == 3)
13227 {
13228 const auto line_indices = internal::TriaAccessorImplementation::
13229 Implementation::get_line_indices_of_cell(*cell);
13230 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13231 {
13232 raw_line_iterator line(this, 0, line_indices[l]);
13233 m_ids.insert(line->manifold_id());
13234 }
13235 }
13236 }
13237 return {m_ids.begin(), m_ids.end()};
13238}
13239
13240#endif
13241/*-----------------------------------------------------------------*/
13242
13243#ifndef DOXYGEN
13244
13245template <int dim, int spacedim>
13248 const Triangulation<dim, spacedim> &other_tria)
13249{
13250 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13251 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13252 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
13253 (dim == 1 || other_tria.faces != nullptr),
13254 ExcMessage(
13255 "When calling Triangulation::copy_triangulation(), "
13256 "the target triangulation must be empty but the source "
13257 "triangulation (the argument to this function) must contain "
13258 "something. Here, it seems like the source does not "
13259 "contain anything at all."));
13260
13261
13262 // copy normal elements
13263 vertices = other_tria.vertices;
13264 vertices_used = other_tria.vertices_used;
13265 anisotropic_refinement = other_tria.anisotropic_refinement;
13266 smooth_grid = other_tria.smooth_grid;
13267 reference_cells = other_tria.reference_cells;
13268 strides = other_tria.strides;
13269
13270 if (dim > 1)
13271 faces =
13272 std::make_unique<internal::TriangulationImplementation::TriaFaces<dim>>(
13273 *other_tria.faces);
13274
13275 for (const auto &p : other_tria.manifolds)
13276 set_manifold(p.first, *p.second);
13277
13278
13279 Assert(other_tria.levels.size() <= numbers::max_n_levels, ExcInternalError());
13280 levels.reserve(other_tria.levels.size());
13281 for (const auto &level : other_tria.levels)
13282 levels.push_back(
13283 std::make_unique<
13284 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>(
13285 *level));
13286
13287 number_cache = other_tria.number_cache;
13288
13289 if (dim == 1)
13290 {
13291 vertex_to_boundary_id_map_1d =
13292 std::make_unique<std::map<unsigned int, types::boundary_id>>(
13293 *other_tria.vertex_to_boundary_id_map_1d);
13294
13295 vertex_to_manifold_id_map_1d =
13296 std::make_unique<std::map<unsigned int, types::manifold_id>>(
13297 *other_tria.vertex_to_manifold_id_map_1d);
13298 }
13299
13300 if (other_tria.policy)
13301 this->policy = other_tria.policy->clone();
13302
13303 // periodic faces
13304 this->periodic_face_pairs_level_0.reserve(
13305 other_tria.periodic_face_pairs_level_0.size());
13306
13307 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
13308 {
13309 auto entry = other_entry;
13310 entry.cell[0] =
13311 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
13312 entry.cell[1] =
13313 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
13314 periodic_face_pairs_level_0.emplace_back(entry);
13315 }
13316
13317 for (auto [first_cell_, second_cell_and_orientation] :
13318 other_tria.periodic_face_map)
13319 {
13320 auto first_cell = first_cell_; // make copy since key is const
13321 first_cell.first = cell_iterator(this,
13322 first_cell.first->level(),
13323 first_cell.first->index());
13324 second_cell_and_orientation.first.first =
13325 cell_iterator(this,
13326 second_cell_and_orientation.first.first->level(),
13327 second_cell_and_orientation.first.first->index());
13328
13329 this->periodic_face_map[first_cell] = second_cell_and_orientation;
13330 }
13331
13332 // inform those who are listening on other_tria of the copy operation
13333 other_tria.signals.copy(*this);
13334 // also inform all listeners of the current triangulation that the
13335 // triangulation has been created
13336 signals.create();
13337
13338 // note that we need not copy the
13339 // subscriptor!
13340}
13341
13342
13343
13344template <int dim, int spacedim>
13347{
13348 if (this->all_reference_cells_are_hyper_cube())
13349 {
13350 this->policy =
13352 dim,
13353 spacedim,
13355 }
13356 else
13357 {
13358 this->policy =
13360 dim,
13361 spacedim,
13363 }
13364}
13365
13366
13367
13368template <int dim, int spacedim>
13371 const std::vector<Point<spacedim>> &v,
13372 const std::vector<CellData<dim>> &cells,
13373 const SubCellData &subcelldata)
13374{
13375 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13376 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13377 // check that no forbidden arrays
13378 // are used
13379 Assert(subcelldata.check_consistency(dim), ExcInternalError());
13380
13381 // try to create a triangulation; if this fails, we still want to
13382 // throw an exception but if we just do so we'll get into trouble
13383 // because sometimes other objects are already attached to it:
13384 try
13385 {
13387 create_triangulation(v, cells, subcelldata, *this);
13388 }
13389 catch (...)
13390 {
13391 clear_despite_subscriptions();
13392 throw;
13393 }
13394
13395 reset_policy();
13396
13397 // update our counts of the various elements of a triangulation, and set
13398 // active_cell_indices of all cells
13399 reset_cell_vertex_indices_cache();
13401 *this, levels.size(), number_cache);
13402 reset_active_cell_indices();
13403 reset_global_cell_indices();
13404
13405 // now verify that there are indeed no distorted cells. as per the
13406 // documentation of this class, we first collect all distorted cells
13407 // and then throw an exception if there are any
13408 if (check_for_distorted_cells)
13409 {
13410 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
13411 // throw the array (and fill the various location fields) if
13412 // there are distorted cells. otherwise, just fall off the end
13413 // of the function
13414 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
13415 }
13416
13417
13418 /*
13419 When the triangulation is a manifold (dim < spacedim) and made of
13420 quadrilaterals, the normal field provided from the map class depends on
13421 the order of the vertices. It may happen that this normal field is
13422 discontinuous. The following code takes care that this is not the case by
13423 setting the cell direction flag on those cell that produce the wrong
13424 orientation.
13425
13426 To determine if 2 neighbors have the same or opposite orientation we use
13427 a truth table. Its entries are indexed by the local indices of the
13428 common face. For example if two elements share a face, and this face is
13429 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
13430 whether the orientation are the same (true) or opposite (false).
13431
13432 Even though there may be a combinatorial/graph theory argument to get this
13433 table in any dimension, I tested by hand all the different possible cases
13434 in 1D and 2D to generate the table.
13435
13436 Assuming that a surface respects the standard orientation for 2d meshes,
13437 the truth tables are symmetric and their true values are the following
13438
13439 - 1D curves: (0,1)
13440 - 2D surface: (0,1),(0,2),(1,3),(2,3)
13441
13442 We store this data using an n_faces x n_faces full matrix, which is
13443 actually much bigger than the minimal data required, but it makes the code
13444 more readable.
13445
13446 */
13447 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
13448 {
13451 switch (dim)
13452 {
13453 case 1:
13454 {
13455 const bool values[][2] = {{false, true}, {true, false}};
13456 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13457 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13458 correct(i, j) = values[i][j];
13459 break;
13460 }
13461 case 2:
13462 {
13463 const bool values[][4] = {{false, true, true, false},
13464 {true, false, false, true},
13465 {true, false, false, true},
13466 {false, true, true, false}};
13467 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13468 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13469 correct(i, j) = (values[i][j]);
13470 break;
13471 }
13472 default:
13474 }
13475
13476
13477 std::list<active_cell_iterator> this_round, next_round;
13478 active_cell_iterator neighbor;
13479
13480 // Start with the first cell and (arbitrarily) decide that its
13481 // direction flag should be 'true':
13482 this_round.push_back(begin_active());
13483 begin_active()->set_direction_flag(true);
13484 begin_active()->set_user_flag();
13485
13486 while (this_round.size() > 0)
13487 {
13488 for (const auto &cell : this_round)
13489 {
13490 for (const unsigned int i : cell->face_indices())
13491 {
13492 if (cell->face(i)->at_boundary() == false)
13493 {
13494 // Consider the i'th neighbor of a cell for
13495 // which we have already set the direction:
13496 neighbor = cell->neighbor(i);
13497
13498 const unsigned int nb_of_nb =
13499 cell->neighbor_of_neighbor(i);
13500
13501 // If we already saw this neighboring cell,
13502 // check that everything is fine:
13503 if (neighbor->user_flag_set())
13504 {
13505 Assert(
13506 !(correct(i, nb_of_nb) ^
13507 (neighbor->direction_flag() ==
13508 cell->direction_flag())),
13509 ExcMessage(
13510 "The triangulation you are trying to create is not orientable."));
13511 }
13512 else
13513 {
13514 // We had not seen this cell yet. Set its
13515 // orientation flag (if necessary), mark it
13516 // as treated via the user flag, and push it
13517 // onto the list of cells to start work from
13518 // the next time around:
13519 if (correct(i, nb_of_nb) ^
13520 (neighbor->direction_flag() ==
13521 cell->direction_flag()))
13522 neighbor->set_direction_flag(
13523 !neighbor->direction_flag());
13524 neighbor->set_user_flag();
13525 next_round.push_back(neighbor);
13526 }
13527 }
13528 }
13529 }
13530
13531 // Before we quit let's check that if the triangulation is
13532 // disconnected that we still get all cells by starting
13533 // again from the first cell we haven't treated yet -- that
13534 // is, the first cell of the next disconnected component we
13535 // had not yet touched.
13536 if (next_round.empty())
13537 for (const auto &cell : this->active_cell_iterators())
13538 if (cell->user_flag_set() == false)
13539 {
13540 next_round.push_back(cell);
13541 cell->set_direction_flag(true);
13542 cell->set_user_flag();
13543 break;
13544 }
13545
13546 // Go on to the next round:
13547 next_round.swap(this_round);
13548 next_round.clear();
13549 }
13550 clear_user_flags();
13551 }
13552
13553 this->update_cell_relations();
13554
13555 // inform all listeners that the triangulation has been created
13556 signals.create();
13557}
13558
13559
13560
13561template <int dim, int spacedim>
13565{
13566 // 1) create coarse grid
13568 construction_data.coarse_cells,
13569 SubCellData());
13570
13571 // create a copy of cell_infos such that we can sort them
13572 auto cell_infos = construction_data.cell_infos;
13573
13574 // sort cell_infos on each level separately
13575 for (auto &cell_info : cell_infos)
13576 std::sort(
13577 cell_info.begin(),
13578 cell_info.end(),
13581 const CellId a_id(a.id);
13582 const CellId b_id(b.id);
13583
13584 const auto a_coarse_cell_index =
13585 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
13586 const auto b_coarse_cell_index =
13587 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
13588
13589 // according to their coarse-cell index and if that is
13590 // same according to their cell id (the result is that
13591 // cells on each level are sorted according to their
13592 // index on that level - what we need in the following
13593 // operations)
13594 if (a_coarse_cell_index != b_coarse_cell_index)
13595 return a_coarse_cell_index < b_coarse_cell_index;
13596 else
13597 return a_id < b_id;
13598 });
13599
13600 // 2) create all levels via a sequence of refinements. note that
13601 // we must make sure that we actually have cells on this level,
13602 // which is not clear in a parallel context for some processes
13603 for (unsigned int level = 0;
13604 level < cell_infos.size() && !cell_infos[level].empty();
13605 ++level)
13606 {
13607 // a) set material and manifold ids here (because new vertices
13608 // have to be positioned correctly during each refinement step)
13609 {
13610 auto cell = this->begin(level);
13611 auto cell_info = cell_infos[level].begin();
13612 for (; cell_info != cell_infos[level].end(); ++cell_info)
13613 {
13614 while (cell_info->id != cell->id().template to_binary<dim>())
13615 ++cell;
13616
13617 if (level == 0)
13618 {
13619 Assert(cell->material_id() == cell_info->material_id,
13620 ExcMessage(
13621 "The coarsest level material_ids must match."));
13622 Assert(cell->manifold_id() == cell_info->manifold_id,
13623 ExcMessage(
13624 "The coarsest level manifold_ids must match."));
13625 }
13626
13627 cell->set_material_id(cell_info->material_id);
13628 if (dim == 2)
13629 for (const auto face : cell->face_indices())
13630 cell->face(face)->set_manifold_id(
13631 cell_info->manifold_line_ids[face]);
13632 else if (dim == 3)
13633 {
13634 for (const auto face : cell->face_indices())
13635 cell->face(face)->set_manifold_id(
13636 cell_info->manifold_quad_ids[face]);
13637
13638 const auto line_indices = internal::TriaAccessorImplementation::
13639 Implementation::get_line_indices_of_cell(*cell);
13640 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13641 {
13642 raw_line_iterator line(this, 0, line_indices[l]);
13643 line->set_manifold_id(cell_info->manifold_line_ids[l]);
13644 }
13645 }
13646
13647 cell->set_manifold_id(cell_info->manifold_id);
13648 }
13649 }
13650
13651 // b) perform refinement on all levels but on the finest
13652 if (level + 1 != cell_infos.size())
13653 {
13654 // find cells that should have children and mark them for
13655 // refinement
13656 auto coarse_cell = this->begin(level);
13657 auto fine_cell_info = cell_infos[level + 1].begin();
13658
13659 // loop over all cells on the next level
13660 for (; fine_cell_info != cell_infos[level + 1].end();
13661 ++fine_cell_info)
13662 {
13663 // find the parent of that cell
13664 while (
13665 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
13666 ++coarse_cell;
13667
13668 // set parent for refinement
13669 coarse_cell->set_refine_flag();
13670 }
13671
13672 // execute refinement
13673 ::Triangulation<dim,
13674 spacedim>::execute_coarsening_and_refinement();
13675 }
13676 }
13677
13678 // 3) set boundary ids
13679 for (unsigned int level = 0;
13680 level < cell_infos.size() && !cell_infos[level].empty();
13681 ++level)
13682 {
13683 auto cell = this->begin(level);
13684 auto cell_info = cell_infos[level].begin();
13685 for (; cell_info != cell_infos[level].end(); ++cell_info)
13686 {
13687 // find cell that has the correct cell
13688 while (cell_info->id != cell->id().template to_binary<dim>())
13689 ++cell;
13690
13691 // boundary ids
13692 for (auto pair : cell_info->boundary_ids)
13693 if (cell->face(pair.first)->at_boundary())
13694 cell->face(pair.first)->set_boundary_id(pair.second);
13695 }
13696 }
13697
13698 // inform all listeners that the triangulation has been created
13699 signals.create();
13700}
13701
13702
13703template <int dim, int spacedim>
13706{
13707 AssertThrow(dim + 1 == spacedim,
13708 ExcMessage(
13709 "This function can only be called if dim == spacedim-1."));
13710 for (const auto &cell : this->active_cell_iterators())
13711 cell->set_direction_flag(!cell->direction_flag());
13712}
13713
13714
13715
13716template <int dim, int spacedim>
13719{
13720 if constexpr (dim == 3)
13721 {
13722 // Compute the vertex to cell map
13723 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
13725
13726 // Compute the line-neighbors
13727 if (this->line_to_adjacent_cells_map)
13728 // If the std::optional ready has a value attached to it, just change
13729 // the size of the table stored inside it.
13730 this->line_to_adjacent_cells_map->reinit(
13731 this->n_active_cells(),
13732 (is_mixed_mesh() ?
13733 GeometryInfo<dim>::lines_per_cell : // err on the safe side: choose
13734 // the largest number of lines
13735 // per cell
13736 get_reference_cells()[0]
13737 .n_lines()) // choose the right number of lines per cell for the
13738 // mesh type used
13739 );
13740 else
13741 // Else if the std::optional has no value attached to it, create a table
13742 // of the corresponding size and store it inside the std::optional.
13743 this->line_to_adjacent_cells_map =
13744 std::make_optional<Table<2, std::set<active_cell_iterator>>>(
13746 this->n_active_cells(),
13747 (is_mixed_mesh() ? GeometryInfo<dim>::lines_per_cell :
13748 get_reference_cells()[0].n_lines())));
13749
13750
13751 // Loop over all cells -> lines -> vertices
13752 for (const auto &cell : this->active_cell_iterators())
13753 for (unsigned int line : cell->line_indices())
13754 {
13755 const unsigned int vertex_0 = cell->vertex_index(
13757 const unsigned int vertex_1 = cell->vertex_index(
13759 const std::set<
13761 &adjacent_cells_to_vertex_0 = vertex_to_cell[vertex_0];
13762 const std::set<
13764 &adjacent_cells_to_vertex_1 = vertex_to_cell[vertex_1];
13765
13766 // add all cells that are adjacent to vertex_0 and vertex_1
13767 std::set_intersection(
13768 adjacent_cells_to_vertex_0.begin(),
13769 adjacent_cells_to_vertex_0.end(),
13770 adjacent_cells_to_vertex_1.begin(),
13771 adjacent_cells_to_vertex_1.end(),
13772 std::inserter(line_to_adjacent_cells_map
13773 .value()[cell->active_cell_index()][line],
13774 line_to_adjacent_cells_map
13775 .value()[cell->active_cell_index()][line]
13776 .begin()));
13777 }
13778 }
13779}
13780
13781
13782
13783template <int dim, int spacedim>
13786{
13787 Assert(n_cells() > 0,
13788 ExcMessage("Error: An empty Triangulation can not be refined."));
13789
13790 for (const auto &cell : this->active_cell_iterators())
13791 {
13792 cell->clear_coarsen_flag();
13793 cell->set_refine_flag();
13794 cell->set_refine_choice();
13795 }
13796}
13797
13798
13799
13800template <int dim, int spacedim>
13802void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
13803{
13804 Assert(n_cells() > 0,
13805 ExcMessage("Error: An empty Triangulation can not be refined."));
13806
13807 for (unsigned int i = 0; i < times; ++i)
13808 {
13809 set_all_refine_flags();
13810 execute_coarsening_and_refinement();
13811 }
13812}
13813
13814
13815
13816template <int dim, int spacedim>
13818void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
13819{
13820 for (unsigned int i = 0; i < times; ++i)
13821 {
13822 for (const auto &cell : this->active_cell_iterators())
13823 {
13824 cell->clear_refine_flag();
13825 cell->set_coarsen_flag();
13826 }
13827 execute_coarsening_and_refinement();
13828 }
13829}
13830
13831
13832#endif
13833/*-------------------- refine/coarsen flags -------------------------*/
13834
13835#ifndef DOXYGEN
13836
13837template <int dim, int spacedim>
13839void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
13840{
13841 v.resize(dim * n_active_cells(), false);
13842 std::vector<bool>::iterator i = v.begin();
13843
13844 for (const auto &cell : this->active_cell_iterators())
13845 for (unsigned int j = 0; j < dim; ++j, ++i)
13846 if (cell->refine_flag_set() & (1 << j))
13847 *i = true;
13848
13849 Assert(i == v.end(), ExcInternalError());
13850}
13851
13852
13853
13854template <int dim, int spacedim>
13856void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
13857{
13858 std::vector<bool> v;
13859 save_refine_flags(v);
13860 write_bool_vector(mn_tria_refine_flags_begin,
13861 v,
13863 out);
13864}
13865
13866
13867
13868template <int dim, int spacedim>
13871{
13872 std::vector<bool> v;
13873 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
13874 load_refine_flags(v);
13875}
13876
13877
13878
13879template <int dim, int spacedim>
13881void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
13882{
13883 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
13884
13885 std::vector<bool>::const_iterator i = v.begin();
13886 for (const auto &cell : this->active_cell_iterators())
13887 {
13888 unsigned int ref_case = 0;
13889
13890 for (unsigned int j = 0; j < dim; ++j, ++i)
13891 if (*i == true)
13892 ref_case += 1 << j;
13894 ExcGridReadError());
13895 if (ref_case > 0)
13896 cell->set_refine_flag(RefinementCase<dim>(ref_case));
13897 else
13898 cell->clear_refine_flag();
13899 }
13900
13901 Assert(i == v.end(), ExcInternalError());
13902}
13903
13904
13905
13906template <int dim, int spacedim>
13909 std::vector<bool> &v) const
13910{
13911 v.resize(n_active_cells(), false);
13912 std::vector<bool>::iterator i = v.begin();
13913 for (const auto &cell : this->active_cell_iterators())
13914 {
13915 *i = cell->coarsen_flag_set();
13916 ++i;
13917 }
13918
13919 Assert(i == v.end(), ExcInternalError());
13920}
13921
13922
13923
13924template <int dim, int spacedim>
13926void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13927{
13928 std::vector<bool> v;
13929 save_coarsen_flags(v);
13930 write_bool_vector(mn_tria_coarsen_flags_begin,
13931 v,
13933 out);
13934}
13935
13936
13937
13938template <int dim, int spacedim>
13941{
13942 std::vector<bool> v;
13943 read_bool_vector(mn_tria_coarsen_flags_begin,
13944 v,
13946 in);
13947 load_coarsen_flags(v);
13948}
13949
13950
13951
13952template <int dim, int spacedim>
13955 const std::vector<bool> &v)
13956{
13957 Assert(v.size() == n_active_cells(), ExcGridReadError());
13958
13959 std::vector<bool>::const_iterator i = v.begin();
13960 for (const auto &cell : this->active_cell_iterators())
13961 {
13962 if (*i == true)
13963 cell->set_coarsen_flag();
13964 else
13965 cell->clear_coarsen_flag();
13966 ++i;
13967 }
13968
13969 Assert(i == v.end(), ExcInternalError());
13970}
13971
13972
13973template <int dim, int spacedim>
13976{
13977 return anisotropic_refinement;
13978}
13979
13980
13981#endif
13982
13983namespace internal
13984{
13985 namespace
13986 {
13987 template <int dim, int spacedim>
13988 std::vector<std::vector<bool>>
13989 extract_raw_coarsen_flags(
13990 const std::vector<
13991 std::unique_ptr<::internal::TriangulationImplementation::
13992 TriaLevel<dim, spacedim>>> &levels)
13993 {
13994 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13995 for (unsigned int level = 0; level < levels.size(); ++level)
13996 coarsen_flags[level] = levels[level]->coarsen_flags;
13997 return coarsen_flags;
13998 }
13999
14000 template <int dim, int spacedim>
14001 std::vector<std::vector<std::uint8_t>>
14002 extract_raw_refine_flags(
14003 const std::vector<
14004 std::unique_ptr<::internal::TriangulationImplementation::
14005 TriaLevel<dim, spacedim>>> &levels)
14006 {
14007 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
14008 for (unsigned int level = 0; level < levels.size(); ++level)
14009 refine_flags[level] = levels[level]->refine_flags;
14010 return refine_flags;
14011 }
14012 } // namespace
14013} // namespace internal
14014
14015
14016/*-------------------- user data/flags -------------------------*/
14017
14018
14019namespace
14020{
14021 // clear user data of cells
14022 template <int dim, int spacedim>
14023 void
14024 clear_user_data(
14025 std::vector<std::unique_ptr<
14027 {
14028 for (auto &level : levels)
14029 level->cells.clear_user_data();
14030 }
14031
14032
14033 // clear user data of faces
14034 template <int dim>
14035 void
14037 {
14038 if (dim == 2)
14039 {
14040 faces->lines.clear_user_data();
14041 }
14042
14043
14044 if (dim == 3)
14045 {
14046 faces->lines.clear_user_data();
14047 faces->quads.clear_user_data();
14048 }
14049 }
14050} // namespace
14051
14052#ifndef DOXYGEN
14053
14054template <int dim, int spacedim>
14057{
14058 // let functions in anonymous namespace do their work
14059 ::clear_user_data(levels);
14060 if (dim > 1)
14061 ::clear_user_data(faces.get());
14062}
14063
14064
14065
14066namespace
14067{
14068 template <int dim, int spacedim>
14069 void
14070 clear_user_flags_line(
14071 std::vector<std::unique_ptr<
14074 {
14075 if (dim == 1)
14076 {
14077 for (const auto &level : levels)
14078 level->cells.clear_user_flags();
14079 }
14080 else if (dim == 2 || dim == 3)
14081 {
14082 faces->lines.clear_user_flags();
14083 }
14084 else
14085 {
14087 }
14088 }
14089} // namespace
14090
14091
14092template <int dim, int spacedim>
14095{
14096 ::clear_user_flags_line(levels, faces.get());
14097}
14098
14099
14100
14101namespace
14102{
14103 template <int dim, int spacedim>
14104 void
14105 clear_user_flags_quad(
14106 std::vector<std::unique_ptr<
14109 {
14110 if (dim == 1)
14111 {
14112 // nothing to do in 1d
14113 }
14114 else if (dim == 2)
14115 {
14116 for (const auto &level : levels)
14117 level->cells.clear_user_flags();
14118 }
14119 else if (dim == 3)
14120 {
14121 faces->quads.clear_user_flags();
14122 }
14123 else
14124 {
14126 }
14127 }
14128} // namespace
14129
14130
14131template <int dim, int spacedim>
14134{
14135 ::clear_user_flags_quad(levels, faces.get());
14136}
14137
14138
14139
14140namespace
14141{
14142 template <int dim, int spacedim>
14143 void
14144 clear_user_flags_hex(
14145 std::vector<std::unique_ptr<
14148 {
14149 if (dim == 1)
14150 {
14151 // nothing to do in 1d
14152 }
14153 else if (dim == 2)
14154 {
14155 // nothing to do in 2d
14156 }
14157 else if (dim == 3)
14158 {
14159 for (const auto &level : levels)
14160 level->cells.clear_user_flags();
14161 }
14162 else
14163 {
14165 }
14166 }
14167} // namespace
14168
14169
14170template <int dim, int spacedim>
14173{
14174 ::clear_user_flags_hex(levels, faces.get());
14175}
14176
14177
14178
14179template <int dim, int spacedim>
14182{
14183 clear_user_flags_line();
14184 clear_user_flags_quad();
14185 clear_user_flags_hex();
14186}
14187
14188
14189
14190template <int dim, int spacedim>
14192void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
14193{
14194 save_user_flags_line(out);
14195
14196 if (dim >= 2)
14197 save_user_flags_quad(out);
14198
14199 if (dim >= 3)
14200 save_user_flags_hex(out);
14201
14202 if (dim >= 4)
14204}
14205
14206
14207
14208template <int dim, int spacedim>
14210void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
14211{
14212 // clear vector and append
14213 // all the stuff later on
14214 v.clear();
14215
14216 std::vector<bool> tmp;
14217
14218 save_user_flags_line(tmp);
14219 v.insert(v.end(), tmp.begin(), tmp.end());
14220
14221 if (dim >= 2)
14222 {
14223 save_user_flags_quad(tmp);
14224 v.insert(v.end(), tmp.begin(), tmp.end());
14225 }
14226
14227 if (dim >= 3)
14228 {
14229 save_user_flags_hex(tmp);
14230 v.insert(v.end(), tmp.begin(), tmp.end());
14231 }
14232
14233 if (dim >= 4)
14235}
14236
14237
14238
14239template <int dim, int spacedim>
14242{
14243 load_user_flags_line(in);
14244
14245 if (dim >= 2)
14246 load_user_flags_quad(in);
14247
14248 if (dim >= 3)
14249 load_user_flags_hex(in);
14250
14251 if (dim >= 4)
14253}
14254
14255
14256
14257template <int dim, int spacedim>
14259void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
14260{
14261 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14262 std::vector<bool> tmp;
14263
14264 // first extract the flags
14265 // belonging to lines
14266 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14267 // and set the lines
14268 load_user_flags_line(tmp);
14269
14270 if (dim >= 2)
14271 {
14272 tmp.clear();
14273 tmp.insert(tmp.end(),
14274 v.begin() + n_lines(),
14275 v.begin() + n_lines() + n_quads());
14276 load_user_flags_quad(tmp);
14277 }
14278
14279 if (dim >= 3)
14280 {
14281 tmp.clear();
14282 tmp.insert(tmp.end(),
14283 v.begin() + n_lines() + n_quads(),
14284 v.begin() + n_lines() + n_quads() + n_hexs());
14285 load_user_flags_hex(tmp);
14286 }
14287
14288 if (dim >= 4)
14290}
14291
14292
14293
14294template <int dim, int spacedim>
14297 std::vector<bool> &v) const
14298{
14299 v.resize(n_lines(), false);
14300 std::vector<bool>::iterator i = v.begin();
14301 line_iterator line = begin_line(), endl = end_line();
14302 for (; line != endl; ++line, ++i)
14303 *i = line->user_flag_set();
14304
14305 Assert(i == v.end(), ExcInternalError());
14306}
14307
14308
14309
14310template <int dim, int spacedim>
14312void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
14313{
14314 std::vector<bool> v;
14315 save_user_flags_line(v);
14316 write_bool_vector(mn_tria_line_user_flags_begin,
14317 v,
14319 out);
14320}
14321
14322
14323
14324template <int dim, int spacedim>
14327{
14328 std::vector<bool> v;
14329 read_bool_vector(mn_tria_line_user_flags_begin,
14330 v,
14332 in);
14333 load_user_flags_line(v);
14334}
14335
14336
14337
14338template <int dim, int spacedim>
14341 const std::vector<bool> &v)
14342{
14343 Assert(v.size() == n_lines(), ExcGridReadError());
14344
14345 line_iterator line = begin_line(), endl = end_line();
14346 std::vector<bool>::const_iterator i = v.begin();
14347 for (; line != endl; ++line, ++i)
14348 if (*i == true)
14349 line->set_user_flag();
14350 else
14351 line->clear_user_flag();
14352
14353 Assert(i == v.end(), ExcInternalError());
14354}
14355
14356#endif
14357
14358namespace
14359{
14360 template <typename Iterator>
14361 bool
14362 get_user_flag(const Iterator &i)
14363 {
14364 return i->user_flag_set();
14365 }
14366
14367
14368
14369 template <int structdim, int dim, int spacedim>
14370 bool
14372 {
14374 return false;
14375 }
14376
14377
14378
14379 template <typename Iterator>
14380 void
14381 set_user_flag(const Iterator &i)
14382 {
14383 i->set_user_flag();
14384 }
14385
14386
14387
14388 template <int structdim, int dim, int spacedim>
14389 void
14391 {
14393 }
14394
14395
14396
14397 template <typename Iterator>
14398 void
14399 clear_user_flag(const Iterator &i)
14400 {
14401 i->clear_user_flag();
14402 }
14403
14404
14405
14406 template <int structdim, int dim, int spacedim>
14407 void
14408 clear_user_flag(
14410 {
14412 }
14413} // namespace
14414
14415#ifndef DOXYGEN
14416
14417template <int dim, int spacedim>
14420 std::vector<bool> &v) const
14421{
14422 v.resize(n_quads(), false);
14423
14424 if (dim >= 2)
14425 {
14426 std::vector<bool>::iterator i = v.begin();
14427 quad_iterator quad = begin_quad(), endq = end_quad();
14428 for (; quad != endq; ++quad, ++i)
14429 *i = get_user_flag(quad);
14430
14431 Assert(i == v.end(), ExcInternalError());
14432 }
14433}
14434
14435
14436
14437template <int dim, int spacedim>
14439void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
14440{
14441 std::vector<bool> v;
14442 save_user_flags_quad(v);
14443 write_bool_vector(mn_tria_quad_user_flags_begin,
14444 v,
14446 out);
14447}
14448
14449
14450
14451template <int dim, int spacedim>
14454{
14455 std::vector<bool> v;
14456 read_bool_vector(mn_tria_quad_user_flags_begin,
14457 v,
14459 in);
14460 load_user_flags_quad(v);
14461}
14462
14463
14464
14465template <int dim, int spacedim>
14468 const std::vector<bool> &v)
14469{
14470 Assert(v.size() == n_quads(), ExcGridReadError());
14471
14472 if (dim >= 2)
14473 {
14474 quad_iterator quad = begin_quad(), endq = end_quad();
14475 std::vector<bool>::const_iterator i = v.begin();
14476 for (; quad != endq; ++quad, ++i)
14477 if (*i == true)
14478 set_user_flag(quad);
14479 else
14480 clear_user_flag(quad);
14481
14482 Assert(i == v.end(), ExcInternalError());
14483 }
14484}
14485
14486
14487
14488template <int dim, int spacedim>
14491 std::vector<bool> &v) const
14492{
14493 v.resize(n_hexs(), false);
14494
14495 if (dim >= 3)
14496 {
14497 std::vector<bool>::iterator i = v.begin();
14498 hex_iterator hex = begin_hex(), endh = end_hex();
14499 for (; hex != endh; ++hex, ++i)
14500 *i = get_user_flag(hex);
14501
14502 Assert(i == v.end(), ExcInternalError());
14503 }
14504}
14505
14506
14507
14508template <int dim, int spacedim>
14510void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
14511{
14512 std::vector<bool> v;
14513 save_user_flags_hex(v);
14514 write_bool_vector(mn_tria_hex_user_flags_begin,
14515 v,
14517 out);
14518}
14519
14520
14521
14522template <int dim, int spacedim>
14525{
14526 std::vector<bool> v;
14527 read_bool_vector(mn_tria_hex_user_flags_begin,
14528 v,
14530 in);
14531 load_user_flags_hex(v);
14532}
14533
14534
14535
14536template <int dim, int spacedim>
14539 const std::vector<bool> &v)
14540{
14541 Assert(v.size() == n_hexs(), ExcGridReadError());
14542
14543 if (dim >= 3)
14544 {
14545 hex_iterator hex = begin_hex(), endh = end_hex();
14546 std::vector<bool>::const_iterator i = v.begin();
14547 for (; hex != endh; ++hex, ++i)
14548 if (*i == true)
14549 set_user_flag(hex);
14550 else
14551 clear_user_flag(hex);
14552
14553 Assert(i == v.end(), ExcInternalError());
14554 }
14555}
14556
14557
14558
14559template <int dim, int spacedim>
14562 std::vector<unsigned int> &v) const
14563{
14564 // clear vector and append all the
14565 // stuff later on
14566 v.clear();
14567
14568 std::vector<unsigned int> tmp;
14569
14570 save_user_indices_line(tmp);
14571 v.insert(v.end(), tmp.begin(), tmp.end());
14572
14573 if (dim >= 2)
14574 {
14575 save_user_indices_quad(tmp);
14576 v.insert(v.end(), tmp.begin(), tmp.end());
14577 }
14578
14579 if (dim >= 3)
14580 {
14581 save_user_indices_hex(tmp);
14582 v.insert(v.end(), tmp.begin(), tmp.end());
14583 }
14584
14585 if (dim >= 4)
14587}
14588
14589
14590
14591template <int dim, int spacedim>
14594 const std::vector<unsigned int> &v)
14595{
14596 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14597 std::vector<unsigned int> tmp;
14598
14599 // first extract the indices
14600 // belonging to lines
14601 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14602 // and set the lines
14603 load_user_indices_line(tmp);
14604
14605 if (dim >= 2)
14606 {
14607 tmp.clear();
14608 tmp.insert(tmp.end(),
14609 v.begin() + n_lines(),
14610 v.begin() + n_lines() + n_quads());
14611 load_user_indices_quad(tmp);
14612 }
14613
14614 if (dim >= 3)
14615 {
14616 tmp.clear();
14617 tmp.insert(tmp.end(),
14618 v.begin() + n_lines() + n_quads(),
14619 v.begin() + n_lines() + n_quads() + n_hexs());
14620 load_user_indices_hex(tmp);
14621 }
14622
14623 if (dim >= 4)
14625}
14626
14627
14628
14629template <int dim, int spacedim>
14631void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
14632{
14633 // Save triangulation information.
14634 {
14635 std::ofstream ofs_tria(file_basename + "_triangulation.data");
14636 AssertThrow(ofs_tria.fail() == false, ExcIO());
14637
14638 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
14639 save(oa,
14641 }
14642
14643 // Save attached data.
14644 {
14645 std::ofstream ofs_info(file_basename + ".info");
14646 ofs_info
14647 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
14648 << std::endl
14650 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
14651 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
14652 << this->n_global_active_cells() << std::endl;
14653 }
14654
14655 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
14656}
14657
14658
14659
14660template <int dim, int spacedim>
14662void Triangulation<dim, spacedim>::load(const std::string &file_basename)
14663{
14664 // It's probably prudent to first get rid of any all content of the
14665 // triangulation, rather than hope that the deserialization below
14666 // overwrites everything:
14667 clear();
14668
14669 // Load triangulation information.
14670 {
14671 std::ifstream ifs_tria(file_basename + "_triangulation.data");
14672 AssertThrow(ifs_tria.fail() == false, ExcIO());
14673
14674 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
14675 load(ia,
14677 }
14678
14679 // Load attached data.
14680 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
14681 n_global_active_cells;
14682 {
14683 std::ifstream ifs_info(std::string(file_basename) + ".info");
14684 AssertThrow(ifs_info.fail() == false, ExcIO());
14685 std::string firstline;
14686 std::getline(ifs_info, firstline);
14687 ifs_info >> version >> numcpus >> attached_count_fixed >>
14688 attached_count_variable >> n_global_active_cells;
14689 }
14690
14691 AssertThrow(numcpus == 1,
14692 ExcMessage("Incompatible number of CPUs found in .info file."));
14693
14694 const auto expected_version =
14696 spacedim>::version_number;
14697 AssertThrow(version == expected_version,
14698 ExcMessage(
14699 "The information saved in the file you are trying "
14700 "to read the triangulation from was written with an "
14701 "incompatible file format version and cannot be read."));
14702 Assert(this->n_global_active_cells() == n_global_active_cells,
14703 ExcMessage("The number of cells of the triangulation differs "
14704 "from the number of cells written into the .info file."));
14705
14706 // Clear all of the callback data, as explained in the documentation of
14707 // register_data_attach().
14708 this->cell_attached_data.n_attached_data_sets = 0;
14709 this->cell_attached_data.n_attached_deserialize =
14710 attached_count_fixed + attached_count_variable;
14711
14712 this->load_attached_data(0,
14713 this->n_global_active_cells(),
14714 this->n_active_cells(),
14715 file_basename,
14716 attached_count_fixed,
14717 attached_count_variable);
14718
14719 this->update_cell_relations();
14720}
14721
14722#endif
14723namespace
14724{
14725 template <typename Iterator>
14726 unsigned int
14727 get_user_index(const Iterator &i)
14728 {
14729 return i->user_index();
14730 }
14731
14732
14733
14734 template <int structdim, int dim, int spacedim>
14735 unsigned int
14736 get_user_index(
14738 {
14741 }
14742
14743
14744
14745 template <typename Iterator>
14746 void
14747 set_user_index(const Iterator &i, const unsigned int x)
14748 {
14749 i->set_user_index(x);
14750 }
14751
14752
14753
14754 template <int structdim, int dim, int spacedim>
14755 void
14756 set_user_index(
14758 const unsigned int)
14759 {
14761 }
14762} // namespace
14763
14764#ifndef DOXYGEN
14765
14766template <int dim, int spacedim>
14769 std::vector<unsigned int> &v) const
14770{
14771 v.resize(n_lines(), 0);
14772 std::vector<unsigned int>::iterator i = v.begin();
14773 line_iterator line = begin_line(), endl = end_line();
14774 for (; line != endl; ++line, ++i)
14775 *i = line->user_index();
14776}
14777
14778
14779
14780template <int dim, int spacedim>
14783 const std::vector<unsigned int> &v)
14784{
14785 Assert(v.size() == n_lines(), ExcGridReadError());
14786
14787 line_iterator line = begin_line(), endl = end_line();
14788 std::vector<unsigned int>::const_iterator i = v.begin();
14789 for (; line != endl; ++line, ++i)
14790 line->set_user_index(*i);
14791}
14792
14793
14794template <int dim, int spacedim>
14797 std::vector<unsigned int> &v) const
14798{
14799 v.resize(n_quads(), 0);
14800
14801 if (dim >= 2)
14802 {
14803 std::vector<unsigned int>::iterator i = v.begin();
14804 quad_iterator quad = begin_quad(), endq = end_quad();
14805 for (; quad != endq; ++quad, ++i)
14806 *i = get_user_index(quad);
14807 }
14808}
14809
14810
14811
14812template <int dim, int spacedim>
14815 const std::vector<unsigned int> &v)
14816{
14817 Assert(v.size() == n_quads(), ExcGridReadError());
14818
14819 if (dim >= 2)
14820 {
14821 quad_iterator quad = begin_quad(), endq = end_quad();
14822 std::vector<unsigned int>::const_iterator i = v.begin();
14823 for (; quad != endq; ++quad, ++i)
14824 set_user_index(quad, *i);
14825 }
14826}
14827
14828
14829template <int dim, int spacedim>
14832 std::vector<unsigned int> &v) const
14833{
14834 v.resize(n_hexs(), 0);
14835
14836 if (dim >= 3)
14837 {
14838 std::vector<unsigned int>::iterator i = v.begin();
14839 hex_iterator hex = begin_hex(), endh = end_hex();
14840 for (; hex != endh; ++hex, ++i)
14841 *i = get_user_index(hex);
14842 }
14843}
14844
14845
14846
14847template <int dim, int spacedim>
14850 const std::vector<unsigned int> &v)
14851{
14852 Assert(v.size() == n_hexs(), ExcGridReadError());
14853
14854 if (dim >= 3)
14855 {
14856 hex_iterator hex = begin_hex(), endh = end_hex();
14857 std::vector<unsigned int>::const_iterator i = v.begin();
14858 for (; hex != endh; ++hex, ++i)
14859 set_user_index(hex, *i);
14860 }
14861}
14862
14863#endif
14864
14865
14866//---------------- user pointers ----------------------------------------//
14867
14868
14869namespace
14870{
14871 template <typename Iterator>
14872 void *
14873 get_user_pointer(const Iterator &i)
14874 {
14875 return i->user_pointer();
14876 }
14877
14878
14879
14880 template <int structdim, int dim, int spacedim>
14881 void *
14882 get_user_pointer(
14884 {
14886 return nullptr;
14887 }
14888
14889
14890
14891 template <typename Iterator>
14892 void
14893 set_user_pointer(const Iterator &i, void *x)
14894 {
14895 i->set_user_pointer(x);
14896 }
14897
14898
14899
14900 template <int structdim, int dim, int spacedim>
14901 void
14902 set_user_pointer(
14904 void *)
14905 {
14907 }
14908} // namespace
14909
14910#ifndef DOXYGEN
14911
14912template <int dim, int spacedim>
14915 std::vector<void *> &v) const
14916{
14917 // clear vector and append all the
14918 // stuff later on
14919 v.clear();
14920
14921 std::vector<void *> tmp;
14922
14923 save_user_pointers_line(tmp);
14924 v.insert(v.end(), tmp.begin(), tmp.end());
14925
14926 if (dim >= 2)
14927 {
14928 save_user_pointers_quad(tmp);
14929 v.insert(v.end(), tmp.begin(), tmp.end());
14930 }
14931
14932 if (dim >= 3)
14933 {
14934 save_user_pointers_hex(tmp);
14935 v.insert(v.end(), tmp.begin(), tmp.end());
14936 }
14937
14938 if (dim >= 4)
14940}
14941
14942
14943
14944template <int dim, int spacedim>
14947 const std::vector<void *> &v)
14948{
14949 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14950 std::vector<void *> tmp;
14951
14952 // first extract the pointers
14953 // belonging to lines
14954 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14955 // and set the lines
14956 load_user_pointers_line(tmp);
14957
14958 if (dim >= 2)
14959 {
14960 tmp.clear();
14961 tmp.insert(tmp.end(),
14962 v.begin() + n_lines(),
14963 v.begin() + n_lines() + n_quads());
14964 load_user_pointers_quad(tmp);
14965 }
14966
14967 if (dim >= 3)
14968 {
14969 tmp.clear();
14970 tmp.insert(tmp.end(),
14971 v.begin() + n_lines() + n_quads(),
14972 v.begin() + n_lines() + n_quads() + n_hexs());
14973 load_user_pointers_hex(tmp);
14974 }
14975
14976 if (dim >= 4)
14978}
14979
14980
14981
14982template <int dim, int spacedim>
14985 std::vector<void *> &v) const
14986{
14987 v.resize(n_lines(), nullptr);
14988 std::vector<void *>::iterator i = v.begin();
14989 line_iterator line = begin_line(), endl = end_line();
14990 for (; line != endl; ++line, ++i)
14991 *i = line->user_pointer();
14992}
14993
14994
14995
14996template <int dim, int spacedim>
14999 const std::vector<void *> &v)
15000{
15001 Assert(v.size() == n_lines(), ExcGridReadError());
15002
15003 line_iterator line = begin_line(), endl = end_line();
15004 std::vector<void *>::const_iterator i = v.begin();
15005 for (; line != endl; ++line, ++i)
15006 line->set_user_pointer(*i);
15007}
15008
15009
15010
15011template <int dim, int spacedim>
15014 std::vector<void *> &v) const
15015{
15016 v.resize(n_quads(), nullptr);
15017
15018 if (dim >= 2)
15019 {
15020 std::vector<void *>::iterator i = v.begin();
15021 quad_iterator quad = begin_quad(), endq = end_quad();
15022 for (; quad != endq; ++quad, ++i)
15023 *i = get_user_pointer(quad);
15024 }
15025}
15026
15027
15028
15029template <int dim, int spacedim>
15032 const std::vector<void *> &v)
15033{
15034 Assert(v.size() == n_quads(), ExcGridReadError());
15035
15036 if (dim >= 2)
15037 {
15038 quad_iterator quad = begin_quad(), endq = end_quad();
15039 std::vector<void *>::const_iterator i = v.begin();
15040 for (; quad != endq; ++quad, ++i)
15041 set_user_pointer(quad, *i);
15042 }
15043}
15044
15045
15046template <int dim, int spacedim>
15049 std::vector<void *> &v) const
15050{
15051 v.resize(n_hexs(), nullptr);
15052
15053 if (dim >= 3)
15054 {
15055 std::vector<void *>::iterator i = v.begin();
15056 hex_iterator hex = begin_hex(), endh = end_hex();
15057 for (; hex != endh; ++hex, ++i)
15058 *i = get_user_pointer(hex);
15059 }
15060}
15061
15062
15063
15064template <int dim, int spacedim>
15067 const std::vector<void *> &v)
15068{
15069 Assert(v.size() == n_hexs(), ExcGridReadError());
15070
15071 if (dim >= 3)
15072 {
15073 hex_iterator hex = begin_hex(), endh = end_hex();
15074 std::vector<void *>::const_iterator i = v.begin();
15075 for (; hex != endh; ++hex, ++i)
15076 set_user_pointer(hex, *i);
15077 }
15078}
15079
15080#endif
15081
15082/*------------------------ Cell iterator functions ------------------------*/
15083
15084#ifndef DOXYGEN
15085
15086template <int dim, int spacedim>
15089 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
15090{
15091 switch (dim)
15092 {
15093 case 1:
15094 return begin_raw_line(level);
15095 case 2:
15096 return begin_raw_quad(level);
15097 case 3:
15098 return begin_raw_hex(level);
15099 default:
15101 return raw_cell_iterator();
15102 }
15103}
15104
15105
15106
15107template <int dim, int spacedim>
15110 Triangulation<dim, spacedim>::begin(const unsigned int level) const
15111{
15112 switch (dim)
15113 {
15114 case 1:
15115 return begin_line(level);
15116 case 2:
15117 return begin_quad(level);
15118 case 3:
15119 return begin_hex(level);
15120 default:
15121 Assert(false, ExcImpossibleInDim(dim));
15122 return cell_iterator();
15123 }
15124}
15125
15126
15127
15128template <int dim, int spacedim>
15131 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
15132{
15133 switch (dim)
15134 {
15135 case 1:
15136 return begin_active_line(level);
15137 case 2:
15138 return begin_active_quad(level);
15139 case 3:
15140 return begin_active_hex(level);
15141 default:
15143 return active_cell_iterator();
15144 }
15145}
15146
15147
15148
15149template <int dim, int spacedim>
15153{
15154 const unsigned int level = levels.size() - 1;
15155 if (levels[level]->cells.n_objects() == 0)
15156 return end(level);
15157
15158 // find the last raw iterator on
15159 // this level
15160 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
15161 level,
15162 levels[level]->cells.n_objects() - 1);
15163
15164 // then move to the last used one
15165 if (ri->used() == true)
15166 return ri;
15167 while ((--ri).state() == IteratorState::valid)
15168 if (ri->used() == true)
15169 return ri;
15170 return ri;
15171}
15172
15173
15174
15175template <int dim, int spacedim>
15179{
15180 // get the last used cell
15181 cell_iterator cell = last();
15182
15183 if (cell != end())
15184 {
15185 // then move to the last active one
15186 if (cell->is_active() == true)
15187 return cell;
15188 while ((--cell).state() == IteratorState::valid)
15189 if (cell->is_active() == true)
15190 return cell;
15191 }
15192 return cell;
15193}
15194
15195
15196
15197template <int dim, int spacedim>
15201 const CellId &cell_id) const
15202{
15203 Assert(
15204 this->contains_cell(cell_id),
15205 ExcMessage(
15206 "CellId is invalid for this triangulation.\n"
15207 "Either the provided CellId does not correspond to a cell in this "
15208 "triangulation object, or, in case you are using a parallel "
15209 "triangulation, may correspond to an artificial cell that is less "
15210 "refined on this processor. In the case of "
15211 "parallel::fullydistributed::Triangulation, the corresponding coarse "
15212 "cell might not be accessible by the current process."));
15213
15214 cell_iterator cell(
15215 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
15216
15217 for (const auto &child_index : cell_id.get_child_indices())
15218 cell = cell->child(static_cast<unsigned int>(child_index));
15219
15220 return cell;
15221}
15222
15223
15224
15225template <int dim, int spacedim>
15227bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
15228{
15229 const auto coarse_cell_index =
15230 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
15231
15232 if (coarse_cell_index == numbers::invalid_unsigned_int)
15233 return false;
15234
15235 cell_iterator cell(this, 0, coarse_cell_index);
15236
15237 for (const auto &child_index : cell_id.get_child_indices())
15238 {
15239 if (cell->has_children() == false)
15240 return false;
15241 cell = cell->child(static_cast<unsigned int>(child_index));
15242 }
15243
15244 return true;
15245}
15246
15247
15248
15249template <int dim, int spacedim>
15253{
15254 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15255 -1,
15256 -1);
15257}
15258
15259
15260
15261template <int dim, int spacedim>
15264 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
15265{
15266 // This function may be called on parallel triangulations on levels
15267 // that exist globally, but not on the local portion of the
15268 // triangulation. In that case, just return the end iterator.
15269 //
15270 // We need to use levels.size() instead of n_levels() because the
15271 // latter function uses the cache, but we need to be able to call
15272 // this function at a time when the cache is not currently up to
15273 // date.
15274 if (level >= levels.size())
15275 {
15276 Assert(level < n_global_levels(),
15277 ExcInvalidLevel(level, n_global_levels()));
15278 return end();
15279 }
15280
15281 // Query whether the given level is valid for the local portion of the
15282 // triangulation.
15283 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15284 if (level < levels.size() - 1)
15285 return begin_raw(level + 1);
15286 else
15287 return end();
15288}
15289
15290
15291template <int dim, int spacedim>
15294 Triangulation<dim, spacedim>::end(const unsigned int level) const
15295{
15296 // This function may be called on parallel triangulations on levels
15297 // that exist globally, but not on the local portion of the
15298 // triangulation. In that case, just return the end iterator.
15299 //
15300 // We need to use levels.size() instead of n_levels() because the
15301 // latter function uses the cache, but we need to be able to call
15302 // this function at a time when the cache is not currently up to
15303 // date.
15304 if (level >= levels.size())
15305 {
15306 Assert(level < n_global_levels(),
15307 ExcInvalidLevel(level, n_global_levels()));
15308 return end();
15309 }
15310
15311 // Query whether the given level is valid for the local portion of the
15312 // triangulation.
15313 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15314 if (level < levels.size() - 1)
15315 return begin(level + 1);
15316 else
15317 return end();
15318}
15319
15320
15321template <int dim, int spacedim>
15324 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
15325{
15326 // This function may be called on parallel triangulations on levels
15327 // that exist globally, but not on the local portion of the
15328 // triangulation. In that case, just return the end iterator.
15329 //
15330 // We need to use levels.size() instead of n_levels() because the
15331 // latter function uses the cache, but we need to be able to call
15332 // this function at a time when the cache is not currently up to
15333 // date.
15334 if (level >= levels.size())
15335 {
15336 Assert(level < n_global_levels(),
15337 ExcInvalidLevel(level, n_global_levels()));
15338 return end();
15339 }
15340
15341 // Query whether the given level is valid for the local portion of the
15342 // triangulation.
15343 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15344 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
15345 begin_active(level + 1));
15346}
15347
15348
15349
15350template <int dim, int spacedim>
15354 const
15355{
15357 begin(), end());
15358}
15359
15360
15361template <int dim, int spacedim>
15364 active_cell_iterator> Triangulation<dim, spacedim>::
15366{
15367 return IteratorRange<
15369 end());
15370}
15371
15372
15373
15374template <int dim, int spacedim>
15377 cell_iterator> Triangulation<dim, spacedim>::
15378 cell_iterators_on_level(const unsigned int level) const
15379{
15381 begin(level), end(level));
15382}
15383
15384
15385
15386template <int dim, int spacedim>
15389 active_cell_iterator> Triangulation<dim, spacedim>::
15390 active_cell_iterators_on_level(const unsigned int level) const
15391{
15392 return IteratorRange<
15394 begin_active(level), end_active(level));
15395}
15396#endif
15397
15398/*------------------------ Face iterator functions ------------------------*/
15399
15400#ifndef DOXYGEN
15401
15402template <int dim, int spacedim>
15406{
15407 switch (dim)
15408 {
15409 case 1:
15410 Assert(false, ExcImpossibleInDim(1));
15411 return raw_face_iterator();
15412 case 2:
15413 return begin_line();
15414 case 3:
15415 return begin_quad();
15416 default:
15418 return face_iterator();
15419 }
15420}
15421
15422
15423
15424template <int dim, int spacedim>
15428{
15429 switch (dim)
15430 {
15431 case 1:
15432 Assert(false, ExcImpossibleInDim(1));
15433 return raw_face_iterator();
15434 case 2:
15435 return begin_active_line();
15436 case 3:
15437 return begin_active_quad();
15438 default:
15440 return active_face_iterator();
15441 }
15442}
15443
15444
15445
15446template <int dim, int spacedim>
15450{
15451 switch (dim)
15452 {
15453 case 1:
15454 Assert(false, ExcImpossibleInDim(1));
15455 return raw_face_iterator();
15456 case 2:
15457 return end_line();
15458 case 3:
15459 return end_quad();
15460 default:
15462 return raw_face_iterator();
15463 }
15464}
15465
15466
15467
15468template <int dim, int spacedim>
15471 active_face_iterator> Triangulation<dim, spacedim>::
15473{
15474 return IteratorRange<
15476 begin_active_face(), end_face());
15477}
15478
15479/*------------------------ Vertex iterator functions ------------------------*/
15480
15481
15482template <int dim, int spacedim>
15486{
15487 vertex_iterator i =
15488 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15489 if (i.state() != IteratorState::valid)
15490 return i;
15491 // This loop will end because every triangulation has used vertices.
15492 while (i->used() == false)
15493 if ((++i).state() != IteratorState::valid)
15494 return i;
15495 return i;
15496}
15497
15498
15499
15500template <int dim, int spacedim>
15504{
15505 // every vertex is active
15506 return begin_vertex();
15507}
15508
15509
15510
15511template <int dim, int spacedim>
15515{
15516 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15517 -1,
15519}
15520
15521#endif
15522
15523
15524/*------------------------ Line iterator functions ------------------------*/
15525
15526#ifndef DOXYGEN
15527
15528template <int dim, int spacedim>
15531 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
15532{
15533 // This function may be called on parallel triangulations on levels
15534 // that exist globally, but not on the local portion of the
15535 // triangulation. In that case, just return the end iterator.
15536 //
15537 // We need to use levels.size() instead of n_levels() because the
15538 // latter function uses the cache, but we need to be able to call
15539 // this function at a time when the cache is not currently up to
15540 // date.
15541 if (level >= levels.size())
15542 {
15543 Assert(level < n_global_levels(),
15544 ExcInvalidLevel(level, n_global_levels()));
15545 return end_line();
15546 }
15547
15548 switch (dim)
15549 {
15550 case 1:
15551 // Query whether the given level is valid for the local portion of the
15552 // triangulation.
15553 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15554
15555 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15556 return end_line();
15557
15558 return raw_line_iterator(
15559 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15560
15561 default:
15562 Assert(level == 0, ExcFacesHaveNoLevel());
15563 return raw_line_iterator(
15564 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15565 }
15566}
15567
15568
15569template <int dim, int spacedim>
15572 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
15573{
15574 // level is checked in begin_raw
15575 raw_line_iterator ri = begin_raw_line(level);
15576 if (ri.state() != IteratorState::valid)
15577 return ri;
15578 while (ri->used() == false)
15579 if ((++ri).state() != IteratorState::valid)
15580 return ri;
15581 return ri;
15582}
15583
15584
15585
15586template <int dim, int spacedim>
15590 const unsigned int level) const
15591{
15592 // level is checked in begin_raw
15593 line_iterator i = begin_line(level);
15594 if (i.state() != IteratorState::valid)
15595 return i;
15596 while (i->has_children())
15597 if ((++i).state() != IteratorState::valid)
15598 return i;
15599 return i;
15600}
15601
15602
15603
15604template <int dim, int spacedim>
15608{
15609 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15610 -1,
15611 -1);
15612}
15613
15614#endif
15615
15616/*------------------------ Quad iterator functions ------------------------*/
15617
15618#ifndef DOXYGEN
15619
15620template <int dim, int spacedim>
15623 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
15624{
15625 // This function may be called on parallel triangulations on levels
15626 // that exist globally, but not on the local portion of the
15627 // triangulation. In that case, just return the end iterator.
15628 //
15629 // We need to use levels.size() instead of n_levels() because the
15630 // latter function uses the cache, but we need to be able to call
15631 // this function at a time when the cache is not currently up to
15632 // date.
15633 if (level >= levels.size())
15634 {
15635 Assert(level < n_global_levels(),
15636 ExcInvalidLevel(level, n_global_levels()));
15637 return end_quad();
15638 }
15639
15640 switch (dim)
15641 {
15642 case 1:
15643 Assert(false, ExcImpossibleInDim(1));
15644 return raw_hex_iterator();
15645 case 2:
15646 {
15647 // Query whether the given level is valid for the local portion of the
15648 // triangulation.
15649 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15650
15651 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15652 return end_quad();
15653
15654 return raw_quad_iterator(
15655 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15656 }
15657
15658 case 3:
15659 {
15660 Assert(level == 0, ExcFacesHaveNoLevel());
15661
15662 return raw_quad_iterator(
15663 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15664 }
15665
15666
15667 default:
15669 return raw_hex_iterator();
15670 }
15671}
15672
15673
15674
15675template <int dim, int spacedim>
15678 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
15679{
15680 // level is checked in begin_raw
15681 raw_quad_iterator ri = begin_raw_quad(level);
15682 if (ri.state() != IteratorState::valid)
15683 return ri;
15684 while (ri->used() == false)
15685 if ((++ri).state() != IteratorState::valid)
15686 return ri;
15687 return ri;
15688}
15689
15690
15691
15692template <int dim, int spacedim>
15696 const unsigned int level) const
15697{
15698 // level is checked in begin_raw
15699 quad_iterator i = begin_quad(level);
15700 if (i.state() != IteratorState::valid)
15701 return i;
15702 while (i->has_children())
15703 if ((++i).state() != IteratorState::valid)
15704 return i;
15705 return i;
15706}
15707
15708
15709
15710template <int dim, int spacedim>
15714{
15715 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15716 -1,
15717 -1);
15718}
15719
15720#endif
15721
15722/*------------------------ Hex iterator functions ------------------------*/
15723
15724#ifndef DOXYGEN
15725
15726template <int dim, int spacedim>
15729 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
15730{
15731 // This function may be called on parallel triangulations on levels
15732 // that exist globally, but not on the local portion of the
15733 // triangulation. In that case, just return the end iterator.
15734 //
15735 // We need to use levels.size() instead of n_levels() because the
15736 // latter function uses the cache, but we need to be able to call
15737 // this function at a time when the cache is not currently up to
15738 // date.
15739 if (level >= levels.size())
15740 {
15741 Assert(level < n_global_levels(),
15742 ExcInvalidLevel(level, n_global_levels()));
15743 return end_hex();
15744 }
15745
15746 switch (dim)
15747 {
15748 case 1:
15749 case 2:
15750 Assert(false, ExcImpossibleInDim(1));
15751 return raw_hex_iterator();
15752 case 3:
15753 {
15754 // Query whether the given level is valid for the local portion of the
15755 // triangulation.
15756 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15757
15758 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15759 return end_hex();
15760
15761 return raw_hex_iterator(
15762 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15763 }
15764
15765 default:
15767 return raw_hex_iterator();
15768 }
15769}
15770
15771
15772
15773template <int dim, int spacedim>
15776 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
15777{
15778 // level is checked in begin_raw
15779 raw_hex_iterator ri = begin_raw_hex(level);
15780 if (ri.state() != IteratorState::valid)
15781 return ri;
15782 while (ri->used() == false)
15783 if ((++ri).state() != IteratorState::valid)
15784 return ri;
15785 return ri;
15786}
15787
15788
15789
15790template <int dim, int spacedim>
15794{
15795 // level is checked in begin_raw
15796 hex_iterator i = begin_hex(level);
15797 if (i.state() != IteratorState::valid)
15798 return i;
15799 while (i->has_children())
15800 if ((++i).state() != IteratorState::valid)
15801 return i;
15802 return i;
15803}
15804
15805
15806
15807template <int dim, int spacedim>
15811{
15812 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15813 -1,
15814 -1);
15815}
15816
15817#endif
15818
15819// -------------------------------- number of cells etc ---------------
15820
15821
15822namespace internal
15823{
15824 namespace TriangulationImplementation
15825 {
15826 unsigned int
15828 {
15829 return c.n_lines;
15830 }
15831
15832
15833 unsigned int
15836 {
15837 return c.n_active_lines;
15838 }
15839
15840
15841 unsigned int
15843 {
15844 return c.n_quads;
15845 }
15846
15847
15848 unsigned int
15851 {
15852 return c.n_active_quads;
15853 }
15854
15855
15856 unsigned int
15858 {
15859 return c.n_hexes;
15860 }
15861
15862
15863 unsigned int
15866 {
15867 return c.n_active_hexes;
15868 }
15869 } // namespace TriangulationImplementation
15870} // namespace internal
15871
15872#ifndef DOXYGEN
15873
15874template <int dim, int spacedim>
15876unsigned int Triangulation<dim, spacedim>::n_cells() const
15877{
15879}
15880
15881
15882template <int dim, int spacedim>
15885{
15887}
15888
15889template <int dim, int spacedim>
15893{
15894 return n_active_cells();
15895}
15896
15897template <int dim, int spacedim>
15901{
15902 return n_cells(0);
15903}
15904
15905template <int dim, int spacedim>
15907unsigned int Triangulation<dim, spacedim>::n_faces() const
15908{
15909 switch (dim)
15910 {
15911 case 1:
15912 return n_used_vertices();
15913 case 2:
15914 return n_lines();
15915 case 3:
15916 return n_quads();
15917 default:
15919 }
15920 return 0;
15921}
15922
15923
15924template <int dim, int spacedim>
15927{
15928 switch (dim)
15929 {
15930 case 1:
15931 return n_vertices();
15932 case 2:
15933 return n_raw_lines();
15934 case 3:
15935 return n_raw_quads();
15936 default:
15938 }
15939 return 0;
15940}
15941
15942
15943template <int dim, int spacedim>
15946{
15947 switch (dim)
15948 {
15949 case 1:
15950 return n_used_vertices();
15951 case 2:
15952 return n_active_lines();
15953 case 3:
15954 return n_active_quads();
15955 default:
15957 }
15958 return 0;
15959}
15960
15961
15962template <int dim, int spacedim>
15965 const unsigned int level) const
15966{
15967 switch (dim)
15968 {
15969 case 1:
15970 return n_raw_lines(level);
15971 case 2:
15972 return n_raw_quads(level);
15973 case 3:
15974 return n_raw_hexs(level);
15975 default:
15977 }
15978 return 0;
15979}
15980
15981
15982
15983template <int dim, int spacedim>
15986 const unsigned int level) const
15987{
15988 switch (dim)
15989 {
15990 case 1:
15991 return n_lines(level);
15992 case 2:
15993 return n_quads(level);
15994 case 3:
15995 return n_hexs(level);
15996 default:
15998 }
15999 return 0;
16000}
16001
16002
16003
16004template <int dim, int spacedim>
16007 const unsigned int level) const
16008{
16009 switch (dim)
16010 {
16011 case 1:
16012 return n_active_lines(level);
16013 case 2:
16014 return n_active_quads(level);
16015 case 3:
16016 return n_active_hexs(level);
16017 default:
16019 }
16020 return 0;
16021}
16022
16023
16024template <int dim, int spacedim>
16027{
16028 if (anisotropic_refinement == false)
16029 {
16030 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
16031 if (n_active_cells(lvl) != 0)
16032 return true;
16033 }
16034 else
16035 {
16036 for (const auto &cell : active_cell_iterators())
16037 for (const auto &i : cell->face_indices())
16038 if (cell->face(i)->has_children())
16039 return true;
16040 }
16041 return false;
16042}
16043
16044
16045template <int dim, int spacedim>
16047unsigned int Triangulation<dim, spacedim>::n_lines() const
16048{
16049 return number_cache.n_lines;
16050}
16051
16052
16053
16054template <int dim, int spacedim>
16057 const unsigned int level) const
16058{
16059 if (dim == 1)
16060 {
16061 AssertIndexRange(level, n_levels());
16062 return levels[level]->cells.n_objects();
16063 }
16064
16065 Assert(false, ExcFacesHaveNoLevel());
16066 return 0;
16067}
16068
16069
16070template <int dim, int spacedim>
16073{
16074 if (dim == 1)
16075 {
16077 return 0;
16078 }
16079
16080 return faces->lines.n_objects();
16081}
16082
16083
16084template <int dim, int spacedim>
16087 const unsigned int level) const
16088{
16089 AssertIndexRange(level, number_cache.n_lines_level.size());
16090 Assert(dim == 1, ExcFacesHaveNoLevel());
16091 return number_cache.n_lines_level[level];
16092}
16093
16094
16095template <int dim, int spacedim>
16098{
16099 return number_cache.n_active_lines;
16100}
16101
16102
16103template <int dim, int spacedim>
16106 const unsigned int level) const
16107{
16108 AssertIndexRange(level, number_cache.n_lines_level.size());
16109 Assert(dim == 1, ExcFacesHaveNoLevel());
16110
16111 return number_cache.n_active_lines_level[level];
16112}
16113
16114
16115
16116template <int dim, int spacedim>
16118unsigned int Triangulation<dim, spacedim>::n_quads() const
16119{
16120 if constexpr (dim == 1)
16121 return 0;
16122 else
16123 return number_cache.n_quads;
16124}
16125
16126
16127
16128template <int dim, int spacedim>
16131 const unsigned int level) const
16132{
16133 (void)level;
16134 if constexpr (dim == 1)
16135 return 0;
16136 else if constexpr (dim == 2)
16137 {
16138 AssertIndexRange(level, number_cache.n_quads_level.size());
16139 return number_cache.n_quads_level[level];
16140 }
16141 else if constexpr (dim == 3)
16142 Assert(dim < 3, ExcFacesHaveNoLevel());
16143 else
16145
16147}
16148
16149
16150
16151template <int dim, int spacedim>
16154{
16155 if constexpr (dim == 1)
16156 return 0;
16157 else if constexpr (dim == 2)
16159 else if constexpr (dim == 3)
16160 return faces->quads.n_objects();
16161 else
16163
16165}
16166
16167
16168
16169template <int dim, int spacedim>
16172 const unsigned int level) const
16173{
16174 (void)level;
16175 if constexpr (dim == 1)
16176 return 0;
16177 else if constexpr (dim == 2)
16178 {
16179 AssertIndexRange(level, n_levels());
16180 return levels[level]->cells.n_objects();
16181 }
16182 else if constexpr (dim == 3)
16183 Assert(dim < 3, ExcFacesHaveNoLevel());
16184 else
16186
16188}
16189
16190
16191
16192template <int dim, int spacedim>
16195{
16196 if constexpr (dim == 1)
16197 return 0;
16198 else
16199 return number_cache.n_active_quads;
16200}
16201
16202
16203
16204template <int dim, int spacedim>
16207 const unsigned int level) const
16208{
16209 (void)level;
16210 if constexpr (dim == 1)
16211 return 0;
16212 else if constexpr (dim == 2)
16213 {
16214 AssertIndexRange(level, number_cache.n_quads_level.size());
16215 return number_cache.n_active_quads_level[level];
16216 }
16217 else if constexpr (dim == 3)
16218 Assert(dim < 3, ExcFacesHaveNoLevel());
16219 else
16221
16223}
16224
16225
16226
16227template <int dim, int spacedim>
16229unsigned int Triangulation<dim, spacedim>::n_hexs() const
16230{
16231 if constexpr (dim == 3)
16232 return number_cache.n_hexes;
16233 else
16234 return 0;
16235}
16236
16237
16238
16239template <int dim, int spacedim>
16242 const unsigned int level) const
16243{
16244 (void)level;
16245 if constexpr (dim == 3)
16246 {
16247 AssertIndexRange(level, number_cache.n_hexes_level.size());
16248 return number_cache.n_hexes_level[level];
16249 }
16250 else
16251 return 0;
16252}
16253
16254
16255
16256template <int dim, int spacedim>
16259 const unsigned int level) const
16260{
16261 (void)level;
16262 if constexpr (dim == 3)
16263 {
16264 AssertIndexRange(level, n_levels());
16265 return levels[level]->cells.n_objects();
16266 }
16267 else
16268 return 0;
16269}
16270
16271
16272template <int dim, int spacedim>
16275{
16276 if constexpr (dim == 3)
16277 return number_cache.n_active_hexes;
16278 else
16279 return 0;
16280}
16281
16282
16283
16284template <int dim, int spacedim>
16287 const unsigned int level) const
16288{
16289 (void)level;
16290 if constexpr (dim == 3)
16291 {
16292 AssertIndexRange(level, number_cache.n_hexes_level.size());
16293 return number_cache.n_active_hexes_level[level];
16294 }
16295 else
16296 return 0;
16297}
16298
16299
16300
16301template <int dim, int spacedim>
16304{
16305 return std::count(vertices_used.begin(), vertices_used.end(), true);
16306}
16307
16308
16309
16310template <int dim, int spacedim>
16312const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
16313{
16314 return vertices_used;
16315}
16316
16317#endif
16318
16319template <>
16320unsigned int
16322{
16323 return 2;
16324}
16325
16326
16327
16328template <>
16329unsigned int
16331{
16332 return 2;
16333}
16334
16335
16336template <>
16337unsigned int
16339{
16340 return 2;
16341}
16342
16343#ifndef DOXYGEN
16344
16345template <int dim, int spacedim>
16348{
16349 cell_iterator cell = begin(0),
16350 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
16351 // store the largest index of the
16352 // vertices used on level 0
16353 unsigned int max_vertex_index = 0;
16354 for (; cell != endc; ++cell)
16355 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16356 if (cell->vertex_index(vertex) > max_vertex_index)
16357 max_vertex_index = cell->vertex_index(vertex);
16358
16359 // store the number of times a cell
16360 // touches a vertex. An unsigned
16361 // int should suffice, even for
16362 // larger dimensions
16363 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
16364 // touch a vertex's usage count
16365 // every time we find an adjacent
16366 // element
16367 for (cell = begin(); cell != endc; ++cell)
16368 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16369 ++usage_count[cell->vertex_index(vertex)];
16370
16372 static_cast<unsigned int>(
16373 *std::max_element(usage_count.begin(), usage_count.end())));
16374}
16375
16376
16377
16378template <int dim, int spacedim>
16382{
16384}
16385
16386
16387
16388template <int dim, int spacedim>
16391{
16392 return *this;
16393}
16394
16395
16396
16397template <int dim, int spacedim>
16401{
16402 return *this;
16403}
16404
16405
16406
16407template <int dim, int spacedim>
16411 &periodicity_vector)
16412{
16413 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
16414 periodicity_vector.begin(),
16415 periodicity_vector.end());
16416
16417 // Now initialize periodic_face_map
16418 update_periodic_face_map();
16419}
16420
16421
16422
16423template <int dim, int spacedim>
16425const typename std::map<
16426 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
16427 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
16428 unsigned int>,
16431{
16432 return periodic_face_map;
16433}
16434
16435
16436template <int dim, int spacedim>
16439{
16440 // We only update the cell relations here for serial triangulations.
16441 // For other triangulations, this is done at other stages of
16442 // mesh creation and mesh refinement.
16444 this))
16445 return;
16446
16447 this->local_cell_relations.clear();
16448 this->local_cell_relations.reserve(this->n_active_cells());
16449
16450 for (const auto &cell : this->active_cell_iterators())
16451 this->local_cell_relations.emplace_back(
16452 cell, ::CellStatus::cell_will_persist);
16453}
16454
16455
16456
16457template <int dim, int spacedim>
16460{
16462 this))
16463 return;
16464
16465 // pack data before triangulation gets updated
16466 if (this->cell_attached_data.n_attached_data_sets > 0)
16467 {
16468 this->local_cell_relations.clear();
16469
16470 for (const auto &cell : this->active_cell_iterators())
16471 {
16472 const bool children_will_be_coarsened =
16473 (cell->level() > 0) && (cell->coarsen_flag_set());
16474
16475 if (children_will_be_coarsened == false)
16476 {
16477 ::CellStatus status =
16478 cell->refine_flag_set() ?
16481
16482 local_cell_relations.emplace_back(cell, status);
16483 }
16484 else if (cell->parent()->child_iterator_to_index(cell) == 0)
16485 {
16486 local_cell_relations.emplace_back(
16487 cell->parent(),
16489
16490 for (unsigned int i = 1; i < cell->parent()->n_children(); ++i)
16491 local_cell_relations.emplace_back(
16492 cell->parent(), ::CellStatus::cell_invalid);
16493 }
16494 }
16495
16496 // pack data
16497 this->data_serializer.pack_data(
16498 this->local_cell_relations,
16499 this->cell_attached_data.pack_callbacks_fixed,
16500 this->cell_attached_data.pack_callbacks_variable,
16501 this->get_mpi_communicator());
16502
16503 // dummy copy of data
16504 this->data_serializer.dest_data_fixed =
16505 this->data_serializer.src_data_fixed;
16506 this->data_serializer.dest_data_variable =
16507 this->data_serializer.src_data_variable;
16508 this->data_serializer.dest_sizes_variable =
16509 this->data_serializer.src_sizes_variable;
16510 }
16511}
16512
16513
16514
16515template <int dim, int spacedim>
16518{
16520 this))
16521 return;
16522
16523 // transfer data after triangulation got updated
16524 if (this->cell_attached_data.n_attached_data_sets > 0)
16525 {
16526 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
16527 cell_relation_t>
16528 temp;
16529
16530 for (const auto &cell : local_cell_relations)
16531 {
16532 if (cell.first->has_children())
16533 {
16536
16537 temp.emplace_back(cell.first->child(0),
16539 }
16540 else
16541 temp.push_back(cell);
16542 }
16543
16544 this->local_cell_relations = std::move(temp);
16545 }
16546}
16547
16548
16549
16550template <int dim, int spacedim>
16553{
16554 // Call our version of prepare_coarsening_and_refinement() even if a derived
16555 // class like parallel::distributed::Triangulation overrides it. Their
16556 // function will be called in their execute_coarsening_and_refinement()
16557 // function. Even in a distributed computation our job here is to reconstruct
16558 // the local part of the mesh and as such checking our flags is enough.
16560
16561 // verify a case with which we have had
16562 // some difficulty in the past (see the
16563 // deal.II/coarsening_* tests)
16564 if (smooth_grid & limit_level_difference_at_vertices)
16565 Assert(satisfies_level1_at_vertex_rule(*this), ExcInternalError());
16566
16567 // Inform all listeners about beginning of refinement.
16568 signals.pre_refinement();
16569
16570 this->pack_data_serial();
16571
16572 execute_coarsening();
16573
16574 const DistortedCellList cells_with_distorted_children = execute_refinement();
16575
16576 // We need to update the cell relations in order to be able to
16577 // deserialize data. Later on, update_cell_relations is called to mark all
16578 // active cells with the cell_will_persist status.
16579 this->unpack_data_serial();
16580
16581 reset_cell_vertex_indices_cache();
16582
16583 // If the line_to_adjacent_cell_map is populated, clear it, as it must
16584 // be recomputed every time the mesh changes.
16585 line_to_adjacent_cells_map.reset();
16586
16587 // verify a case with which we have had
16588 // some difficulty in the past (see the
16589 // deal.II/coarsening_* tests)
16590 if (smooth_grid & limit_level_difference_at_vertices)
16591 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
16592
16593 // finally build up neighbor connectivity information, and set
16594 // active cell indices
16595 this->policy->update_neighbors(*this);
16596 reset_active_cell_indices();
16597
16598 reset_global_cell_indices(); // TODO: better place?
16599
16600 // Inform all listeners about end of refinement.
16601 signals.post_refinement();
16602
16603 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
16604 cells_with_distorted_children);
16605
16606 update_periodic_face_map();
16607
16608 if (this->cell_attached_data.n_attached_data_sets == 0)
16609 this->update_cell_relations();
16610
16611 if constexpr (running_in_debug_mode())
16612 {
16613 // In debug mode, we want to check for some consistency of the
16614 // result of this function. Because there are multiple exit
16615 // paths, put this check into a ScopeExit object that is
16616 // executed on each of the exit paths.
16617 //
16618 // Specifically, check on exit of this function that if a quad
16619 // cell has been refined, all of its children have neighbors
16620 // in all directions in which the parent cell has neighbors as
16621 // well. The children's neighbors are either the parent
16622 // neighbor or the parent neighbor's children, or simply one of
16623 // the other children of the current cell. This check is
16624 // useful because if one creates a triangulation with an
16625 // inconsistently ordered set of cells (e.g., because one has
16626 // forgotten to call GridTools::consistently_order_cells()),
16627 // then this relatively simple invariant is violated -- so the
16628 // check here can be used to catch that case, at least
16629 // sometimes.
16630 //
16631 // In 1d, this situation cannot happen. In 3d, we have explicit
16632 // orientation flags to ensure that it is not necessary to re-orient
16633 // cells at the beginning. But in both cases, the invariant should
16634 // still hold as long as the cell is a hypercube.
16635 for (const auto &cell : cell_iterators())
16636 {
16637 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
16638 for (const unsigned int f : cell->face_indices())
16639 if (cell->at_boundary(f) == false)
16640 {
16641 for (const auto &child : cell->child_iterators())
16642 {
16643 Assert(
16644 child->at_boundary(f) == false,
16645 ExcMessage(
16646 "We ended up with a triangulation whose child cells "
16647 "are not connected to their neighbors as expected. "
16648 "When you created the triangulation, did you forget "
16649 "to call GridTools::consistently_order_cells() "
16650 "before calling Triangulation::create_triangulation()?"));
16651 }
16652 }
16653 }
16654 }
16655}
16656
16657
16658
16659template <int dim, int spacedim>
16662{
16663 unsigned int active_cell_index = 0;
16664 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
16665 if ((cell->used() == false) || cell->has_children())
16666 cell->set_active_cell_index(numbers::invalid_unsigned_int);
16667 else
16668 {
16669 cell->set_active_cell_index(active_cell_index);
16670 ++active_cell_index;
16671 }
16672
16673 Assert(active_cell_index == n_active_cells(), ExcInternalError());
16674}
16675
16676
16677
16678template <int dim, int spacedim>
16681{
16682 types::global_cell_index active_cell_index = 0;
16683 for (unsigned int l = 0; l < levels.size(); ++l)
16684 {
16685 types::global_cell_index level_cell_index = 0;
16686 for (const auto &cell : cell_iterators_on_level(l))
16687 {
16688 cell->set_global_level_cell_index(level_cell_index++);
16689 if (cell->is_active())
16690 cell->set_global_active_cell_index(active_cell_index++);
16691 }
16692 }
16693 AssertDimension(active_cell_index, this->n_active_cells());
16694}
16695
16696
16697
16698template <int dim, int spacedim>
16701{
16702 for (unsigned int l = 0; l < levels.size(); ++l)
16703 for (const auto &cell : cell_iterators_on_level(l))
16704 {
16705 const unsigned int n_vertices = cell->n_vertices();
16706
16708 ReferenceCells::max_n_vertices<dim>()>
16709 cell_vertices(n_vertices);
16710 if constexpr (running_in_debug_mode())
16711 std::fill(cell_vertices.begin(),
16712 cell_vertices.end(),
16714
16715 GridTools::internal::extract_vertices_without_cache<dim, spacedim>(
16716 cell, cell_vertices);
16717 for (unsigned int vertex_no = 0; vertex_no < n_vertices; ++vertex_no)
16718 levels[l]->set_cached_vertex_index(cell->index(),
16719 vertex_no,
16720 cell_vertices[vertex_no]);
16721 }
16722}
16723
16724
16725
16726template <int dim, int spacedim>
16729{
16730 // first empty the currently stored objects
16731 periodic_face_map.clear();
16732
16733 typename std::vector<
16735 for (it = periodic_face_pairs_level_0.begin();
16736 it != periodic_face_pairs_level_0.end();
16737 ++it)
16738 {
16739 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16740 it->cell[1],
16741 it->face_idx[0],
16742 it->face_idx[1],
16743 it->orientation,
16744 periodic_face_map);
16745
16746 const auto face_reference_cell =
16747 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16748 // for the other way, we need to invert the orientation
16749 update_periodic_face_map_recursively<dim, spacedim>(
16750 it->cell[1],
16751 it->cell[0],
16752 it->face_idx[1],
16753 it->face_idx[0],
16754 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16755 periodic_face_map);
16756 }
16757
16758 // check consistency
16759 typename std::map<std::pair<cell_iterator, unsigned int>,
16760 std::pair<std::pair<cell_iterator, unsigned int>,
16761 types::geometric_orientation>>::const_iterator
16762 it_test;
16763 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16764 ++it_test)
16765 {
16767 it_test->first.first;
16769 it_test->second.first.first;
16770 if (cell_1->level() == cell_2->level())
16771 {
16772 // if both cells have the same neighbor, then the same pair
16773 // order swapped has to be in the map
16774 Assert(periodic_face_map[it_test->second.first].first ==
16775 it_test->first,
16777 }
16778 }
16779}
16780
16781
16782
16783template <int dim, int spacedim>
16785const std::vector<ReferenceCell<dim>>
16787{
16788 return this->reference_cells;
16789}
16790
16791
16792
16793template <int dim, int spacedim>
16796{
16797 Assert(this->reference_cells.size() > 0,
16798 ExcMessage("You can't ask about the kinds of reference "
16799 "cells used by this triangulation if the "
16800 "triangulation doesn't yet have any cells in it."));
16801 return (this->reference_cells.size() == 1 &&
16802 this->reference_cells[0].is_hyper_cube());
16803}
16804
16805
16806
16807template <int dim, int spacedim>
16810{
16811 Assert(this->reference_cells.size() > 0,
16812 ExcMessage("You can't ask about the kinds of reference "
16813 "cells used by this triangulation if the "
16814 "triangulation doesn't yet have any cells in it."));
16815 return (this->reference_cells.size() == 1 &&
16816 this->reference_cells[0].is_simplex());
16817}
16818
16819
16820
16821template <int dim, int spacedim>
16824{
16825 Assert(this->reference_cells.size() > 0,
16826 ExcMessage("You can't ask about the kinds of reference "
16827 "cells used by this triangulation if the "
16828 "triangulation doesn't yet have any cells in it."));
16829 return reference_cells.size() > 1 ||
16830 ((reference_cells[0].is_hyper_cube() == false) &&
16831 (reference_cells[0].is_simplex() == false));
16832}
16833
16834
16835
16836template <int dim, int spacedim>
16839 const std::function<std::vector<char>(const cell_iterator &,
16840 const ::CellStatus)>
16841 &pack_callback,
16842 const bool returns_variable_size_data)
16843{
16844 unsigned int handle = numbers::invalid_unsigned_int;
16845
16846 // Add new callback function to the corresponding register.
16847 // Encode handles according to returns_variable_size_data.
16848 if (returns_variable_size_data)
16849 {
16850 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16851 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16852 }
16853 else
16854 {
16855 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16856 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16857 }
16858
16859 // Increase overall counter.
16860 ++this->cell_attached_data.n_attached_data_sets;
16861
16862 return handle;
16863}
16864
16865
16866
16867template <int dim, int spacedim>
16870 const unsigned int handle,
16871 const std::function<
16872 void(const cell_iterator &,
16873 const ::CellStatus,
16874 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16875 &unpack_callback)
16876{
16877 // perform unpacking
16878 this->data_serializer.unpack_data(this->local_cell_relations,
16879 handle,
16880 unpack_callback);
16881
16882 // decrease counters
16883 --this->cell_attached_data.n_attached_data_sets;
16884 if (this->cell_attached_data.n_attached_deserialize > 0)
16885 --this->cell_attached_data.n_attached_deserialize;
16886
16887 // important: only remove data if we are not in the deserialization
16888 // process. There, each SolutionTransfer registers and unpacks before
16889 // the next one does this, so n_attached_data_sets is only 1 here. This
16890 // would destroy the saved data before the second SolutionTransfer can
16891 // get it. This created a bug that is documented in
16892 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16893
16894 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16895 this->cell_attached_data.n_attached_deserialize == 0)
16896 {
16897 // everybody got their data, time for cleanup!
16898 this->cell_attached_data.pack_callbacks_fixed.clear();
16899 this->cell_attached_data.pack_callbacks_variable.clear();
16900 this->data_serializer.clear();
16901
16902 // reset all cell_status entries after coarsening/refinement
16903 for (auto &cell_rel : this->local_cell_relations)
16904 cell_rel.second = ::CellStatus::cell_will_persist;
16905 }
16906}
16907
16908
16909
16910template <int dim, int spacedim>
16913 const unsigned int global_first_cell,
16914 const unsigned int global_num_cells,
16915 const std::string &file_basename) const
16916{
16917 // cast away constness
16918 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16919
16920 // each cell should have been flagged `CellStatus::cell_will_persist`
16921 for (const auto &cell_rel : this->local_cell_relations)
16922 {
16923 (void)cell_rel;
16924 Assert((cell_rel.second == // cell_status
16927 }
16928
16929 if (this->cell_attached_data.n_attached_data_sets > 0)
16930 {
16931 // pack attached data first
16932 tria->data_serializer.pack_data(
16933 tria->local_cell_relations,
16934 tria->cell_attached_data.pack_callbacks_fixed,
16935 tria->cell_attached_data.pack_callbacks_variable,
16936 this->get_mpi_communicator());
16937
16938 // then store buffers in file
16939 tria->data_serializer.save(global_first_cell,
16940 global_num_cells,
16941 file_basename,
16942 this->get_mpi_communicator());
16943
16944 // and release the memory afterwards
16945 tria->data_serializer.clear();
16946 }
16947
16948 // clear all of the callback data, as explained in the documentation of
16949 // register_data_attach()
16950 {
16951 tria->cell_attached_data.n_attached_data_sets = 0;
16952 tria->cell_attached_data.pack_callbacks_fixed.clear();
16953 tria->cell_attached_data.pack_callbacks_variable.clear();
16954 }
16955}
16956
16957
16958template <int dim, int spacedim>
16961 const unsigned int global_first_cell,
16962 const unsigned int global_num_cells,
16963 const unsigned int local_num_cells,
16964 const std::string &file_basename,
16965 const unsigned int n_attached_deserialize_fixed,
16966 const unsigned int n_attached_deserialize_variable)
16967{
16968 // load saved data, if any was stored
16969 if (this->cell_attached_data.n_attached_deserialize > 0)
16970 {
16971 this->data_serializer.load(global_first_cell,
16972 global_num_cells,
16973 local_num_cells,
16974 file_basename,
16975 n_attached_deserialize_fixed,
16976 n_attached_deserialize_variable,
16977 this->get_mpi_communicator());
16978
16979 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16980
16981 if constexpr (running_in_debug_mode())
16982 {
16983 // the CellStatus of all stored cells should always be
16984 // CellStatus::cell_will_persist.
16985 for (const auto &cell_rel : this->local_cell_relations)
16986 {
16987 Assert((cell_rel.second == // cell_status
16990 }
16991 }
16992 }
16993}
16994
16995
16996template <int dim, int spacedim>
16999{
17000 levels.clear();
17001 faces.reset();
17002
17003 vertices.clear();
17004 vertices_used.clear();
17005
17006 manifolds.clear();
17007
17008 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
17009 if (dim == 1)
17010 {
17011 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
17012 vertex_to_boundary_id_map_1d->clear();
17013
17014 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
17015 vertex_to_manifold_id_map_1d->clear();
17016 }
17017 else
17018 {
17019 // For dim>1, these maps should simply not exist.
17020 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
17021 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
17022 }
17023
17024
17026}
17027
17028
17029
17030template <int dim, int spacedim>
17034{
17035 const DistortedCellList cells_with_distorted_children =
17036 this->policy->execute_refinement(*this, check_for_distorted_cells);
17037
17038
17039
17040 // re-compute number of lines
17042 *this, levels.size(), number_cache);
17043
17044 if constexpr (running_in_debug_mode())
17045 {
17046 for (const auto &level : levels)
17047 monitor_memory(level->cells, dim);
17048
17049 // check whether really all refinement flags are reset (also of
17050 // previously non-active cells which we may not have touched. If the
17051 // refinement flag of a non-active cell is set, something went wrong
17052 // since the cell-accessors should have caught this)
17053 for (const auto &cell : this->cell_iterators())
17054 Assert(!cell->refine_flag_set(), ExcInternalError());
17055 }
17056
17057 return cells_with_distorted_children;
17058}
17059
17060
17061
17062template <int dim, int spacedim>
17065{
17066 // first find out if there are any cells at all to be coarsened in the
17067 // loop below
17068 const cell_iterator endc = end();
17069 bool do_coarsen = false;
17070 if (levels.size() >= 2)
17071 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17072 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17073 {
17074 do_coarsen = true;
17075 break;
17076 }
17077
17078 if (!do_coarsen)
17079 return;
17080
17081 // create a vector counting for each line and quads how many cells contain
17082 // the respective object. this is used later to decide which lines can be
17083 // deleted after coarsening a cell.
17084 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
17085 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
17086 if (dim > 1)
17087 for (const auto &cell : this->cell_iterators())
17088 {
17089 if (dim > 2)
17090 {
17091 const auto line_indices = internal::TriaAccessorImplementation::
17092 Implementation::get_line_indices_of_cell(*cell);
17093 // avoid a compiler warning by fixing the max number of
17094 // loop iterations to 12
17095 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
17096 for (unsigned int l = 0; l < n_lines; ++l)
17097 ++line_cell_count[line_indices[l]];
17098 for (const unsigned int q : cell->face_indices())
17099 ++quad_cell_count[cell->face_index(q)];
17100 }
17101 else
17102 for (unsigned int l = 0; l < cell->n_lines(); ++l)
17103 ++line_cell_count[cell->line(l)->index()];
17104 }
17105
17106 // Since the loop goes over used cells we only need not worry about
17107 // deleting some cells since the ++operator will then just hop over them
17108 // if we should hit one. Do the loop in the reverse way since we may
17109 // only delete some cells if their neighbors have already been deleted
17110 // (if the latter are on a higher level for example). In effect, only
17111 // those cells are deleted of which originally all children were flagged
17112 // and for which all children are on the same refinement level. Note
17113 // that because of the effects of
17114 // @p{fix_coarsen_flags}, of a cell either all or no children must be
17115 // flagged for coarsening, so it is ok to only check the first child
17116 //
17117 // since we delete the *children* of cells, we can ignore cells on the
17118 // highest level, i.e., level must be less than or equal to
17119 // n_levels()-2.
17120 if (levels.size() >= 2)
17121 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17122 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17123 {
17124 for (unsigned int child = 0; child < cell->n_children(); ++child)
17125 {
17126 Assert(cell->child(child)->coarsen_flag_set(),
17128 cell->child(child)->clear_coarsen_flag();
17129 }
17130 // inform all listeners that cell coarsening is going to happen
17131 signals.pre_coarsening_on_cell(cell);
17132 // use a separate function, since this is dimension specific
17133 this->policy->delete_children(*this,
17134 cell,
17135 line_cell_count,
17136 quad_cell_count);
17137 }
17138
17139 // re-compute number of lines and quads
17141 *this, levels.size(), number_cache);
17142}
17143
17144
17145
17146template <int dim, int spacedim>
17149{
17150 // copy a piece of code from prepare_coarsening_and_refinement that
17151 // ensures that the level difference at vertices is limited if so
17152 // desired. we need this code here since at least in 1d we don't
17153 // call the dimension-independent version of
17154 // prepare_coarsening_and_refinement function. in 2d and 3d, having
17155 // this hunk here makes our lives a bit easier as well as it takes
17156 // care of these cases earlier than it would otherwise happen.
17157 //
17158 // the main difference to the code in p_c_and_r is that here we
17159 // absolutely have to make sure that we get things right, i.e. that
17160 // in particular we set flags right if
17161 // limit_level_difference_at_vertices is set. to do so we iterate
17162 // until the flags don't change any more
17163 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17164
17165 bool continue_iterating = true;
17166
17167 do
17168 {
17169 if (smooth_grid & limit_level_difference_at_vertices)
17170 {
17171 Assert(!anisotropic_refinement,
17172 ExcMessage("In case of anisotropic refinement the "
17173 "limit_level_difference_at_vertices flag for "
17174 "mesh smoothing must not be set!"));
17175
17176 // store highest level one of the cells adjacent to a vertex
17177 // belongs to
17178 std::vector<int> vertex_level(vertices.size(), 0);
17179 for (const auto &cell : this->active_cell_iterators())
17180 {
17181 if (cell->refine_flag_set())
17182 for (const unsigned int vertex : cell->vertex_indices())
17183 vertex_level[cell->vertex_index(vertex)] =
17184 std::max(vertex_level[cell->vertex_index(vertex)],
17185 cell->level() + 1);
17186 else if (!cell->coarsen_flag_set())
17187 for (const unsigned int vertex : cell->vertex_indices())
17188 vertex_level[cell->vertex_index(vertex)] =
17189 std::max(vertex_level[cell->vertex_index(vertex)],
17190 cell->level());
17191 else
17192 {
17193 // if coarsen flag is set then tentatively assume
17194 // that the cell will be coarsened. this isn't
17195 // always true (the coarsen flag could be removed
17196 // again) and so we may make an error here. we try
17197 // to correct this by iterating over the entire
17198 // process until we are converged
17199 Assert(cell->coarsen_flag_set(), ExcInternalError());
17200 for (const unsigned int vertex : cell->vertex_indices())
17201 vertex_level[cell->vertex_index(vertex)] =
17202 std::max(vertex_level[cell->vertex_index(vertex)],
17203 cell->level() - 1);
17204 }
17205 }
17206
17207
17208 // loop over all cells in reverse order. do so because we
17209 // can then update the vertex levels on the adjacent
17210 // vertices and maybe already flag additional cells in this
17211 // loop
17212 //
17213 // note that not only may we have to add additional
17214 // refinement flags, but we will also have to remove
17215 // coarsening flags on cells adjacent to vertices that will
17216 // see refinement
17217 active_cell_iterator endc = end();
17218 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
17219 if (cell->refine_flag_set() == false)
17220 {
17221 for (const unsigned int vertex : cell->vertex_indices())
17222 if (vertex_level[cell->vertex_index(vertex)] >=
17223 cell->level() + 1)
17224 {
17225 // remove coarsen flag...
17226 cell->clear_coarsen_flag();
17227
17228 // ...and if necessary also refine the current
17229 // cell, at the same time updating the level
17230 // information about vertices
17231 if (vertex_level[cell->vertex_index(vertex)] >
17232 cell->level() + 1)
17233 {
17234 cell->set_refine_flag();
17235
17236 for (const unsigned int v : cell->vertex_indices())
17237 vertex_level[cell->vertex_index(v)] =
17238 std::max(vertex_level[cell->vertex_index(v)],
17239 cell->level() + 1);
17240 }
17241
17242 // continue and see whether we may, for example,
17243 // go into the inner 'if' above based on a
17244 // different vertex
17245 }
17246 }
17247 }
17248
17249 // loop over all cells and remove the coarsen flags for those cells that
17250 // have sister cells not marked for coarsening, or where some neighbors
17251 // are more refined.
17252
17253 // Coarsen flags of cells with no mother cell, i.e. on the
17254 // coarsest level, are deleted explicitly.
17255 for (const auto &acell : this->active_cell_iterators_on_level(0))
17256 acell->clear_coarsen_flag();
17257
17258 const cell_iterator endc = end();
17259 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17260 {
17261 // nothing to do if we are already on the finest level
17262 if (cell->is_active())
17263 continue;
17264
17265 const unsigned int n_children = cell->n_children();
17266 unsigned int flagged_children = 0;
17267 for (unsigned int child = 0; child < n_children; ++child)
17268 {
17269 const auto child_cell = cell->child(child);
17270 if (child_cell->is_active() && child_cell->coarsen_flag_set())
17271 {
17272 ++flagged_children;
17273 // clear flag since we don't need it anymore
17274 child_cell->clear_coarsen_flag();
17275 }
17276 }
17277
17278 // flag the children for coarsening again if all children were
17279 // flagged and if the policy allows it
17280 if (flagged_children == n_children &&
17281 this->policy->coarsening_allowed(cell))
17282 for (unsigned int c = 0; c < n_children; ++c)
17283 {
17284 Assert(cell->child(c)->refine_flag_set() == false,
17286
17287 cell->child(c)->set_coarsen_flag();
17288 }
17289 }
17290
17291 // now see if anything has changed in the last iteration of this
17292 // function
17293 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17294
17295 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
17296 previous_coarsen_flags.swap(current_coarsen_flags);
17297 }
17298 while (continue_iterating == true);
17299}
17300
17301#endif
17302
17303// TODO: merge the following 3 functions since they are the same
17304template <>
17305bool
17307{
17308 // save the flags to determine whether something was changed in the
17309 // course of this function
17310 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17311
17312 // do nothing in 1d, except setting the coarsening flags correctly
17313 fix_coarsen_flags();
17314
17315 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17316
17317 return (flags_before != flags_after);
17318}
17319
17320
17321
17322template <>
17323bool
17325{
17326 // save the flags to determine whether something was changed in the
17327 // course of this function
17328 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17329
17330 // do nothing in 1d, except setting the coarsening flags correctly
17331 fix_coarsen_flags();
17332
17333 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17334
17335 return (flags_before != flags_after);
17336}
17337
17338
17339
17340template <>
17341bool
17343{
17344 // save the flags to determine whether something was changed in the
17345 // course of this function
17346 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17347
17348 // do nothing in 1d, except setting the coarsening flags correctly
17349 fix_coarsen_flags();
17350
17351 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17352
17353 return (flags_before != flags_after);
17354}
17355
17356
17357
17358namespace
17359{
17360 // check if the given @param cell marked for coarsening would
17361 // produce an unrefined island. To break up long chains of these
17362 // cells we recursively check our neighbors in case we change this
17363 // cell. This reduces the number of outer iterations dramatically.
17364 template <int dim, int spacedim>
17365 void
17366 possibly_do_not_produce_unrefined_islands(
17368 {
17369 Assert(cell->has_children(), ExcInternalError());
17370
17371 unsigned int n_neighbors = 0;
17372 // count all neighbors that will be refined along the face of our
17373 // cell after the next step
17374 unsigned int count = 0;
17375 for (const unsigned int n : GeometryInfo<dim>::face_indices())
17376 {
17377 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
17378 cell->neighbor(n);
17379 if (neighbor.state() == IteratorState::valid)
17380 {
17381 ++n_neighbors;
17382 if (face_will_be_refined_by_neighbor(cell, n))
17383 ++count;
17384 }
17385 }
17386 // clear coarsen flags if either all existing neighbors will be
17387 // refined or all but one will be and the cell is in the interior
17388 // of the domain
17389 if (count == n_neighbors ||
17390 (count >= n_neighbors - 1 &&
17391 n_neighbors == GeometryInfo<dim>::faces_per_cell))
17392 {
17393 for (unsigned int c = 0; c < cell->n_children(); ++c)
17394 cell->child(c)->clear_coarsen_flag();
17395
17396 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17397 if (!cell->at_boundary(face) &&
17398 (!cell->neighbor(face)->is_active()) &&
17399 (cell_will_be_coarsened(cell->neighbor(face))))
17400 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
17401 cell->neighbor(face));
17402 }
17403 }
17404
17405
17406 // see if the current cell needs to be refined to avoid unrefined
17407 // islands.
17408 //
17409 // there are sometimes chains of cells that induce refinement of
17410 // each other. to avoid running the loop in
17411 // prepare_coarsening_and_refinement over and over again for each
17412 // one of them, at least for the isotropic refinement case we seek
17413 // to flag neighboring elements as well as necessary. this takes
17414 // care of (slightly pathological) cases like
17415 // deal.II/mesh_smoothing_03
17416 template <int dim, int spacedim>
17417 void
17418 possibly_refine_unrefined_island(
17420 const bool allow_anisotropic_smoothing)
17421 {
17422 Assert(cell->is_active(), ExcInternalError());
17423
17424 if constexpr (running_in_debug_mode())
17425 {
17426 // If this is not a parallel::distributed::Triangulation, then we really
17427 // should only get here if the cell is marked for refinement:
17428 if (dynamic_cast<
17430 &cell->get_triangulation()) == nullptr)
17431 Assert(cell->refine_flag_set() == false, ExcInternalError());
17432 else
17433 // But if this is a p::d::Triangulation, then we don't have that
17434 // much control and we can get here because mesh smoothing is
17435 // requested but can not be honored because p4est controls
17436 // what gets refined. In that case, we can at least provide
17437 // a better error message.
17438 Assert(
17439 cell->refine_flag_set() == false,
17440 ExcMessage(
17441 "The triangulation is trying to avoid unrefined islands "
17442 "during mesh refinement/coarsening, as you had requested "
17443 " by passing the appropriate 'smoothing flags' to the "
17444 "constructor of the triangulation. However, for objects "
17445 "of type parallel::distributed::Triangulation, control "
17446 "over which cells get refined rests with p4est, not the "
17447 "deal.II triangulation, and consequently it is not "
17448 "always possible to avoid unrefined islands in the mesh. "
17449 "Please remove the constructor argument to the triangulation "
17450 "object that requests mesh smoothing."));
17451 }
17452
17453 // now we provide two algorithms. the first one is the standard
17454 // one, coming from the time, where only isotropic refinement was
17455 // possible. it simply counts the neighbors that are or will be
17456 // refined and compares to the number of other ones. the second
17457 // one does this check independently for each direction: if all
17458 // neighbors in one direction (normally two, at the boundary only
17459 // one) are refined, the current cell is flagged to be refined in
17460 // an according direction.
17461
17462 if (allow_anisotropic_smoothing == false)
17463 {
17464 // use first algorithm
17465 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
17466 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17467 if (!cell->at_boundary(face))
17468 {
17469 if (face_will_be_refined_by_neighbor(cell, face))
17470 ++refined_neighbors;
17471 else
17472 ++unrefined_neighbors;
17473 }
17474
17475 if (unrefined_neighbors < refined_neighbors)
17476 {
17477 cell->clear_coarsen_flag();
17478 cell->set_refine_flag();
17479
17480 // ok, so now we have flagged this cell. if we know that
17481 // there were any unrefined neighbors at all, see if any
17482 // of those will have to be refined as well
17483 if (unrefined_neighbors > 0)
17484 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17485 if (!cell->at_boundary(face) &&
17486 (face_will_be_refined_by_neighbor(cell, face) == false) &&
17487 (cell->neighbor(face)->has_children() == false) &&
17488 (cell->neighbor(face)->refine_flag_set() == false))
17489 possibly_refine_unrefined_island<dim, spacedim>(
17490 cell->neighbor(face), allow_anisotropic_smoothing);
17491 }
17492 }
17493 else
17494 {
17495 // variable to store the cell refine case needed to fulfill
17496 // all smoothing requirements
17497 RefinementCase<dim> smoothing_cell_refinement_case =
17499
17500 // use second algorithm, do the check individually for each
17501 // direction
17502 for (unsigned int face_pair = 0;
17503 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
17504 ++face_pair)
17505 {
17506 // variable to store the cell refine case needed to refine
17507 // at the current face pair in the same way as the
17508 // neighbors do...
17509 RefinementCase<dim> directional_cell_refinement_case =
17511
17512 for (unsigned int face_index = 0; face_index < 2; ++face_index)
17513 {
17514 unsigned int face = 2 * face_pair + face_index;
17515 // variable to store the refine case (to come) of the
17516 // face under consideration
17517 RefinementCase<dim - 1> expected_face_ref_case =
17518 RefinementCase<dim - 1>::no_refinement;
17519
17520 if (cell->neighbor(face).state() == IteratorState::valid)
17521 face_will_be_refined_by_neighbor<dim, spacedim>(
17522 cell, face, expected_face_ref_case);
17523 // now extract which refine case would be necessary to
17524 // achieve the same face refinement. set the
17525 // intersection with other requirements for the same
17526 // direction.
17527
17528 // note: using the intersection is not an obvious
17529 // decision, we could also argue that it is more
17530 // natural to use the union. however, intersection is
17531 // the less aggressive tactic and favours a smaller
17532 // number of refined cells over an intensive
17533 // smoothing. this way we try not to lose too much of
17534 // the effort we put in anisotropic refinement
17535 // indicators due to overly aggressive smoothing...
17536 directional_cell_refinement_case =
17537 (directional_cell_refinement_case &
17540 expected_face_ref_case,
17541 face,
17542 cell->face_orientation(face),
17543 cell->face_flip(face),
17544 cell->face_rotation(face)));
17545 } // for both face indices
17546 // if both requirements sum up to something useful, add
17547 // this to the refine case for smoothing. note: if
17548 // directional_cell_refinement_case is isotropic still,
17549 // then something went wrong...
17550 Assert(directional_cell_refinement_case <
17553 smoothing_cell_refinement_case =
17554 smoothing_cell_refinement_case | directional_cell_refinement_case;
17555 } // for all face_pairs
17556 // no we collected contributions from all directions. combine
17557 // the new flags with the existing refine case, but only if
17558 // smoothing is required
17559 if (smoothing_cell_refinement_case)
17560 {
17561 cell->clear_coarsen_flag();
17562 cell->set_refine_flag(cell->refine_flag_set() |
17563 smoothing_cell_refinement_case);
17564 }
17565 }
17566 }
17567} // namespace
17568
17569#ifndef DOXYGEN
17570template <int dim, int spacedim>
17573{
17574 // save the flags to determine whether something was changed in the
17575 // course of this function
17576 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
17577 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
17578
17579 // save the flags at the outset of each loop. we do so in order to
17580 // find out whether something was changed in the present loop, in
17581 // which case we would have to re-run the loop. the other
17582 // possibility to find this out would be to set a flag
17583 // @p{something_changed} to true each time we change something.
17584 // however, sometimes one change in one of the parts of the loop is
17585 // undone by another one, so we might end up in an endless loop. we
17586 // could be tempted to break this loop at an arbitrary number of
17587 // runs, but that would not be a clean solution, since we would
17588 // either have to 1/ break the loop too early, in which case the
17589 // promise that a second call to this function immediately after the
17590 // first one does not change anything, would be broken, or 2/ we do
17591 // as many loops as there are levels. we know that information is
17592 // transported over one level in each run of the loop, so this is
17593 // enough. Unfortunately, each loop is rather expensive, so we chose
17594 // the way presented here
17595 auto coarsen_flags_before_loop = coarsen_flags_before;
17596 auto refine_flags_before_loop = refine_flags_before;
17597
17598 // now for what is done in each loop: we have to fulfill several
17599 // tasks at the same time, namely several mesh smoothing algorithms
17600 // and mesh regularization, by which we mean that the next mesh
17601 // fulfills several requirements such as no double refinement at
17602 // each face or line, etc.
17603 //
17604 // since doing these things at once seems almost impossible (in the
17605 // first year of this library, they were done in two functions, one
17606 // for refinement and one for coarsening, and most things within
17607 // these were done at once, so the code was rather impossible to
17608 // join into this, only, function), we do them one after each
17609 // other. the order in which we do them is such that the important
17610 // tasks, namely regularization, are done last and the least
17611 // important things are done the first. the following order is
17612 // chosen:
17613 //
17614 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
17615 // coarsen flags on level 1 to avoid level 0 cells being created
17616 // by coarsening. As coarsen flags will never be added, this can
17617 // be done once and for all before the actual loop starts.
17618 //
17619 // 1/ do not coarsen a cell if 'most of the neighbors' will be
17620 // refined after the step. This is to prevent occurrence of
17621 // unrefined islands.
17622 //
17623 // 2/ eliminate refined islands in the interior and at the
17624 // boundary. since they don't do much harm besides increasing the
17625 // number of degrees of freedom, doing this has a rather low
17626 // priority.
17627 //
17628 // 3/ limit the level difference of neighboring cells at each
17629 // vertex.
17630 //
17631 // 4/ eliminate unrefined islands. this has higher priority since
17632 // this diminishes the approximation properties not only of the
17633 // unrefined island, but also of the surrounding patch.
17634 //
17635 // 5/ ensure patch level 1. Then the triangulation consists of
17636 // patches, i.e. of cells that are refined once. It follows that
17637 // if at least one of the children of a cell is or will be
17638 // refined than all children need to be refined. This step only
17639 // sets refinement flags and does not set coarsening flags. If
17640 // the patch_level_1 flag is set, then
17641 // eliminate_unrefined_islands, eliminate_refined_inner_islands
17642 // and eliminate_refined_boundary_islands will be fulfilled
17643 // automatically and do not need to be enforced separately.
17644 //
17645 // 6/ take care of the requirement that no double refinement is done
17646 // at each face
17647 //
17648 // 7/ take care that no double refinement is done at each line in 3d
17649 // or higher dimensions.
17650 //
17651 // 8/ make sure that all children of each cell are either flagged
17652 // for coarsening or none of the children is
17653 //
17654 // For some of these steps, it is known that they interact. Namely,
17655 // it is not possible to guarantee that after step 6 another step 5
17656 // would have no effect; the same holds for the opposite order and
17657 // also when taking into account step 7. however, it is important to
17658 // guarantee that step five or six do not undo something that step 5
17659 // did, and step 7 not something of step 6, otherwise the
17660 // requirements will not be satisfied even if the loop
17661 // terminates. this is accomplished by the fact that steps 5 and 6
17662 // only *add* refinement flags and delete coarsening flags
17663 // (therefore, step 6 can't undo something that step 4 already did),
17664 // and step 7 only deletes coarsening flags, never adds some. step 7
17665 // needs also take care that it won't tag cells for refinement for
17666 // which some neighbors are more refined or will be refined.
17667
17668 //------------------------------------
17669 // STEP 0:
17670 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17671 // coarsen flags on level 1 to avoid level 0 cells being created
17672 // by coarsening.
17673 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17674 n_levels() >= 2)
17675 {
17676 for (const auto &cell : active_cell_iterators_on_level(1))
17677 cell->clear_coarsen_flag();
17678 }
17679
17680 bool mesh_changed_in_this_loop = false;
17681 do
17682 {
17683 //------------------------------------
17684 // STEP 1:
17685 // do not coarsen a cell if 'most of the neighbors' will be
17686 // refined after the step. This is to prevent the occurrence
17687 // of unrefined islands. If patch_level_1 is set, this will
17688 // be automatically fulfilled.
17689 if (smooth_grid & do_not_produce_unrefined_islands &&
17690 !(smooth_grid & patch_level_1))
17691 {
17692 for (const auto &cell : cell_iterators())
17693 {
17694 // only do something if this
17695 // cell will be coarsened
17696 if (!cell->is_active() && cell_will_be_coarsened(cell))
17697 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17698 }
17699 }
17700
17701
17702 //------------------------------------
17703 // STEP 2:
17704 // eliminate refined islands in the interior and at the
17705 // boundary. since they don't do much harm besides increasing
17706 // the number of degrees of freedom, doing this has a rather
17707 // low priority. If patch_level_1 is set, this will be
17708 // automatically fulfilled.
17709 //
17710 // there is one corner case to consider: if this is a
17711 // distributed triangulation, there may be refined islands on
17712 // the boundary of which we own only part (e.g. a single cell
17713 // in the corner of a domain). the rest of the island is
17714 // ghost cells and it *looks* like the area around it
17715 // (artificial cells) are coarser but this is only because
17716 // they may actually be equally fine on other
17717 // processors. it's hard to detect this case but we can do
17718 // the following: only set coarsen flags to remove this
17719 // refined island if all cells we want to set flags on are
17720 // locally owned
17721 if (smooth_grid & (eliminate_refined_inner_islands |
17722 eliminate_refined_boundary_islands) &&
17723 !(smooth_grid & patch_level_1))
17724 {
17725 for (const auto &cell : cell_iterators())
17726 if (!cell->is_active() ||
17727 (cell->is_active() && cell->refine_flag_set() &&
17728 cell->is_locally_owned()))
17729 {
17730 // check whether all children are active, i.e. not
17731 // refined themselves. This is a precondition that the
17732 // children may be coarsened away. If the cell is only
17733 // flagged for refinement, then all future children
17734 // will be active
17735 bool all_children_active = true;
17736 if (!cell->is_active())
17737 for (unsigned int c = 0; c < cell->n_children(); ++c)
17738 if (!cell->child(c)->is_active() ||
17739 cell->child(c)->is_ghost() ||
17740 cell->child(c)->is_artificial())
17741 {
17742 all_children_active = false;
17743 break;
17744 }
17745
17746 if (all_children_active)
17747 {
17748 // count number of refined and unrefined neighbors
17749 // of cell. neighbors on lower levels are counted
17750 // as unrefined since they can only get to the
17751 // same level as this cell by the next refinement
17752 // cycle
17753 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17754
17755 // Keep track if this cell is at a periodic
17756 // boundary or not. TODO: We do not currently run
17757 // the algorithm for inner islands at a periodic
17758 // boundary (remains to be implemented), but we
17759 // also don't want to consider them
17760 // boundary_island cells as this can interfere
17761 // with 2:1 refinement across periodic faces.
17762 // Instead: just ignore those cells for this
17763 // smoothing operation below.
17764 bool at_periodic_boundary = false;
17765
17766 for (const unsigned int n : cell->face_indices())
17767 {
17768 const cell_iterator neighbor = cell->neighbor(n);
17769 if (neighbor.state() == IteratorState::valid)
17770 {
17771 ++total_neighbors;
17772
17773 if (!face_will_be_refined_by_neighbor(cell, n))
17774 ++unrefined_neighbors;
17775 }
17776 else if (cell->has_periodic_neighbor(n))
17777 {
17778 ++total_neighbors;
17779 at_periodic_boundary = true;
17780 }
17781 }
17782
17783 // if all neighbors unrefined: mark this cell for
17784 // coarsening or don't refine if marked for that
17785 //
17786 // also do the distinction between the two
17787 // versions of the eliminate_refined_*_islands
17788 // flag
17789 //
17790 // the last check is whether there are any
17791 // neighbors at all. if not so, then we are (e.g.)
17792 // on the coarsest grid with one cell, for which,
17793 // of course, we do not remove the refine flag.
17794 if ((unrefined_neighbors == total_neighbors) &&
17795 ((!cell->at_boundary() &&
17796 (smooth_grid & eliminate_refined_inner_islands)) ||
17797 (cell->at_boundary() && !at_periodic_boundary &&
17798 (smooth_grid &
17799 eliminate_refined_boundary_islands))) &&
17800 (total_neighbors != 0))
17801 {
17802 if (!cell->is_active())
17803 for (unsigned int c = 0; c < cell->n_children(); ++c)
17804 {
17805 cell->child(c)->clear_refine_flag();
17806 cell->child(c)->set_coarsen_flag();
17807 }
17808 else
17809 cell->clear_refine_flag();
17810 }
17811 }
17812 }
17813 }
17814
17815 //------------------------------------
17816 // STEP 3:
17817 // limit the level difference of neighboring cells at each
17818 // vertex.
17819 //
17820 // in case of anisotropic refinement this does not make
17821 // sense. as soon as one cell is anisotropically refined, an
17822 // Assertion is thrown. therefore we can ignore this problem
17823 // later on
17824 if (smooth_grid & limit_level_difference_at_vertices)
17825 {
17826 Assert(!anisotropic_refinement,
17827 ExcMessage("In case of anisotropic refinement the "
17828 "limit_level_difference_at_vertices flag for "
17829 "mesh smoothing must not be set!"));
17830
17831 // store highest level one of the cells adjacent to a vertex
17832 // belongs to
17833 std::vector<int> vertex_level(vertices.size(), 0);
17834 for (const auto &cell : active_cell_iterators())
17835 {
17836 if (cell->refine_flag_set())
17837 for (const unsigned int vertex : cell->vertex_indices())
17838 vertex_level[cell->vertex_index(vertex)] =
17839 std::max(vertex_level[cell->vertex_index(vertex)],
17840 cell->level() + 1);
17841 else if (!cell->coarsen_flag_set())
17842 for (const unsigned int vertex : cell->vertex_indices())
17843 vertex_level[cell->vertex_index(vertex)] =
17844 std::max(vertex_level[cell->vertex_index(vertex)],
17845 cell->level());
17846 else
17847 {
17848 // if coarsen flag is set then tentatively assume
17849 // that the cell will be coarsened. this isn't
17850 // always true (the coarsen flag could be removed
17851 // again) and so we may make an error here
17852 Assert(cell->coarsen_flag_set(), ExcInternalError());
17853 for (const unsigned int vertex : cell->vertex_indices())
17854 vertex_level[cell->vertex_index(vertex)] =
17855 std::max(vertex_level[cell->vertex_index(vertex)],
17856 cell->level() - 1);
17857 }
17858 }
17859
17860
17861 // loop over all cells in reverse order. do so because we
17862 // can then update the vertex levels on the adjacent
17863 // vertices and maybe already flag additional cells in this
17864 // loop
17865 //
17866 // note that not only may we have to add additional
17867 // refinement flags, but we will also have to remove
17868 // coarsening flags on cells adjacent to vertices that will
17869 // see refinement
17870 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17871 if (cell->refine_flag_set() == false)
17872 {
17873 for (const unsigned int vertex : cell->vertex_indices())
17874 if (vertex_level[cell->vertex_index(vertex)] >=
17875 cell->level() + 1)
17876 {
17877 // remove coarsen flag...
17878 cell->clear_coarsen_flag();
17879
17880 // ...and if necessary also refine the current
17881 // cell, at the same time updating the level
17882 // information about vertices
17883 if (vertex_level[cell->vertex_index(vertex)] >
17884 cell->level() + 1)
17885 {
17886 cell->set_refine_flag();
17887
17888 for (const unsigned int v : cell->vertex_indices())
17889 vertex_level[cell->vertex_index(v)] =
17890 std::max(vertex_level[cell->vertex_index(v)],
17891 cell->level() + 1);
17892 }
17893
17894 // continue and see whether we may, for example,
17895 // go into the inner'if'
17896 // above based on a
17897 // different vertex
17898 }
17899 }
17900 }
17901
17902 //-----------------------------------
17903 // STEP 4:
17904 // eliminate unrefined islands. this has higher priority
17905 // since this diminishes the approximation properties not
17906 // only of the unrefined island, but also of the surrounding
17907 // patch.
17908 //
17909 // do the loop from finest to coarsest cells since we may
17910 // trigger a cascade by marking cells for refinement which
17911 // may trigger more cells further down below
17912 if (smooth_grid & eliminate_unrefined_islands)
17913 {
17914 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17915 // only do something if cell is not already flagged for
17916 // (isotropic) refinement
17917 if (cell->refine_flag_set() !=
17919 possibly_refine_unrefined_island<dim, spacedim>(
17920 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17921 }
17922
17923 //-------------------------------
17924 // STEP 5:
17925 // ensure patch level 1.
17926 //
17927 // Introduce some terminology:
17928 // - a cell that is refined
17929 // once is a patch of
17930 // level 1 simply called patch.
17931 // - a cell that is globally
17932 // refined twice is called
17933 // a patch of level 2.
17934 // - patch level n says that
17935 // the triangulation consists
17936 // of patches of level n.
17937 // This makes sense only
17938 // if the grid is already at
17939 // least n times globally
17940 // refined.
17941 //
17942 // E.g. from patch level 1 follows: if at least one of the
17943 // children of a cell is or will be refined than enforce all
17944 // children to be refined.
17945
17946 // This step 4 only sets refinement flags and does not set
17947 // coarsening flags.
17948 if (smooth_grid & patch_level_1)
17949 {
17950 // An important assumption (A) is that before calling this
17951 // function the grid was already of patch level 1.
17952
17953 // loop over all cells whose children are all active. (By
17954 // assumption (A) either all or none of the children are
17955 // active). If the refine flag of at least one of the
17956 // children is set then set_refine_flag and
17957 // clear_coarsen_flag of all children.
17958 for (const auto &cell : cell_iterators())
17959 if (!cell->is_active())
17960 {
17961 // ensure the invariant. we can then check whether all
17962 // of its children are further refined or not by
17963 // simply looking at the first child
17964 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17965 if (cell->child(0)->has_children() == true)
17966 continue;
17967
17968 // cell is found to be a patch. combine the refine
17969 // cases of all children
17970 RefinementCase<dim> combined_ref_case =
17972 for (unsigned int i = 0; i < cell->n_children(); ++i)
17973 combined_ref_case =
17974 combined_ref_case | cell->child(i)->refine_flag_set();
17975 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17976 for (unsigned int i = 0; i < cell->n_children(); ++i)
17977 {
17978 cell_iterator child = cell->child(i);
17979
17980 child->clear_coarsen_flag();
17981 child->set_refine_flag(combined_ref_case);
17982 }
17983 }
17984
17985 // The code above dealt with the case where we may get a
17986 // non-patch_level_1 mesh from refinement. Now also deal
17987 // with the case where we could get such a mesh by
17988 // coarsening. Coarsen the children (and remove the
17989 // grandchildren) only if all cell->grandchild(i)
17990 // ->coarsen_flag_set() are set.
17991 //
17992 // for a case where this is a bit tricky, take a look at the
17993 // mesh_smoothing_0[12] testcases
17994 for (const auto &cell : cell_iterators())
17995 {
17996 // check if this cell has active grandchildren. note
17997 // that we know that it is patch_level_1, i.e. if one of
17998 // its children is active then so are all, and it isn't
17999 // going to have any grandchildren at all:
18000 if (cell->is_active() || cell->child(0)->is_active())
18001 continue;
18002
18003 // cell is not active, and so are none of its
18004 // children. check the grandchildren. note that the
18005 // children are also patch_level_1, and so we only ever
18006 // need to check their first child
18007 const unsigned int n_children = cell->n_children();
18008 bool has_active_grandchildren = false;
18009
18010 for (unsigned int i = 0; i < n_children; ++i)
18011 if (cell->child(i)->child(0)->is_active())
18012 {
18013 has_active_grandchildren = true;
18014 break;
18015 }
18016
18017 if (has_active_grandchildren == false)
18018 continue;
18019
18020
18021 // ok, there are active grandchildren. see if either all
18022 // or none of them are flagged for coarsening
18023 unsigned int n_grandchildren = 0;
18024
18025 // count all coarsen flags of the grandchildren.
18026 unsigned int n_coarsen_flags = 0;
18027
18028 // cell is not a patch (of level 1) as it has a
18029 // grandchild. Is cell a patch of level 2?? Therefore:
18030 // find out whether all cell->child(i) are patches
18031 for (unsigned int c = 0; c < n_children; ++c)
18032 {
18033 // get at the child. by assumption (A), and the
18034 // check by which we got here, the child is not
18035 // active
18036 cell_iterator child = cell->child(c);
18037
18038 const unsigned int nn_children = child->n_children();
18039 n_grandchildren += nn_children;
18040
18041 // if child is found to be a patch of active cells
18042 // itself, then add up how many of its children are
18043 // supposed to be coarsened
18044 if (child->child(0)->is_active())
18045 for (unsigned int cc = 0; cc < nn_children; ++cc)
18046 if (child->child(cc)->coarsen_flag_set())
18047 ++n_coarsen_flags;
18048 }
18049
18050 // if not all grandchildren are supposed to be coarsened
18051 // (e.g. because some simply don't have the flag set, or
18052 // because they are not active and therefore cannot
18053 // carry the flag), then remove the coarsen flag from
18054 // all of the active grandchildren. note that there may
18055 // be coarsen flags on the grandgrandchildren -- we
18056 // don't clear them here, but we'll get to them in later
18057 // iterations if necessary
18058 //
18059 // there is nothing we have to do if no coarsen flags
18060 // have been set at all
18061 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
18062 for (unsigned int c = 0; c < n_children; ++c)
18063 {
18064 const cell_iterator child = cell->child(c);
18065 if (child->child(0)->is_active())
18066 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
18067 child->child(cc)->clear_coarsen_flag();
18068 }
18069 }
18070 }
18071
18072 //--------------------------------
18073 //
18074 // at the boundary we could end up with cells with negative
18075 // volume or at least with a part, that is negative, if the
18076 // cell is refined anisotropically. we have to check, whether
18077 // that can happen
18078 this->policy->prevent_distorted_boundary_cells(*this);
18079
18080 //-------------------------------
18081 // STEP 6:
18082 // take care of the requirement that no
18083 // double refinement is done at each face
18084 //
18085 // in case of anisotropic refinement it is only likely, but
18086 // not sure, that the cells, which are more refined along a
18087 // certain face common to two cells are on a higher
18088 // level. therefore we cannot be sure, that the requirement
18089 // of no double refinement is fulfilled after a single pass
18090 // of the following actions. We could just wait for the next
18091 // global loop. when this function terminates, the
18092 // requirement will be fulfilled. However, it might be faster
18093 // to insert an inner loop here.
18094 bool changed = true;
18095 while (changed)
18096 {
18097 changed = false;
18098 active_cell_iterator cell = last_active(), endc = end();
18099
18100 for (; cell != endc; --cell)
18101 if (cell->refine_flag_set())
18102 {
18103 // loop over neighbors of cell
18104 for (const auto i : cell->face_indices())
18105 {
18106 // only do something if the face is not at the
18107 // boundary and if the face will be refined with
18108 // the RefineCase currently flagged for
18109 const bool has_periodic_neighbor =
18110 cell->has_periodic_neighbor(i);
18111 const bool has_neighbor_or_periodic_neighbor =
18112 !cell->at_boundary(i) || has_periodic_neighbor;
18113 if (has_neighbor_or_periodic_neighbor &&
18115 cell->refine_flag_set(), i) !=
18117 {
18118 // 1) if the neighbor has children: nothing to
18119 // worry about. 2) if the neighbor is active
18120 // and a coarser one, ensure, that its
18121 // refine_flag is set 3) if the neighbor is
18122 // active and as refined along the face as our
18123 // current cell, make sure, that no
18124 // coarsen_flag is set. if we remove the
18125 // coarsen flag of our neighbor,
18126 // fix_coarsen_flags() makes sure, that the
18127 // mother cell will not be coarsened
18128 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
18129 {
18130 if ((!has_periodic_neighbor &&
18131 cell->neighbor_is_coarser(i)) ||
18132 (has_periodic_neighbor &&
18133 cell->periodic_neighbor_is_coarser(i)))
18134 {
18135 if (cell->neighbor_or_periodic_neighbor(i)
18136 ->coarsen_flag_set())
18137 cell->neighbor_or_periodic_neighbor(i)
18138 ->clear_coarsen_flag();
18139 // we'll set the refine flag for this
18140 // neighbor below. we note, that we
18141 // have changed something by setting
18142 // the changed flag to true. We do not
18143 // need to do so, if we just removed
18144 // the coarsen flag, as the changed
18145 // flag only indicates the need to
18146 // re-run the inner loop. however, we
18147 // only loop over cells flagged for
18148 // refinement here, so nothing to
18149 // worry about if we remove coarsen
18150 // flags
18151
18152 if (dim == 2)
18153 {
18154 if (smooth_grid &
18155 allow_anisotropic_smoothing)
18156 changed =
18157 has_periodic_neighbor ?
18158 cell->periodic_neighbor(i)
18159 ->flag_for_face_refinement(
18160 cell
18161 ->periodic_neighbor_of_coarser_periodic_neighbor(
18162 i)
18163 .first,
18165 cell->neighbor(i)
18166 ->flag_for_face_refinement(
18167 cell
18168 ->neighbor_of_coarser_neighbor(
18169 i)
18170 .first,
18172 else
18173 {
18174 if (!cell
18175 ->neighbor_or_periodic_neighbor(
18176 i)
18177 ->refine_flag_set())
18178 changed = true;
18179 cell->neighbor_or_periodic_neighbor(i)
18180 ->set_refine_flag();
18181 }
18182 }
18183 else // i.e. if (dim==3)
18184 {
18185 // ugly situations might arise here,
18186 // consider the following situation, which
18187 // shows neighboring cells at the common
18188 // face, where the upper right element is
18189 // coarser at the given face. Now the upper
18190 // child element of the lower left wants to
18191 // refine according to cut_z, such that
18192 // there is a 'horizontal' refinement of the
18193 // face marked with #####
18194 //
18195 // / /
18196 // / /
18197 // *---------------*
18198 // | |
18199 // | |
18200 // | |
18201 // | |
18202 // | |
18203 // | | /
18204 // | |/
18205 // *---------------*
18206 //
18207 //
18208 // *---------------*
18209 // /| /|
18210 // / | ##### / |
18211 // | |
18212 // *---------------*
18213 // /| /|
18214 // / | / |
18215 // | |
18216 // *---------------*
18217 // / /
18218 // / /
18219 //
18220 // this introduces too many hanging nodes
18221 // and the neighboring (coarser) cell (upper
18222 // right) has to be refined. If it is only
18223 // refined according to cut_z, then
18224 // everything is ok:
18225 //
18226 // / /
18227 // / /
18228 // *---------------*
18229 // | |
18230 // | | /
18231 // | |/
18232 // *---------------*
18233 // | |
18234 // | | /
18235 // | |/
18236 // *---------------*
18237 //
18238 //
18239 // *---------------*
18240 // /| /|
18241 // / *---------------*
18242 // /| /|
18243 // *---------------*
18244 // /| /|
18245 // / | / |
18246 // | |
18247 // *---------------*
18248 // / /
18249 // / /
18250 //
18251 // if however the cell wants to refine
18252 // itself in an other way, or if we disallow
18253 // anisotropic smoothing, then simply
18254 // refining the neighbor isotropically is
18255 // not going to work, since this introduces
18256 // a refinement of face ##### with both
18257 // cut_x and cut_y, which is not possible:
18258 //
18259 // / / /
18260 // / / /
18261 // *-------*-------*
18262 // | | |
18263 // | | | /
18264 // | | |/
18265 // *-------*-------*
18266 // | | |
18267 // | | | /
18268 // | | |/
18269 // *-------*-------*
18270 //
18271 //
18272 // *---------------*
18273 // /| /|
18274 // / *---------------*
18275 // /| /|
18276 // *---------------*
18277 // /| /|
18278 // / | / |
18279 // | |
18280 // *---------------*
18281 // / /
18282 // / /
18283 //
18284 // thus, in this case we also need to refine
18285 // our current cell in the new direction:
18286 //
18287 // / / /
18288 // / / /
18289 // *-------*-------*
18290 // | | |
18291 // | | | /
18292 // | | |/
18293 // *-------*-------*
18294 // | | |
18295 // | | | /
18296 // | | |/
18297 // *-------*-------*
18298 //
18299 //
18300 // *-------*-------*
18301 // /| /| /|
18302 // / *-------*-------*
18303 // /| /| /|
18304 // *-------*-------*
18305 // /| / /|
18306 // / | / |
18307 // | |
18308 // *---------------*
18309 // / /
18310 // / /
18311
18312 std::pair<unsigned int, unsigned int>
18313 nb_indices =
18314 has_periodic_neighbor ?
18315 cell
18316 ->periodic_neighbor_of_coarser_periodic_neighbor(
18317 i) :
18318 cell->neighbor_of_coarser_neighbor(i);
18319 unsigned int refined_along_x = 0,
18320 refined_along_y = 0,
18321 to_be_refined_along_x = 0,
18322 to_be_refined_along_y = 0;
18323
18324 const int this_face_index =
18325 cell->face_index(i);
18326
18327 // step 1: detect, along which axis the face
18328 // is currently refined
18329
18330 // first, we need an iterator pointing to
18331 // the parent face. This requires a slight
18332 // detour in case the neighbor is behind a
18333 // periodic face.
18334 const auto parent_face = [&]() {
18335 if (has_periodic_neighbor)
18336 {
18337 const auto neighbor =
18338 cell->periodic_neighbor(i);
18339 const auto parent_face_no =
18340 neighbor
18341 ->periodic_neighbor_of_periodic_neighbor(
18342 nb_indices.first);
18343 auto parent =
18344 neighbor->periodic_neighbor(
18345 nb_indices.first);
18346 return parent->face(parent_face_no);
18347 }
18348 else
18349 return cell->neighbor(i)->face(
18350 nb_indices.first);
18351 }();
18352
18353 if ((this_face_index ==
18354 parent_face->child_index(0)) ||
18355 (this_face_index ==
18356 parent_face->child_index(1)))
18357 {
18358 // this might be an
18359 // anisotropic child. get the
18360 // face refine case of the
18361 // neighbors face and count
18362 // refinements in x and y
18363 // direction.
18364 RefinementCase<dim - 1> frc =
18365 parent_face->refinement_case();
18367 ++refined_along_x;
18369 ++refined_along_y;
18370 }
18371 else
18372 // this has to be an isotropic
18373 // child
18374 {
18375 ++refined_along_x;
18376 ++refined_along_y;
18377 }
18378 // step 2: detect, along which axis the face
18379 // has to be refined given the current
18380 // refine flag
18381 RefinementCase<dim - 1> flagged_frc =
18383 cell->refine_flag_set(),
18384 i,
18385 cell->face_orientation(i),
18386 cell->face_flip(i),
18387 cell->face_rotation(i));
18388 if (flagged_frc &
18390 ++to_be_refined_along_x;
18391 if (flagged_frc &
18393 ++to_be_refined_along_y;
18394
18395 // step 3: set the refine flag of the
18396 // (coarser and active) neighbor.
18397 if ((smooth_grid &
18398 allow_anisotropic_smoothing) ||
18399 cell->neighbor_or_periodic_neighbor(i)
18400 ->refine_flag_set())
18401 {
18402 if (refined_along_x +
18403 to_be_refined_along_x >
18404 1)
18405 changed |=
18406 cell
18407 ->neighbor_or_periodic_neighbor(i)
18408 ->flag_for_face_refinement(
18409 nb_indices.first,
18410 RefinementCase<dim -
18411 1>::cut_axis(0));
18412 if (refined_along_y +
18413 to_be_refined_along_y >
18414 1)
18415 changed |=
18416 cell
18417 ->neighbor_or_periodic_neighbor(i)
18418 ->flag_for_face_refinement(
18419 nb_indices.first,
18420 RefinementCase<dim -
18421 1>::cut_axis(1));
18422 }
18423 else
18424 {
18425 if (cell
18426 ->neighbor_or_periodic_neighbor(i)
18427 ->refine_flag_set() !=
18430 changed = true;
18431 cell->neighbor_or_periodic_neighbor(i)
18432 ->set_refine_flag();
18433 }
18434
18435 // step 4: if necessary (see above) add to
18436 // the refine flag of the current cell
18437 cell_iterator nb =
18438 cell->neighbor_or_periodic_neighbor(i);
18439 RefinementCase<dim - 1> nb_frc =
18441 nb->refine_flag_set(),
18442 nb_indices.first,
18443 nb->face_orientation(nb_indices.first),
18444 nb->face_flip(nb_indices.first),
18445 nb->face_rotation(nb_indices.first));
18446 if ((nb_frc & RefinementCase<dim>::cut_x) &&
18447 !((refined_along_x != 0u) ||
18448 (to_be_refined_along_x != 0u)))
18449 changed |= cell->flag_for_face_refinement(
18450 i,
18452 if ((nb_frc & RefinementCase<dim>::cut_y) &&
18453 !((refined_along_y != 0u) ||
18454 (to_be_refined_along_y != 0u)))
18455 changed |= cell->flag_for_face_refinement(
18456 i,
18458 }
18459 } // if neighbor is coarser
18460 else // -> now the neighbor is not coarser
18461 {
18462 cell->neighbor_or_periodic_neighbor(i)
18463 ->clear_coarsen_flag();
18464 const unsigned int nb_nb =
18465 has_periodic_neighbor ?
18466 cell
18467 ->periodic_neighbor_of_periodic_neighbor(
18468 i) :
18469 cell->neighbor_of_neighbor(i);
18470 const cell_iterator neighbor =
18471 cell->neighbor_or_periodic_neighbor(i);
18472 RefinementCase<dim - 1> face_ref_case =
18474 neighbor->refine_flag_set(),
18475 nb_nb,
18476 neighbor->face_orientation(nb_nb),
18477 neighbor->face_flip(nb_nb),
18478 neighbor->face_rotation(nb_nb));
18479 RefinementCase<dim - 1> needed_face_ref_case =
18481 cell->refine_flag_set(),
18482 i,
18483 cell->face_orientation(i),
18484 cell->face_flip(i),
18485 cell->face_rotation(i));
18486 // if the neighbor wants to refine the
18487 // face with cut_x and we want cut_y
18488 // or vice versa, we have to refine
18489 // isotropically at the given face
18490 if ((face_ref_case ==
18492 needed_face_ref_case ==
18494 (face_ref_case ==
18496 needed_face_ref_case ==
18498 {
18499 changed = cell->flag_for_face_refinement(
18500 i, face_ref_case);
18501 neighbor->flag_for_face_refinement(
18502 nb_nb, needed_face_ref_case);
18503 }
18504 }
18505 }
18506 else //-> the neighbor is not active
18507 {
18508 RefinementCase<dim - 1>
18509 face_ref_case = cell->face(i)->refinement_case(),
18510 needed_face_ref_case =
18512 cell->refine_flag_set(),
18513 i,
18514 cell->face_orientation(i),
18515 cell->face_flip(i),
18516 cell->face_rotation(i));
18517 // if the face is refined with cut_x and
18518 // we want cut_y or vice versa, we have to
18519 // refine isotropically at the given face
18520 if ((face_ref_case == RefinementCase<dim>::cut_x &&
18521 needed_face_ref_case ==
18523 (face_ref_case == RefinementCase<dim>::cut_y &&
18524 needed_face_ref_case ==
18526 changed =
18527 cell->flag_for_face_refinement(i,
18528 face_ref_case);
18529 }
18530 }
18531 }
18532 }
18533 }
18534
18535 //------------------------------------
18536 // STEP 7:
18537 // take care that no double refinement is done at each line in 3d or
18538 // higher dimensions.
18539 this->policy->prepare_refinement_dim_dependent(*this);
18540
18541 //------------------------------------
18542 // STEP 8:
18543 // make sure that all children of each cell are either flagged for
18544 // coarsening or none of the children is
18545 fix_coarsen_flags();
18546
18547 //------------------------------------
18548 // Match refinement and coarsening decisions across periodic
18549 // faces if requested. In a distributed triangulation, only
18550 // modify locally owned cells; changes to ghost cells are made
18551 // by their owners after flags are exchanged.
18552 if (smooth_grid & match_refinement_across_periodic_boundaries)
18553 for (const auto &cell : active_cell_iterators())
18554 if (cell->is_locally_owned())
18555 for (const unsigned int face : cell->face_indices())
18556 if (cell->has_periodic_neighbor(face))
18557 {
18558 const auto periodic_neighbor = cell->periodic_neighbor(face);
18559
18560 const int periodic_neighbor_future_level =
18561 periodic_neighbor->level() +
18562 (periodic_neighbor->refine_flag_set() ? 1 : 0) -
18563 (periodic_neighbor->coarsen_flag_set() ? 1 : 0);
18564
18565 if (cell->level() < periodic_neighbor_future_level)
18566 {
18567 if (cell->coarsen_flag_set())
18568 cell->clear_coarsen_flag();
18569 else if (!cell->refine_flag_set())
18570 cell->set_refine_flag();
18571 }
18572 else if (cell->level() == periodic_neighbor_future_level &&
18573 cell->coarsen_flag_set())
18574 cell->clear_coarsen_flag();
18575 }
18576
18577 // get the refinement and coarsening flags
18578 auto coarsen_flags_after_loop =
18579 internal::extract_raw_coarsen_flags(levels);
18580 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
18581
18582 // find out whether something was changed in this loop
18583 mesh_changed_in_this_loop =
18584 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
18585 (refine_flags_before_loop != refine_flags_after_loop));
18586
18587 // set the flags for the next loop already
18588 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
18589 refine_flags_before_loop.swap(refine_flags_after_loop);
18590 }
18591 while (mesh_changed_in_this_loop);
18592
18593
18594 // find out whether something was really changed in this
18595 // function. Note that @p{..._flags_before_loop} represents the state
18596 // after the last loop, i.e., the present state
18597 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
18598 (refine_flags_before != refine_flags_before_loop));
18599}
18600
18601
18602
18603template <int dim, int spacedim>
18606 const unsigned int magic_number1,
18607 const std::vector<bool> &v,
18608 const unsigned int magic_number2,
18609 std::ostream &out)
18610{
18611 const unsigned int N = v.size();
18612 unsigned char *flags = new unsigned char[N / 8 + 1];
18613 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18614 flags[i] = 0;
18615
18616 for (unsigned int position = 0; position < N; ++position)
18617 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
18618
18619 AssertThrow(out.fail() == false, ExcIO());
18620
18621 // format:
18622 // 0. magic number
18623 // 1. number of flags
18624 // 2. the flags
18625 // 3. magic number
18626 out << magic_number1 << ' ' << N << std::endl;
18627 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18628 out << static_cast<unsigned int>(flags[i]) << ' ';
18629
18630 out << std::endl << magic_number2 << std::endl;
18631
18632 delete[] flags;
18633
18634 AssertThrow(out.fail() == false, ExcIO());
18635}
18636
18637
18638template <int dim, int spacedim>
18641 const unsigned int magic_number1,
18642 std::vector<bool> &v,
18643 const unsigned int magic_number2,
18644 std::istream &in)
18645{
18646 AssertThrow(in.fail() == false, ExcIO());
18647
18648 unsigned int magic_number;
18649 in >> magic_number;
18650 AssertThrow(magic_number == magic_number1, ExcGridReadError());
18651
18652 unsigned int N;
18653 in >> N;
18654 v.resize(N);
18655
18656 unsigned char *flags = new unsigned char[N / 8 + 1];
18657 unsigned short int tmp;
18658 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18659 {
18660 in >> tmp;
18661 flags[i] = tmp;
18662 }
18663
18664 for (unsigned int position = 0; position != N; ++position)
18665 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
18666
18667 in >> magic_number;
18668 AssertThrow(magic_number == magic_number2, ExcGridReadError());
18669
18670 delete[] flags;
18671
18672 AssertThrow(in.fail() == false, ExcIO());
18673}
18674
18675
18676
18677template <int dim, int spacedim>
18680{
18681 std::size_t mem = 0;
18682 mem += sizeof(MeshSmoothing);
18683 mem += MemoryConsumption::memory_consumption(reference_cells);
18684 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
18686 for (const auto &level : levels)
18689 mem += MemoryConsumption::memory_consumption(vertices_used);
18690 mem += sizeof(default_flat_manifold) + sizeof(*default_flat_manifold);
18691 mem += sizeof(manifolds);
18692 mem += sizeof(smooth_grid);
18693 mem += MemoryConsumption::memory_consumption(number_cache);
18694 mem += sizeof(faces);
18695 if (faces)
18697
18698 return mem;
18699}
18700
18701
18702
18703template <int dim, int spacedim>
18706 default;
18707
18708#endif
18709
18710// explicit instantiations
18711#include "grid/tria.inst"
18712
*  iterator end()
*  *  for(const auto &cell :triangulation.active_cell_iterators())
*  *  iterator begin()
*  *  iterator()=default
***mech_lbc_system increment_interpolation_handlers push_back(scale_z_handler)
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
CellStatus
Definition cell_status.h:29
@ cell_will_be_refined
@ children_will_be_coarsened
iterator begin() const
Definition array_view.h:755
iterator end() const
Definition array_view.h:764
std::size_t size() const
Definition array_view.h:737
types::coarse_cell_id get_coarse_cell_id() const
Definition cell_id.h:385
EnableObserverPointer & operator=(const EnableObserverPointer &)
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const =0
Definition point.h:111
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
unsigned int face_to_cell_lines(const unsigned int face, const unsigned int line, const types::geometric_orientation face_orientation) const
constexpr ReferenceCell< dim - 1 > face_reference_cell(const unsigned int face_index) const
unsigned int standard_to_real_face_vertex(const unsigned int vertex, const unsigned int face, const types::geometric_orientation face_orientation) const
unsigned int face_to_cell_vertices(const unsigned int face, const unsigned int vertex, const types::geometric_orientation face_orientation) const
unsigned int face_and_line_to_cell_vertices(const unsigned int face, const unsigned int line, const unsigned int vertex, const types::geometric_orientation face_orientation) const
constexpr void clear()
void join() const
IteratorState::IteratorStates state() const
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual ~Policy()=default
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual std::unique_ptr< Policy > clone()=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
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4253
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)
std::vector< bool > vertices_used
Definition tria.h:4629
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4648
active_quad_iterator begin_active_quad(const unsigned int level=0) const
bool get_anisotropic_refinement_flag() const
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
virtual types::coarse_cell_id n_global_coarse_cells() const
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4706
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()
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces< dim > > faces
Definition tria.h:4618
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
std::vector< Point< spacedim > > vertices
Definition tria.h:4624
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual types::subdomain_id locally_owned_subdomain() const
unsigned int n_raw_faces() const
unsigned int n_active_faces() const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
const bool check_for_distorted_cells
Definition tria.h:4655
raw_cell_iterator end_raw(const unsigned int level) const
line_iterator end_line() const
std::unique_ptr< std::map< unsigned int, types::boundary_id > > vertex_to_boundary_id_map_1d
Definition tria.h:4683
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
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)
std::vector< ReferenceCell< dim > > reference_cells
Definition tria.h:4160
void save_user_flags(std::ostream &out) const
void refine_global(const unsigned int times=1)
std::vector< std::unique_ptr< ::internal::TriangulationImplementation::TriaLevel< dim, spacedim > > > levels
Definition tria.h:4610
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)
const std::vector< Point< spacedim > > & get_vertices() const
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
unsigned int n_levels() 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
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:4254
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)
::internal::TriangulationImplementation::NumberCache< dim > number_cache
Definition tria.h:4666
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
std::vector< GridTools::PeriodicFacePair< cell_iterator > > periodic_face_pairs_level_0
Definition tria.h:4229
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
bool vertex_used(const unsigned int index) 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:4255
MeshSmoothing smooth_grid
Definition tria.h:4154
void save_refine_flags(std::ostream &out) const
Triangulation< dim, spacedim > & get_triangulation()
std::unique_ptr< Policy > policy
Definition tria.h:4220
void save_user_flags_quad(std::ostream &out) const
void compute_line_to_adjacent_cells_map()
Signals signals
Definition tria.h:2603
virtual ~Triangulation() override
internal::TriangulationImplementation::Strides< dim > strides
Definition tria.h:4165
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
const std::vector< ReferenceCell< dim > > & get_reference_cells() 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:458
std::unique_ptr< typename Triangulation< dim, spacedim >::Policy > clone() override
Definition tria.cc:2248
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2226
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2233
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:2209
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2203
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2240
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2219
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
constexpr iterator end() noexcept
constexpr size_type size() const noexcept
constexpr iterator begin() noexcept
constexpr LibraryBuildMode library_build_mode
Definition config.h:66
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
constexpr bool running_in_debug_mode()
Definition config.h:76
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:249
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
Point< 2 > second
Definition grid_out.cc:4640
Point< 2 > first
Definition grid_out.cc:4639
unsigned int level
Definition grid_out.cc:4642
AdjacentCell adjacent_cells[2]
unsigned int vertex_indices[2]
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)
#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)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcInvalidVertexIndex(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
#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:1771
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1762
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1782
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1747
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1723
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1738
void set_all_manifold_ids_on_boundary(const types::manifold_id number)
const Manifold< dim, spacedim > & get_manifold(const types::manifold_id number) const
virtual std::vector< types::manifold_id > get_manifold_ids() const
void reset_manifold(const types::manifold_id manifold_number)
void set_manifold(const types::manifold_id number, const Manifold< dim, spacedim > &manifold_object)
void reset_all_manifolds()
void set_all_manifold_ids(const types::manifold_id number)
Task< RT > new_task(const std::function< RT()> &function)
const unsigned int mn_tria_refine_flags_end
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
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell< dim > &reference_cell)
std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > vertex_to_cell_map(const Triangulation< dim, spacedim > &triangulation)
double diameter(const Triangulation< dim, spacedim > &tria)
@ valid
Iterator points to a valid object.
constexpr char N
double norm(const FEValuesBase< dim > &fe, const ArrayView< const std::vector< Tensor< 1, dim > > > &Du)
Definition divergence.h:469
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)
*  *  if(update_pressure &update_flags) *  compute_pressure(constitutive_request
*  *  *  *  std::vector< Number > ThermoPlasticMaterial< dim, ViscoplasticYieldLaw, Number >::get_state_parameters   const
constexpr ReferenceCell< 3 > Hexahedron
constexpr ReferenceCell< 2 > Quadrilateral
constexpr ReferenceCell< 1 > Line
constexpr ReferenceCell< 2 > Triangle
constexpr ReferenceCell< 3 > Tetrahedron
constexpr ReferenceCell< 3 > Pyramid
constexpr ReferenceCell< 3 > Wedge
constexpr ReferenceCell< 0 > Vertex
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:103
T max(const T &t, const MPI_Comm mpi_communicator)
std::vector< T > compute_set_union(const std::vector< T > &vec, const MPI_Comm comm)
unsigned int this_mpi_process(const MPI_Comm mpi_communicator)
Definition mpi.cc:118
std::size_t pack(const T &object, std::vector< char > &dest_buffer, const bool allow_compression=true)
Definition utilities.h:1352
constexpr T fixed_power(const T t)
Definition utilities.h:942
void load(Archive &ar, ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)
void save(Archive &ar, const ::std_cxx26::inplace_vector< T, N > &vec, const unsigned int)
void build_face_entities_templated(const std::vector< ReferenceCell< dim > > &cell_types, const ArrayOfArrays &cells_to_vertices, ArrayOfArrays &cells_to_faces, ArrayOfArrays &crs_0, std::vector< types::geometric_orientation > &orientations, const FU &second_key_function)
Definition tria.cc:2588
ArrayOfArrays determine_neighbors(const ArrayOfArrays &cells_to_faces)
Definition tria.cc:2513
Connectivity< dim > build_connectivity(const std::vector< ReferenceCell< dim > > &cell_types, const std::set< ReferenceCell< dim > > &all_reference_cells, const ArrayOfArrays &cells_to_vertices)
Definition tria.cc:2979
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:15834
void build_face_entities(const std::vector< ReferenceCell< dim > > &cell_types, const ArrayOfArrays &cells_to_vertices, ArrayOfArrays &cells_to_faces, ArrayOfArrays &crs_0, std::vector< types::geometric_orientation > &orientations, const FU &second_key_function)
Definition tria.cc:2804
void build_intersection(const std::vector< ReferenceCell< dim > > &cell_types, const ArrayOfArrays &cells_to_vertices, const ArrayOfArrays &cells_to_lines, const ArrayOfArrays &lines_to_vertices, const ArrayOfArrays &cells_to_quads, const ArrayOfArrays &quads_to_vertices, const std::vector< types::geometric_orientation > &ori_cq, ArrayOfArrays &quads_to_lines, std::vector< types::geometric_orientation > &ori_ql, std::vector< ReferenceCell< 2 > > &quad_t_id)
Definition tria.cc:2864
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:15827
void monitor_memory(const TriaLevel< dim, spacedim > &tria_level, const unsigned int true_dimension)
Definition tria.cc:2067
std::tuple< bool, bool, bool > split_face_orientation(const types::geometric_orientation combined_orientation)
constexpr std::uint8_t max_n_levels
Definition types.h:415
constexpr unsigned int invalid_unsigned_int
Definition types.h:228
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:319
constexpr types::manifold_id flat_manifold_id
Definition types.h:332
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:355
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:385
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:342
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:171
unsigned int boundary_id
Definition types.h:159
std::uint8_t geometric_orientation
Definition types.h:38
IsotropicRefinementChoice
std_cxx26::inplace_vector< unsigned int, ReferenceCells::max_n_vertices< structdim >()> vertices
Definition cell_data.h:84
static unsigned int child_cell_on_face(const RefinementCase< dim > &ref_case, const unsigned int face, const unsigned int subface, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement)
static RefinementCase< dim - 1 > face_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices()
static RefinementCase< dim > min_cell_refinement_case_for_face_refinement(const RefinementCase< dim - 1 > &face_refinement_case, const unsigned int face_no, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static unsigned int n_children(const RefinementCase< dim > &refinement_case)
static void alternating_form_at_vertices(const Point< spacedim >(&vertices)[vertices_per_cell], Tensor< spacedim - dim, spacedim >(&forms)[vertices_per_cell])
std::vector< CellData< 2 > > boundary_quads
Definition cell_data.h:247
bool check_consistency(const unsigned int dim) const
std::vector< CellData< 1 > > boundary_lines
Definition cell_data.h:231
std::vector< std::vector< CellData< dim > > > cell_infos
std::vector<::CellData< dim > > coarse_cells
std::vector< Point< spacedim > > coarse_cell_vertices
virtual ~DistortedCellList() noexcept override
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1817
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2449
boost::signals2::signal< void(const typename Triangulation< dim, spacedim >::cell_iterator &cell)> post_refinement_on_cell
Definition tria.h:2439
ArrayView< const unsigned int > operator[](const unsigned int i) const
Definition tria.cc:2321
ArrayOfArrays & operator=(ArrayOfArrays &&)=default
ArrayOfArrays(const std::vector< std::size_t > &offsets, const std::vector< unsigned int > &columns)
Definition tria.cc:2280
ArrayOfArrays & operator=(const ArrayOfArrays &)=default
ArrayOfArrays(std::vector< std::size_t > &&offsets, std::vector< unsigned int > &&columns)
Definition tria.cc:2290
const ArrayOfArrays & entity_to_entities(const unsigned int from, const unsigned int to) const
Definition tria.cc:2465
Connectivity(const std::vector< ReferenceCell< dim > > &cell_types, const std::set< ReferenceCell< dim > > &all_reference_cells)
Definition tria.cc:2374
std::vector< ReferenceCell< structdim > > & entity_types()
Definition tria.cc:2415
std::set< ReferenceCell< dim > > all_reference_cells_
Definition tria.cc:2486
std::vector< types::geometric_orientation > line_orientation
Definition tria.cc:2490
const std::vector< ReferenceCell< structdim > > & entity_types() const
Definition tria.cc:2431
std::vector< ReferenceCell< 2 > > quad_types
Definition tria.cc:2500
ArrayOfArrays & entity_to_entities(const unsigned int from, const unsigned int to)
Definition tria.cc:2446
const std::set< ReferenceCell< dim > > & all_reference_cells() const
Definition tria.cc:2386
std::vector< types::geometric_orientation > & entity_orientations(const unsigned int structdim)
Definition tria.cc:2392
const std::vector< types::geometric_orientation > & entity_orientations(const unsigned int structdim) const
Definition tria.cc:2403
std::vector< types::geometric_orientation > quad_orientation
Definition tria.cc:2495
std::vector< ReferenceCell< dim > > cell_types
Definition tria.cc:2484
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:12756
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:12836
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:12827
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:12852
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12761
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12844
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:12816
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:3331
static void prevent_distorted_boundary_cells(Triangulation< 1, spacedim > &)
Definition tria.cc:12364
static void process_subcelldata(const ArrayOfArrays &crs, TriaObjects &obj, const std::vector< CellData< structdim > > &boundary_objects_in, const std::vector< Point< spacedim > > &vertex_locations)
Definition tria.cc:3973
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3555
static void prepare_refinement_dim_dependent(const Triangulation< dim, spacedim > &)
Definition tria.cc:12451
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:4343
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3549
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:7983
static void compute_number_cache(const Triangulation< dim, spacedim > &triangulation, const unsigned int level_objects, internal::TriangulationImplementation::NumberCache< dim > &number_cache)
Definition tria.cc:3527
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:4971
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12371
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 1, spacedim > &, const bool)
Definition tria.cc:5343
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)
Definition tria.cc:12684
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:3436
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5354
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:4101
static void prepare_refinement_dim_dependent(Triangulation< 3, spacedim > &triangulation)
Definition tria.cc:12461
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:4205
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:3243
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5834
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:6390
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:3697
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:6069
Strides of various arrays in a Triangulation.
Definition tria.h:353
std::vector< std::vector< CellData< dim > > > cell_infos