deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
tria.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: 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 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
6449 --level_no)
6450 {
6451 std::size_t needed_cells = 0;
6452
6453 for (const auto &cell :
6454 triangulation.active_cell_iterators_on_level(level_no))
6455 if (cell->refine_flag_set())
6456 {
6457 // Only support isotropic refinement
6458 Assert(cell->refine_flag_set() ==
6461
6462 // get reference cell type of current cell
6463 const auto cell_reference_cell = cell->reference_cell();
6464
6465 // Now count up how many new cells, faces, edges, and
6466 // vertices we will need to allocate to do this refinement.
6467 needed_cells += cell_reference_cell.n_isotropic_children();
6468
6469 switch (cell_reference_cell)
6470 {
6472 needed_lines_single += 1;
6473 needed_faces_single += 8;
6474 break;
6475
6477 // TODO: Pyramid
6478 // - No vertices (all provided by face refinement)
6479 // - 5 faces for center pyramid
6480 // - 4 times 2 for the remaining tets
6481 needed_lines_single += 4;
6482 needed_faces_single += 13;
6483 break;
6484
6486 // - We won't need vertices (all required vertices
6487 // will be provided by the refined faces)
6488 // - 3 lines will be required to build up the
6489 // "refined" middle triangle
6490 // - 4 faces for the new refined middle triangle + 6
6491 // faces for the quads building the wedges in
6492 // z-direction. Rest will be provided via refinement
6493 // of faces. Store them all as singles. See also
6494 // https://link.springer.com/article/10.1007/BF01221213
6495 needed_lines_single += 3;
6496 needed_faces_single += 10;
6497 break;
6498
6500 // One vertex in the center of the parent
6501 ++needed_vertices;
6502 needed_lines_single += 6;
6503 needed_faces_single += 12;
6504 break;
6505
6506 default:
6508 }
6509
6510 // Also check whether we have to refine any of the faces and
6511 // edges that bound this cell. They may of course already be
6512 // refined, so we only *mark* them for refinement by setting
6513 // the user flags
6514
6515 // Faces
6516 for (const auto face : cell->face_indices())
6517 if (cell->face(face)->n_children() == 0)
6518 cell->face(face)->set_user_flag();
6519 else
6520 // Check that the child of the cell has enough children
6521 Assert(cell->face(face)->n_children() ==
6522 cell_reference_cell.face_reference_cell(face)
6523 .n_isotropic_children(),
6525
6526 // Edges
6527 for (const auto line : cell->line_indices())
6528 if (cell->line(line)->has_children() == false)
6529 cell->line(line)->set_user_flag();
6530 else
6531 Assert(cell->line(line)->n_children() == 2,
6533 }
6534
6535 auto &next_level = *triangulation.levels[level_no + 1];
6536 const auto used_cells = std::count(next_level.cells.used.begin(),
6537 next_level.cells.used.end(),
6538 true);
6539 if (used_cells + needed_cells > next_level.size())
6540 next_level.allocate_end(
6541 (used_cells + needed_cells) - next_level.size(),
6542 // We unconditionally store the orientation in 3d
6543 true,
6544 // TODO: we can get rid of this check (i.e., we don't need to
6545 // store this value for purely wedge meshes). This will be
6546 // simpler to do once we merge IsotropicRefinementChoice and
6547 // RefinementCase.
6548 !triangulation.all_reference_cells_are_hyper_cube());
6549
6550 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
6551 next_level.cells.allocate_end(needed_cells, 0);
6552 }
6553
6554 // now count the faces and lines which were flagged for
6555 // refinement
6557 triangulation.begin_quad();
6558 quad != triangulation.end_quad();
6559 ++quad)
6560 {
6561 if (quad->user_flag_set() == false)
6562 continue;
6563
6564 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6565 {
6566 needed_faces_pair += 4;
6567 needed_lines_pair += 4;
6568 needed_vertices += 1;
6569 }
6570 else if (quad->reference_cell() == ReferenceCells::Triangle)
6571 {
6572 needed_faces_pair += 4;
6573 needed_lines_single += 3;
6574 }
6575 else
6576 {
6578 }
6579 }
6580
6582 triangulation.begin_line();
6583 line != triangulation.end_line();
6584 ++line)
6585 {
6586 if (line->user_flag_set() == false)
6587 continue;
6588
6589 needed_lines_pair += 2;
6590 needed_vertices += 1;
6591 }
6592
6593 triangulation.faces->allocate_end(needed_faces_pair,
6594 needed_faces_single);
6595 triangulation.faces->lines.allocate_end(needed_lines_pair,
6596 needed_lines_single);
6597
6598 // add to needed vertices how many vertices are already in use
6599 needed_vertices += std::count(triangulation.vertices_used.begin(),
6600 triangulation.vertices_used.end(),
6601 true);
6602
6603 if (needed_vertices > triangulation.vertices.size())
6604 {
6605 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6606 triangulation.vertices_used.resize(needed_vertices, false);
6607 }
6608 } // STORAGE
6609
6610 //-----------------------------------------
6611 // Before we start with the actual refinement, we do some
6612 // sanity checks if in debug mode. especially, we try to catch
6613 // the notorious problem with lines being twice refined,
6614 // i.e. there are cells adjacent at one line ("around the
6615 // edge", but not at a face), with two cells differing by more
6616 // than one refinement level
6617 //
6618 // this check is very simple to implement here, since we have
6619 // all lines flagged if they shall be refined
6620 if constexpr (running_in_debug_mode())
6621 {
6622 for (const auto &cell : triangulation.active_cell_iterators())
6623 if (!cell->refine_flag_set())
6624 for (unsigned int line_n = 0; line_n < cell->n_lines();
6625 ++line_n)
6626 if (cell->line(line_n)->has_children())
6627 for (unsigned int c = 0; c < 2; ++c)
6628 Assert(cell->line(line_n)->child(c)->user_flag_set() ==
6629 false,
6631 }
6632
6633 unsigned int current_vertex = 0;
6634
6635 // helper function - find the next available vertex number and mark it
6636 // as used.
6637 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6638 std::vector<bool> &vertices_used) {
6639 unsigned int next_vertex = current_vertex;
6640 while (next_vertex < vertices_used.size() &&
6641 vertices_used[next_vertex] == true)
6642 ++next_vertex;
6643 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6644 vertices_used[next_vertex] = true;
6645
6646 return next_vertex;
6647 };
6648
6649
6650 { // LINES
6652 line = triangulation.begin_active_line(),
6653 endl = triangulation.end_line();
6654 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6655
6656 for (; line != endl; ++line)
6657 {
6658 if (line->user_flag_set() == false)
6659 continue;
6660
6661 next_unused_line =
6662 triangulation.faces->lines.template next_free_pair_object<1>(
6663 triangulation);
6664 Assert(next_unused_line.state() == IteratorState::valid,
6666
6667 // now we found two consecutive unused lines, such
6668 // that the children of a line will be consecutive.
6669 // then set the child pointer of the present line
6670 line->set_children(0, next_unused_line->index());
6671
6672 const std::array<raw_line_iterator, 2> children{
6673 {next_unused_line, ++next_unused_line}};
6674
6675 AssertIsNotUsed(children[0]);
6676 AssertIsNotUsed(children[1]);
6677
6678 current_vertex =
6679 get_next_unused_vertex(current_vertex,
6680 triangulation.vertices_used);
6681 triangulation.vertices[current_vertex] = line->center(true);
6682
6683 children[0]->set_bounding_object_indices(
6684 {line->vertex_index(0), current_vertex});
6685 children[1]->set_bounding_object_indices(
6686 {current_vertex, line->vertex_index(1)});
6687
6688 const auto manifold_id = line->manifold_id();
6689 const auto boundary_id = line->boundary_id();
6690 for (const auto &child : children)
6691 {
6692 child->set_used_flag();
6693 child->clear_children();
6694 child->clear_user_data();
6695 child->clear_user_flag();
6696 child->set_boundary_id_internal(boundary_id);
6697 child->set_manifold_id(manifold_id);
6698 }
6699
6700 line->clear_user_flag();
6701 }
6702 }
6703
6704 { // FACES
6705 // (i.e., quads or triangles, or both)
6707 face = triangulation.begin_face(),
6708 endf = triangulation.end_face();
6709
6710 for (; face != endf; ++face)
6711 {
6712 if (face->user_flag_set() == false)
6713 continue;
6714
6715 const auto reference_face_type = face->reference_cell();
6716 const auto n_lines_per_face = reference_face_type.n_lines();
6717
6718 // 1) Create new lines (property is set later).
6719 // Maximum of 4 new lines (4 quadrilateral, 3 triangle).
6720 std::array<raw_line_iterator, 4> new_lines;
6721 switch (reference_face_type)
6722 {
6724 for (unsigned int l = 0; l < 3; ++l)
6725 new_lines[l] =
6726 triangulation.faces->lines
6727 .template next_free_single_object<1>(triangulation);
6728 break;
6729
6731 for (unsigned int l = 0; l < 2; ++l)
6732 {
6733 auto next_unused_line =
6734 triangulation.faces->lines
6735 .template next_free_pair_object<1>(triangulation);
6736 new_lines[2 * l] = next_unused_line;
6737 new_lines[2 * l + 1] = ++next_unused_line;
6738 }
6739 break;
6740
6741 default:
6743 }
6744
6745 if constexpr (running_in_debug_mode())
6746 {
6747 for (const unsigned int line : face->line_indices())
6748 AssertIsNotUsed(new_lines[line]);
6749 }
6750
6751 // 2) Create new face (properties are set below).
6752 // Both triangles and quads are divided in four. (For historical
6753 // reasons, we only have `raw_quad_iterator`, not
6754 // `raw_face_iterator`, but the former also works if a face is
6755 // actually a triangle.)
6756 std::array<raw_quad_iterator, 4> new_faces;
6757 for (unsigned int f = 0; f < 2; ++f)
6758 {
6759 auto next_unused_quad =
6760 triangulation.faces->quads
6761 .template next_free_pair_object<2>(triangulation);
6762
6763 new_faces[2 * f] = next_unused_quad;
6764 new_faces[2 * f + 1] = ++next_unused_quad;
6765
6766 face->set_children(2 * f, new_faces[2 * f]->index());
6767 }
6768 // Tell the original face that is has been isotropically refined.
6769 face->set_refinement_case(RefinementCase<2>::cut_xy);
6770
6771 if constexpr (running_in_debug_mode())
6772 {
6773 for (const auto &quad : new_faces)
6774 AssertIsNotUsed(quad);
6775 }
6776
6777 // 3) Create an ordered list of vertices.
6778 // The order is determined by the physical position of the
6779 // vertices within the face reference cell, enabling easy
6780 // identification/lookup by the vertex's index in this list.
6781 // Additionally the center vertex required for quadrilaterals is
6782 // created.
6783
6784 // Maximum of 9 vertices per refined face (9 for Quadrilateral, 6
6785 // for Triangle)
6786 std::array<unsigned int, 9> vertex_indices = {};
6787 unsigned int k = 0;
6788 for (const auto i : face->vertex_indices())
6789 vertex_indices[k++] = face->vertex_index(i);
6790
6791 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6792 vertex_indices[k++] = face->line(l)->child(0)->vertex_index(1);
6793
6794 if (reference_face_type == ReferenceCells::Quadrilateral)
6795 {
6796 current_vertex =
6797 get_next_unused_vertex(current_vertex,
6798 triangulation.vertices_used);
6799 vertex_indices[k++] = current_vertex;
6800
6801 triangulation.vertices[current_vertex] =
6802 face->center(true, true);
6803 }
6804
6805 // 4) Set new lines on these faces and their properties.
6806 // 'magic numbers' in `line_vertices_X` are indices in the list
6807 // created in step 3).
6808 std::array<raw_line_iterator, 12> lines;
6809 unsigned int n_lines = 0;
6810 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6811 for (unsigned int c = 0; c < 2; ++c)
6812 lines[n_lines++] = face->line(l)->child(
6813 child_line_index(c, face->line_orientation(l)));
6814
6815 for (unsigned int l = 0; l < n_lines_per_face; ++l)
6816 lines[n_lines++] = new_lines[l];
6817
6818 std::array<int, 12> line_indices;
6819 for (unsigned int i = 0; i < n_lines; ++i)
6820 line_indices[i] = lines[i]->index();
6821
6822 // 2---7---3 .-6-.-7-. .---.---.
6823 // | | | 1 9 3 | 2 | 3 |
6824 // 4---8---5 .-10.11-. .---.---.
6825 // | | | 0 8 2 | 0 | 1 |
6826 // 0---6---1 .-4-.-5-. .---.---.
6827 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_quad{
6828 {{{0, 4}},
6829 {{4, 2}},
6830 {{1, 5}},
6831 {{5, 3}},
6832 {{0, 6}},
6833 {{6, 1}},
6834 {{2, 7}},
6835 {{7, 3}},
6836 {{6, 8}},
6837 {{8, 7}},
6838 {{4, 8}},
6839 {{8, 5}}}};
6840
6841 constexpr ::ndarray<unsigned int, 4, 4> quad_lines_quad{
6842 {{{0, 8, 4, 10}},
6843 {{8, 2, 5, 11}},
6844 {{1, 9, 10, 6}},
6845 {{9, 3, 11, 7}}}};
6846
6847 // 2 * * .
6848 // |\ |\ |\ .
6849 // v ^ 4 3 | \ .
6850 // | \ | \ | 2 \ .
6851 // 5--<--4 *--7--* *-----* .
6852 // |\ |\ |\ |\ |\ 3 |\ .
6853 // v ^ ^ ^ 5 8 6 2 | \ | \ .
6854 // | \| \ | \| \ | 0 \| 1 \ .
6855 // 0-->--3-->--1 *--0--*--1--* *-----*-----* .
6856 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_tri{
6857 {{{0, 3}},
6858 {{3, 1}},
6859 {{1, 4}},
6860 {{4, 2}},
6861 {{2, 5}},
6862 {{5, 0}},
6863 {{3, 4}},
6864 {{4, 5}},
6865 {{3, 5}},
6866 {{X, X}},
6867 {{X, X}},
6868 {{X, X}}}};
6869
6870 constexpr ::ndarray<unsigned int, 4, 4> tri_lines_tri{
6871 {{{0, 8, 5, X}},
6872 {{1, 2, 6, X}},
6873 {{7, 3, 4, X}},
6874 {{6, 7, 8, X}}}};
6875
6876 // The defined lines in `line_vertices_tri` do not satisfy the
6877 // expected orientations of all the children's reference cells.
6878 // This table specifies the expected line orientations (i.e.
6879 // vertex order) necessary for `set_line_orientation(...)`.
6880 constexpr ::ndarray<unsigned int, 4, 4, 2>
6881 tri_line_vertices_tri{
6882 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6883 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6884 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6885 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6886
6887 // Select lookup table according to reference cell of parent.
6888 const auto &line_vertices =
6889 (reference_face_type == ReferenceCells::Quadrilateral) ?
6890 line_vertices_quad :
6891 line_vertices_tri;
6892 const auto &face_lines =
6893 (reference_face_type == ReferenceCells::Quadrilateral) ?
6894 quad_lines_quad :
6895 tri_lines_tri;
6896
6897 // The first 2*face->n_lines() lines are already created by
6898 // refining the original lines on the face. Therefore, only the
6899 // subsequent face->n_lines() lines need to be processed now.
6900 for (unsigned int i = 0, j = 2 * n_lines_per_face;
6901 i < n_lines_per_face;
6902 ++i, ++j)
6903 {
6904 auto &new_line = new_lines[i];
6905 new_line->set_bounding_object_indices(
6906 {vertex_indices[line_vertices[j][0]],
6907 vertex_indices[line_vertices[j][1]]});
6908 new_line->set_used_flag();
6909 new_line->clear_user_flag();
6910 new_line->clear_user_data();
6911 new_line->clear_children();
6912 new_line->set_boundary_id_internal(face->boundary_id());
6913 new_line->set_manifold_id(face->manifold_id());
6914 }
6915
6916 // 5) Set properties of faces
6917 for (unsigned int i = 0; i < new_faces.size(); ++i)
6918 {
6919 // 5.a) Create faces
6920 auto &new_face = new_faces[i];
6921
6922 // We assume here that all children have the same type as the
6923 // parent face.
6924 triangulation.faces->set_quad_type(new_face->index(),
6925 reference_face_type);
6926
6927 switch (reference_face_type)
6928 {
6930 new_face->set_bounding_object_indices(
6931 {line_indices[face_lines[i][0]],
6932 line_indices[face_lines[i][1]],
6933 line_indices[face_lines[i][2]]});
6934 break;
6935
6937 new_face->set_bounding_object_indices(
6938 {line_indices[face_lines[i][0]],
6939 line_indices[face_lines[i][1]],
6940 line_indices[face_lines[i][2]],
6941 line_indices[face_lines[i][3]]});
6942 break;
6943
6944 default:
6946 }
6947
6948 new_face->set_used_flag();
6949 new_face->clear_user_flag();
6950 new_face->clear_user_data();
6951 new_face->clear_children();
6952 new_face->set_boundary_id_internal(face->boundary_id());
6953 new_face->set_manifold_id(face->manifold_id());
6954
6955 [[maybe_unused]] std::set<unsigned int> s;
6956
6957 // 5.b.I) Fix orientation of lines of face
6958 // For triangles an expensive algorithm is used,
6959 // quadrilaterals are treated a few lines below by a cheaper
6960 // algorithm
6961 if (reference_face_type == ReferenceCells::Triangle)
6962 {
6963 for (const auto f : new_face->line_indices())
6964 {
6965 const std::array<unsigned int, 2> vertices_0 = {
6966 {lines[face_lines[i][f]]->vertex_index(0),
6967 lines[face_lines[i][f]]->vertex_index(1)}};
6968
6969 const std::array<unsigned int, 2> vertices_1 = {
6970 {vertex_indices[tri_line_vertices_tri[i][f][0]],
6971 vertex_indices[tri_line_vertices_tri[i][f][1]]}};
6972
6973 const auto orientation =
6974 ReferenceCells::Line.get_combined_orientation(
6975 make_array_view(vertices_0),
6976 make_array_view(vertices_1));
6977
6978 if constexpr (library_build_mode ==
6980 {
6981 for (const auto i : vertices_0)
6982 s.insert(i);
6983 for (const auto i : vertices_1)
6984 s.insert(i);
6985 }
6986
6987 new_face->set_line_orientation(f, orientation);
6988 }
6989 if constexpr (library_build_mode ==
6991 {
6992 AssertDimension(s.size(), 3);
6993 }
6994 }
6995 }
6996
6997 // 5.b.II) Fix orientation of lines of faces for quadrilaterals
6998 // with cheap algorithm.
6999 if (reference_face_type == ReferenceCells::Quadrilateral)
7000 {
7001 constexpr ::ndarray<unsigned int, 4, 2>
7002 quad_child_line_vertices{{{{0, 2}}, //
7003 {{1, 3}}, //
7004 {{0, 1}}, //
7005 {{2, 3}}}};
7006
7007 for (unsigned int i = 0; i < 4; ++i)
7008 for (unsigned int j = 0; j < 2; ++j)
7009 new_faces[quad_child_line_vertices[i][j]]
7010 ->set_line_orientation(i, face->line_orientation(i));
7011 }
7012
7013 face->clear_user_flag();
7014 }
7015 } // FACES
7016
7017 // Cells
7019 cells_with_distorted_children;
7020
7022 triangulation.begin_active(0);
7023 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
7024 ++level)
7025 {
7027 next_unused_cell = triangulation.begin_raw(level + 1);
7028 Assert(cell == triangulation.end() ||
7029 cell->level() >= static_cast<int>(level),
7031
7032 // Iterate over all active cells in the current level
7033 for (; cell != triangulation.end() &&
7034 cell->level() == static_cast<int>(level);
7035 ++cell)
7036 {
7037 if (cell->refine_flag_set() ==
7039 continue;
7040
7041 // Copy the requested refinement case to the cell's actual
7042 // refinement flag, informing the cell how it has been refined.
7043 const RefinementCase<dim> ref_case = cell->refine_flag_set();
7044 cell->clear_refine_flag();
7045 cell->set_refinement_case(ref_case);
7046
7047 const auto cell_reference_cell = cell->reference_cell();
7048
7049 unsigned int n_new_lines = 0;
7050 unsigned int n_new_faces = 0;
7051 const unsigned int n_new_cells =
7052 cell_reference_cell.n_isotropic_children();
7053
7054 // Must match the information used close the beginning of this
7055 // function.
7056 switch (cell_reference_cell)
7057 {
7059 n_new_lines = 1;
7060 n_new_faces = 8;
7061 break;
7062
7064 n_new_lines = 4;
7065 n_new_faces = 13;
7066 break;
7067
7069 n_new_lines = 3;
7070 n_new_faces = 10;
7071 break;
7072
7074 n_new_lines = 6;
7075 n_new_faces = 12;
7076 break;
7077
7078 default:
7080 }
7081
7082 // the following numbers should be the max numbers of the above.
7083 // They are used for sizing of arrays.
7084 constexpr unsigned int max_n_new_lines = 6;
7085 constexpr unsigned int max_n_new_faces = 13;
7086 constexpr unsigned int max_n_new_children = 10;
7087 constexpr unsigned int max_relevant_vertices = 27;
7088 constexpr unsigned int max_relevant_lines = 30;
7089 constexpr unsigned int max_face_indices = 36;
7090
7091 std::array<raw_line_iterator, max_n_new_lines> new_lines;
7092 for (unsigned int i = 0; i < n_new_lines; ++i)
7093 {
7094 new_lines[i] =
7095 triangulation.faces->lines
7096 .template next_free_single_object<1>(triangulation);
7097
7098 AssertIsNotUsed(new_lines[i]);
7099 new_lines[i]->set_used_flag();
7100 new_lines[i]->clear_user_flag();
7101 new_lines[i]->clear_user_data();
7102 new_lines[i]->clear_children();
7103 new_lines[i]->set_boundary_id_internal(
7105 new_lines[i]->set_manifold_id(cell->manifold_id());
7106 }
7107
7108 std::array<raw_quad_iterator, max_n_new_faces> new_faces;
7109 for (unsigned int i = 0; i < n_new_faces; ++i)
7110 {
7111 new_faces[i] =
7112 triangulation.faces->quads
7113 .template next_free_single_object<2>(triangulation);
7114
7115 auto &new_face = new_faces[i];
7116
7117 AssertIsNotUsed(new_face);
7118 new_face->set_used_flag();
7119 new_face->clear_user_flag();
7120 new_face->clear_user_data();
7121 new_face->clear_children();
7122 new_face->set_boundary_id_internal(
7124 new_face->set_manifold_id(cell->manifold_id());
7125
7126 // At this point the face doesn't have its ReferenceCell
7127 // set, so rely on lower-level functionality to reset
7128 // per-line data
7129 for (unsigned int j = 0;
7130 j < triangulation.faces->lines_per_quad;
7131 ++j)
7132 new_face->set_line_orientation(
7134 }
7135
7136
7137 { // CREATE_CELLS
7138 // Build a list of all relevant vertices required for
7139 // - The creation of additional faces not generated by the
7140 // refinement of the parent faces.
7141 // - The definition of the child cells.
7142 //
7143 // Number of meaningful entries in this list is
7144 // 10 Tetrahedron 18 Wedge
7145 // 14 Pyramid 27 Hexahedron
7146 // In case the maximum changes, edit `max_relevant_vertices` a
7147 // few lines above (or in case it was moved to ReferenceCell,
7148 // update it there).
7149 //
7150 // The following algorithm is used to get the vertices.
7151 // 1. Get vertices of the parent as provided.
7152 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
7153 //
7154 // 2. Get the center vertices of the (refined) bounding lines
7155 // of the parent's faces (quad and tet (i.e. all) faces)
7156 //
7157 // .---3---. .
7158 // | | /|
7159 // 0 1 or 2 1
7160 // | | / |
7161 // .---2---. .-0-. n: vertices retrieved
7162 //
7163 // 3. Get the remaining new vertices that were created in the
7164 // center of the parent's bounding faces during refinement
7165 // (quad faces)
7166 //
7167 // .-------.
7168 // | |
7169 // .---O |
7170 // | | |
7171 // .---.---. O: vertex retrieved
7172 //
7173 // 4. Get (or, better yet, create) the newly required
7174 // vertices. (i.e. the new vertex in the middle of a hex,
7175 // only relevant for hexes)
7176 //
7177 // .-------.
7178 // /| |
7179 // . | / |
7180 // | - -O |
7181 // | .--:----.
7182 // |/ : /
7183 // .-------.
7184
7185 std::array<unsigned int, max_relevant_vertices>
7186 vertex_indices = {};
7187
7188 { // GET_VERTICES
7189 // continuous counter variable
7190 unsigned int k = 0;
7191
7192 // avoid a compiler warning by fixing max number of
7193 // iterations to 8.
7194 const unsigned int n_vertices =
7195 std::min(cell->n_vertices(), 8u);
7196
7197 // Step 1 Get vertices of the parent
7198 for (unsigned int i = 0; i < n_vertices; ++i)
7199 vertex_indices[k++] = cell->vertex_index(i);
7200
7201 // Step 2 (relevant for all faces)
7202
7203 // Avoid a compiler warning by fixing the max number of loop
7204 // iterations to 12 (max number of new lines)
7205 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
7206
7207 const std::array<unsigned int, 12> line_indices =
7208 TriaAccessorImplementation::Implementation::
7209 get_line_indices_of_cell(*cell);
7210
7211 for (unsigned int l = 0; l < n_lines; ++l)
7212 {
7213 raw_line_iterator line(&triangulation,
7214 0,
7215 line_indices[l]);
7216 vertex_indices[k++] = line->child(0)->vertex_index(1);
7217 }
7218
7219 // Step 3 (depends on the reference cell type of face, only
7220 // quads affected)
7221 for (auto quad_face_index :
7222 cell_reference_cell.face_indices_by_type(
7224 {
7225 vertex_indices[k++] = cell->face(quad_face_index)
7226 ->child(0)
7227 ->vertex_index(3);
7228 }
7229
7230 // Step 4 Create the center vertex for hex cells
7231 if (cell_reference_cell == ReferenceCells::Hexahedron)
7232 {
7233 // Set single new vertex in the center
7234 current_vertex =
7235 get_next_unused_vertex(current_vertex,
7236 triangulation.vertices_used);
7237 vertex_indices[k++] = current_vertex;
7238
7239 triangulation.vertices[current_vertex] =
7240 cell->center(true, true);
7241 }
7242 } // GET_VERTICES
7243
7244
7245 unsigned int chosen_line_tetrahedron = 0;
7246
7247 // set up new lines
7248 switch (cell_reference_cell)
7249 {
7251 {
7252 // in the tetrahedron case, we have the three
7253 // possibilities (6,8), (5,7), (4,9) -> pick the
7254 // shortest line to guarantee the best possible aspect
7255 // ratios
7256 constexpr ::ndarray<unsigned int, 3, 2>
7257 new_line_vertices = {{{{6, 8}}, //
7258 {{5, 7}}, //
7259 {{4, 9}}}};
7260
7261 // choose line to cut either by refinement case or by
7262 // shortest distance between edge midpoints
7263 std::uint8_t refinement_choice =
7264 cell->refine_choice();
7265 if (refinement_choice ==
7266 static_cast<char>(IsotropicRefinementChoice::
7268 {
7269 const auto &vertices =
7270 triangulation.get_vertices();
7271 double min_distance =
7272 std::numeric_limits<double>::infinity();
7273 for (unsigned int i = 0;
7274 i < new_line_vertices.size();
7275 ++i)
7276 {
7277 const double current_distance =
7278 vertices[vertex_indices
7279 [new_line_vertices[i][0]]]
7280 .distance(
7281 vertices[vertex_indices
7282 [new_line_vertices[i][1]]]);
7283 if (current_distance < min_distance)
7284 {
7285 chosen_line_tetrahedron = i;
7286 min_distance = current_distance;
7287 }
7288 }
7289 }
7290 else if (refinement_choice ==
7291 static_cast<char>(
7293 chosen_line_tetrahedron = 0;
7294 else if (refinement_choice ==
7295 static_cast<char>(
7297 chosen_line_tetrahedron = 1;
7298 else if (refinement_choice ==
7299 static_cast<char>(
7301 chosen_line_tetrahedron = 2;
7302 else
7304
7305 cell->set_refinement_case(
7306 RefinementCase<dim>(chosen_line_tetrahedron + 1));
7307
7308 new_lines[0]->set_bounding_object_indices(
7310 [new_line_vertices[chosen_line_tetrahedron][0]],
7311 vertex_indices[new_line_vertices
7312 [chosen_line_tetrahedron][1]]});
7313 }
7314 break;
7315
7317 {
7318 // Directions so that middle bottom pyramids all have
7319 // lines with default orientation. Order as children
7320 // of refined bottom quad.
7321 static constexpr ::ndarray<unsigned int, 4, 2>
7322 new_line_vertices = {{{{13, 9}}, //
7323 {{13, 10}}, //
7324 {{13, 11}}, //
7325 {{13, 12}}}};
7326
7327 for (unsigned int i = 0; i < n_new_lines; ++i)
7328 new_lines[i]->set_bounding_object_indices(
7329 {vertex_indices[new_line_vertices[i][0]],
7330 vertex_indices[new_line_vertices[i][1]]});
7331 }
7332 break;
7333
7335 {
7336 // Directions so that middle tri looks like a 'normal'
7337 // refined tri (refined quads define outer lines)
7338 constexpr ::ndarray<unsigned int, 3, 2>
7339 new_line_vertices = {{{{15, 16}}, //
7340 {{16, 17}}, //
7341 {{15, 17}}}};
7342
7343 for (unsigned int i = 0; i < n_new_lines; ++i)
7344 new_lines[i]->set_bounding_object_indices(
7345 {vertex_indices[new_line_vertices[i][0]],
7346 vertex_indices[new_line_vertices[i][1]]});
7347 }
7348 break;
7349
7351 {
7352 constexpr ::ndarray<unsigned int, 6, 2>
7353 new_line_vertices = {{{{22, 26}},
7354 {{26, 23}},
7355 {{20, 26}},
7356 {{26, 21}},
7357 {{24, 26}},
7358 {{26, 25}}}};
7359 for (unsigned int i = 0; i < n_new_lines; ++i)
7360 new_lines[i]->set_bounding_object_indices(
7361 {vertex_indices[new_line_vertices[i][0]],
7362 vertex_indices[new_line_vertices[i][1]]});
7363 }
7364 break;
7365
7366 default:
7368 }
7369
7370 // Get the corrected orientation of the child indices of
7371 // `child` for a refined face, given the `face_ref_cell_type`
7372 // and the `face_orientation` as stored in the cell it bounds.
7373 auto standard_to_real_quad_child_index =
7374 [](const unsigned int child,
7375 const types::geometric_orientation face_orientation,
7376 const ReferenceCell<dim - 1> face_ref_cell_type) {
7377 // The parent vertex indices correlate nicely with the
7378 // child indices of a tri and quad, as shown in the
7379 // drawing for 2D face refinement (see the curly brackets
7380 // tagged {} // FACES). We can thus apply the existing
7381 // algorithm for orientation correction of vertex indices
7382 // and reinterpret the output. The only problem is child 3
7383 // in triangles. However it is always in the center so no
7384 // correction is necessary at all.
7385 switch (face_ref_cell_type)
7386 {
7388 // A complicated way to query the private attribute
7389 // `ReferenceCell::triangle_vertex_permutations[face_orientation][vertex]`
7390 if (child != 3)
7393 0,
7394 face_orientation);
7395 else
7396 return 3u;
7397
7399 // `ReferenceCell::quadrilateral_vertex_permutations[face_orientation][vertex]`.
7402 0,
7403 face_orientation);
7404 default:
7406 }
7407 };
7408
7409 // set up new faces
7410 {
7411 // Similar to `vertex_indices` above the `relevant_lines`
7412 // are filled in multiple steps. The order is once again
7413 // determined by the reference cell and the refinement
7414 // algorithms used by the faces. (For Tetrahedron
7415 // `chosen_line_tetrahedron` is also relevant).
7416 // 1. Get the lines from the faces that are Quadrilaterals.
7417 //
7418 // .- -.- -.
7419 // : 1 :
7420 // .-2-.-3-.
7421 // : 0 :
7422 // .- - - -. n: extracted lines
7423 //
7424 // 2. Get the lines from the faces that are Triangles.
7425 //
7426 // | \ .
7427 // *--1--* .
7428 // |\ |\ .
7429 // | 2 0 \ .
7430 // | \| .
7431 // *-----*--- .
7432 //
7433 // 3. Newly created lines (see above)
7434 // 4. Load indices for the extracted lines
7435 //
7436 // Number of meaningful entries in this list is
7437 // 13 Tetrahedron 21 Wedge
7438 // 20 Pyramid 30 Hexahedron
7439 // In case the maximum changes, edit `max_relevant_lines` a
7440 // few lines above (or in case it was moved to
7441 // ReferenceCell, update it there).
7442
7443 std::array<raw_line_iterator, max_relevant_lines>
7444 relevant_lines;
7445 std::array<int, max_relevant_lines> relevant_line_indices;
7446 unsigned int relevant_lines_counter = 0;
7447 // 1. Get relevant lines from quads
7448 for (auto f : cell_reference_cell.face_indices_by_type(
7450 {
7451 // To retrieve the newly created lines within a quad, it
7452 // is sufficient to query child 0 and 3 (or 1 and 2), as
7453 // they border all relevant lines. Specifically, we are
7454 // interested in lines 1 and 3 of child 0, and lines
7455 // 0 and 2 of child 3. This is currently implemented in
7456 // `quad_relevant_children_and_lines` below (where the
7457 // first index is the child and the second is the
7458 // child's line index). A more readable implementation
7459 // is provided right below. However, it cannot be
7460 // (nicely) used to mimic the existing table's behavior.
7461 // Modifications to this behavior would result in
7462 // extensive rewriting of tables in `ReferenceCell`.
7463 //
7464 // constexpr std::
7465 // pair<unsigned int, std::array<unsigned int, 2>>
7466 // quad_relevant_children_and_lines = {{0, {1, 3}},
7467 // {3, {0, 2}}};
7468 constexpr ::ndarray<unsigned int, 4, 2>
7469 quad_relevant_children_and_lines = {{{{0, 1}}, //
7470 {{3, 0}}, //
7471 {{0, 3}}, //
7472 {{3, 2}}}};
7473 for (unsigned int l = 0; l < 4;
7474 ++l, ++relevant_lines_counter)
7475 {
7476 // Use previously defined helper function to find
7477 // children in an orientation-corrected way.
7478 const unsigned int relevant_child =
7479 standard_to_real_quad_child_index(
7480 quad_relevant_children_and_lines[l][0],
7481 cell->combined_face_orientation(f),
7483
7484 // Get the orientation corrected line index of the
7485 // child while using the fact that quad children
7486 // share their physical orientation with the parent.
7487 const unsigned int relevant_child_line =
7489 .standard_to_real_face_line(
7490 quad_relevant_children_and_lines[l][1],
7491 // face irrelevant -> function doesn't use it.
7492 0,
7493 cell->combined_face_orientation(f));
7494
7495
7496 // extract and store line
7497 relevant_lines[relevant_lines_counter] =
7498 cell->face(f)
7499 ->isotropic_child(relevant_child)
7500 ->line(relevant_child_line);
7501 }
7502 }
7503
7504 // 2. Get lines from tris
7505 for (auto f : cell_reference_cell.face_indices_by_type(
7507 {
7508 for (unsigned int l = 0; l < 3;
7509 ++l, ++relevant_lines_counter)
7510 {
7511 // Permutations of reference cell indices against
7512 // real world indices given the real world
7513 // orientation of the face.
7514 const std::array<std::array<unsigned int, 3>, 6>
7515 // Extract newly created lines surrounding the
7516 // center child (child 3) of the refined
7517 // triangular faces in a predictable manner (i.e.,
7518 // the lines always appear at the same location
7519 // within the to be refined 3d reference cell),
7520 // the orientation of the face must be considered.
7521 // This orientation correction is implemented via
7522 // the table below relating the lines of the
7523 // oriented face to their counterparts on the
7524 // reference cell face.
7525 tri_line_perm = {{{{0, 1, 2}}, // 0
7526 {{1, 0, 2}},
7527 {{2, 0, 1}}, // 2
7528 {{0, 2, 1}},
7529 {{1, 2, 0}}, // 4
7530 {{2, 1, 0}}}};
7531
7532 const auto combined_orientation =
7533 cell->combined_face_orientation(f);
7534 relevant_lines[relevant_lines_counter] =
7535 cell->face(f)
7536 ->child(3 /*center triangle*/)
7537 ->line(tri_line_perm[combined_orientation][l]);
7538 }
7539 }
7540
7541 // 3. Fill end of `relevant_lines` with `new_lines`.
7542 for (unsigned int i = 0; i < n_new_lines;
7543 ++i, ++relevant_lines_counter)
7544 relevant_lines[relevant_lines_counter] = new_lines[i];
7545
7546
7547 // 4. Extract and store indices of the relevant lines.
7548 for (unsigned int i = 0; i < relevant_lines_counter; ++i)
7549 relevant_line_indices[i] = relevant_lines[i]->index();
7550
7551
7552 // New faces (internal to the parent) are required for the
7553 // creation of children. The lines bounding these new faces
7554 // are stored in `relevant_lines`. The exact assignment of
7555 // these lines is then determined using the lookup table
7556 // retrieved below, by providing the appropriate indices
7557 // into `relevant_lines`.
7558 const auto &new_face_lines =
7559 cell_reference_cell.new_isotropic_child_face_lines(
7560 chosen_line_tetrahedron);
7561
7562 // The created lines might not be oriented according to the
7563 // expectation of the face's reference cell. Consequently,
7564 // an additional lookup table is necessary to define the
7565 // correct line connectivity desired by the reference cell.
7566 // This is very similar to the refinement of triangles in 2d
7567 // where the same problem occurred.
7568 const auto &new_face_lines_vert =
7569 cell_reference_cell
7570 .new_isotropic_child_face_line_vertices(
7571 chosen_line_tetrahedron);
7572
7573 // When fixing the orientation of lines for hexes the
7574 // calculated orientation of one line can be used for some
7575 // other lines as well. This connection is described in this
7576 // table.
7577 constexpr ::ndarray<unsigned int, 4, 2>
7578 representative_lines{{{{0, 2}}, //
7579 {{2, 0}}, //
7580 {{3, 3}}, //
7581 {{1, 1}}}};
7582
7583 for (unsigned int q = 0; q < n_new_faces; ++q)
7584 {
7585 auto &new_face = new_faces[q];
7586
7587 if (new_face_lines[q][3] == X)
7588 {
7589 // Set the face type implicitly, based on whether
7590 // the fourth line is `X`.
7591 triangulation.faces->set_quad_type(
7592 new_face->index(), ReferenceCells::Triangle);
7593
7594 new_face->set_bounding_object_indices(
7595 {relevant_line_indices[new_face_lines[q][0]],
7596 relevant_line_indices[new_face_lines[q][1]],
7597 relevant_line_indices[new_face_lines[q][2]]});
7598 }
7599 else
7600 {
7601 triangulation.faces->set_quad_type(
7602 new_face->index(), ReferenceCells::Quadrilateral);
7603
7604 new_face->set_bounding_object_indices(
7605 {relevant_line_indices[new_face_lines[q][0]],
7606 relevant_line_indices[new_face_lines[q][1]],
7607 relevant_line_indices[new_face_lines[q][2]],
7608 relevant_line_indices[new_face_lines[q][3]]});
7609 }
7610
7611 // On hexes, we must only determine a single line
7612 // according to the representative_lines array above
7613 // (this saves expensive operations), for tets we do
7614 // all lines manually
7615 const unsigned int n_compute_lines =
7616 cell_reference_cell == ReferenceCells::Hexahedron ?
7617 1 :
7618 new_face->n_lines();
7619 for (unsigned int line = 0; line < n_compute_lines;
7620 ++line)
7621 {
7622 const unsigned int l =
7623 (cell_reference_cell ==
7625 representative_lines[q % 4][0] :
7626 line;
7627
7628 const std::array<unsigned int, 2> vertices_0 = {
7629 {relevant_lines[new_face_lines[q][l]]
7630 ->vertex_index(0),
7631 relevant_lines[new_face_lines[q][l]]
7632 ->vertex_index(1)}};
7633
7634 const std::array<unsigned int, 2> vertices_1 = {
7635 {vertex_indices[new_face_lines_vert[q][l][0]],
7636 vertex_indices[new_face_lines_vert[q][l][1]]}};
7637
7638 const auto orientation =
7639 ReferenceCells::Line.get_combined_orientation(
7640 make_array_view(vertices_0),
7641 make_array_view(vertices_1));
7642
7643 new_face->set_line_orientation(l, orientation);
7644
7645 // on a hex, inject the status of the current line
7646 // also to the line on the other quad along the
7647 // same direction
7648 if (cell_reference_cell ==
7650 new_faces[representative_lines[q % 4][1] + q -
7651 (q % 4)]
7652 ->set_line_orientation(l, orientation);
7653 }
7654 }
7655 }
7656
7657 // set up new cell
7658 {
7659 // Similar to the steps before we now use an algorithm to
7660 // extract all the faces.
7661 // 1. Add newly created faces to the beginning.
7662 // 2. Get children of refined quad faces.
7663 // for numbering see {} // FACE.
7664 // 3. Get children of refined tri faces.
7665 // for numbering see {} // FACE.
7666 //
7667 // Number of meaningful entries in this list is
7668 // 24 Tetrahedron 30 Wedge
7669 // 33 Pyramid 36 Hexahedron
7670 // In case the maximum changes, edit `max_face_indices` a
7671 // few lines above (or in case it was moved to
7672 // ReferenceCell, update it there).
7673
7674 std::array<int, max_face_indices> face_indices;
7675
7676 unsigned int face_indices_counter = 0;
7677
7678 // 1. Get new face's ids.
7679 for (; face_indices_counter < n_new_faces;
7680 ++face_indices_counter)
7681 face_indices[face_indices_counter] =
7682 new_faces[face_indices_counter]->index();
7683
7684 // 2. Now the faces of the parent's refined quads.
7685 for (auto f_q : cell_reference_cell.face_indices_by_type(
7687 {
7688 for (unsigned int c = 0; c < 4;
7689 ++c, ++face_indices_counter)
7690 {
7691 const auto combined_orientation =
7692 cell->combined_face_orientation(f_q);
7693
7694 // Correct once again for orientation.
7695 face_indices[face_indices_counter] =
7696 cell->face(f_q)->isotropic_child_index(
7697 standard_to_real_quad_child_index(
7698 c,
7699 combined_orientation,
7701 }
7702 }
7703
7704 // 3. Now the faces of the parent's refined tris
7705 for (auto f_t : cell_reference_cell.face_indices_by_type(
7707 {
7708 for (unsigned int c = 0; c < 4;
7709 ++c, ++face_indices_counter)
7710 {
7711 const auto combined_orientation =
7712 cell->combined_face_orientation(f_t);
7713
7714 // Correct once again for orientation.
7715 face_indices[face_indices_counter] =
7716 cell->face(f_t)->child_index(
7717 standard_to_real_quad_child_index(
7718 c,
7719 combined_orientation,
7721 }
7722 }
7723
7724 // Similar to the faces described above, we need to identify
7725 // which faces (specified by their indices in
7726 // `face_indices`) bound the new cells. This information is
7727 // stored in the ReferenceCell and retrieved here.
7728 const auto cell_faces =
7729 cell_reference_cell.new_isotropic_child_cell_faces(
7730 chosen_line_tetrahedron);
7731
7732 // We also need to account for potential orientation
7733 // mismatches between the face and the cell's ReferenceCell.
7734 // (See the discussion above in new face creation for more
7735 // details.)
7736 const auto new_cells_vertices =
7737 cell_reference_cell.new_isotropic_child_cell_vertices(
7738 chosen_line_tetrahedron);
7739
7740 // 1. Preserve data that can only be extracted from active
7741 // cells.
7742 // Parent becomes inactive after setting the first child!
7743 const ::types::subdomain_id cell_subdomain_id =
7744 cell->subdomain_id();
7745
7746 // Create the new cells
7747 std::array<
7749 max_n_new_children>
7750 new_cells;
7751 for (unsigned int c = 0; c < n_new_cells; ++c)
7752 {
7753 // Since we search for pairs of hexes (next_free_hex
7754 // returns a pair) we need to search only every other
7755 // time.
7756 if (c % 2 == 0)
7757 next_unused_cell =
7758 triangulation.levels[level + 1]
7759 ->cells.next_free_hex(triangulation, level + 1);
7760 else
7761 ++next_unused_cell;
7762
7763 new_cells[c] = next_unused_cell;
7764
7765 auto &new_cell = new_cells[c];
7766
7767 AssertIsNotUsed(new_cell);
7768
7769 // 2. Copy parent data to child.
7770 new_cell->set_used_flag();
7771 new_cell->clear_user_flag();
7772 new_cell->clear_user_data();
7773 new_cell->clear_children();
7774 new_cell->set_material_id(cell->material_id());
7775 new_cell->set_manifold_id(cell->manifold_id());
7776 new_cell->set_subdomain_id(cell_subdomain_id);
7777
7778 // 3. Setup child parent relation (can only happen after
7779 // call to `set_used_flag()`)
7780 if (c % 2 == 0)
7781 {
7782 new_cell->set_parent(cell->index());
7783 cell->set_children(c, new_cell->index());
7784 }
7785
7786 // 4.a Determine the cell reference cell using the
7787 // number of vertices it has according to
7788 // `new_cells_vertices`.
7789 const ReferenceCell child_reference_cell =
7790 (new_cells_vertices[c][4] == X) ? ReferenceCells::Tetrahedron : // Tet
7791 (new_cells_vertices[c][5] == X) ? ReferenceCells::Pyramid : // Pyramid
7792 (new_cells_vertices[c][6] == X) ? ReferenceCells::Wedge : // Wedge
7794
7795 // 4.b Set the reference cell
7796 triangulation.levels[new_cell->level()]
7797 ->reference_cell[new_cell->index()] =
7798 child_reference_cell;
7799
7800 // 5. Set the bounding faces of the new cells
7801 // This seems to be the only option since
7802 // set_bounding_object_indices() takes an
7803 // std::initializer_list as argument
7804 switch (child_reference_cell)
7805 {
7807 new_cell->set_bounding_object_indices(
7808 {face_indices[cell_faces[c][0]],
7809 face_indices[cell_faces[c][1]],
7810 face_indices[cell_faces[c][2]],
7811 face_indices[cell_faces[c][3]]});
7812 break;
7813
7814 // Pyramids and Wedges share same number of faces
7817 new_cell->set_bounding_object_indices(
7818 {face_indices[cell_faces[c][0]],
7819 face_indices[cell_faces[c][1]],
7820 face_indices[cell_faces[c][2]],
7821 face_indices[cell_faces[c][3]],
7822 face_indices[cell_faces[c][4]]});
7823 break;
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 face_indices[cell_faces[c][4]],
7832 face_indices[cell_faces[c][5]]});
7833 break;
7834
7835 default:
7837 }
7838
7839 // 6. Fix orientation of faces.
7840 // For all reference cells except for Hexes, we need to
7841 // go through the faces and figure the orientation out
7842 // the hard way
7843
7844 // Set the orientation flag to its default state for
7845 // all faces initially. later on go the other way
7846 // round and reset faces that are at the boundary of
7847 // the mother cube.
7848 // TODO: This might only be necessary for Hexes. For
7849 // all other cells the orientation is calculated for
7850 // all faces one by one. (Only a guess though).
7851 for (const auto f : new_cell->face_indices())
7852 new_cell->set_combined_face_orientation(
7854
7855 if (child_reference_cell != ReferenceCells::Hexahedron)
7856 {
7857 for (const auto f : new_cell->face_indices())
7858 {
7859 const auto &face = new_cell->face(f);
7860
7861 // load correct vertices of cell
7862 auto new_cell_vertices = new_cells_vertices[c];
7863
7864 // Load correct indices of vertices of face `f`
7865 std::array<unsigned int, 4> vertices_0,
7866 vertices_1;
7867 vertices_0.fill(numbers::invalid_unsigned_int);
7868 vertices_1.fill(numbers::invalid_unsigned_int);
7869
7870 for (unsigned int face_vertex_no :
7871 face->vertex_indices())
7872 {
7873 // Calculate index for vertex
7874 // `face_vertex_no` of face `f` as an index
7875 // in the cells reference cells indices.
7876 const auto cell_vertex_no =
7877 child_reference_cell
7879 f,
7880 face_vertex_no,
7881 numbers::
7882 default_geometric_orientation);
7883
7884 // Get according index from
7885 // `vertex_indices`. Use `cell_vertex_no` as
7886 // the index in the table describing which
7887 // vertices belong to which cell and then
7888 // get that index. Use `cell_vertex_no` to
7889 // look up the specific vertex (more
7890 // precisely the index in `vertex_indices`)
7891 // within the cell's connectivity table
7892 // `new_cell_vertices` and retrieve the
7893 // corresponding vertex (index) from
7894 // `vertex_indices`.
7895 vertices_0[face_vertex_no] = vertex_indices
7896 [new_cell_vertices[cell_vertex_no]];
7897 }
7898
7899 // max 4 vertices (if face is quad)
7900 for (const auto i : face->vertex_indices())
7901 vertices_1[i] = face->vertex_index(i);
7902
7903 // Calculate combined orientation as permutation
7904 // of desired face vertex indices an actual
7905 // vertex indices of the face.
7906 new_cell->set_combined_face_orientation(
7907 f,
7908 face->reference_cell()
7909 .get_combined_orientation(
7910 make_array_view(vertices_0.cbegin(),
7911 vertices_0.cbegin() +
7912 face->n_vertices()),
7913 make_array_view(vertices_1.cbegin(),
7914 vertices_1.cbegin() +
7915 face->n_vertices())));
7916 }
7917 }
7918 }
7919
7920 // For hexes, we can simply inherit the orientation values
7921 // from the parent on the outer faces; the inner faces can
7922 // be skipped as their orientation is always the default
7923 // one set above.
7924 constexpr ::ndarray<unsigned int, 6, 4>
7925 face_to_child_indices_hex{{{{0, 2, 4, 6}},
7926 {{1, 3, 5, 7}},
7927 {{0, 1, 4, 5}},
7928 {{2, 3, 6, 7}},
7929 {{0, 1, 2, 3}},
7930 {{4, 5, 6, 7}}}};
7931 if (cell_reference_cell == ReferenceCells::Hexahedron)
7932 for (const auto f : cell->face_indices())
7933 {
7934 const auto combined_orientation =
7935 cell->combined_face_orientation(f);
7936 for (unsigned int c = 0; c < 4; ++c)
7937 new_cells[face_to_child_indices_hex[f][c]]
7938 ->set_combined_face_orientation(
7939 f, combined_orientation);
7940 }
7941 }
7942 } // CREATE_CELLS
7943
7944 // Check for distorted children
7945 if (check_for_distorted_cells &&
7946 has_distorted_children<dim, spacedim>(cell))
7947 cells_with_distorted_children.distorted_cells.push_back(cell);
7948
7949 triangulation.signals.post_refinement_on_cell(cell);
7950 }
7951 }
7952
7953 triangulation.faces->quads.clear_user_data();
7954
7955 return cells_with_distorted_children;
7956 }
7957
7962 template <int spacedim>
7965 const bool check_for_distorted_cells)
7966 {
7967 const unsigned int dim = 3;
7968
7969 {
7970 bool flag_isotropic_mesh = true;
7972 cell = triangulation.begin(),
7973 endc = triangulation.end();
7974 for (; cell != endc; ++cell)
7975 if (cell->used())
7976 if (triangulation.get_anisotropic_refinement_flag() ||
7977 cell->refine_flag_set() == RefinementCase<dim>::cut_x ||
7978 cell->refine_flag_set() == RefinementCase<dim>::cut_y ||
7979 cell->refine_flag_set() == RefinementCase<dim>::cut_z ||
7980 cell->refine_flag_set() == RefinementCase<dim>::cut_xy ||
7981 cell->refine_flag_set() == RefinementCase<dim>::cut_xz ||
7982 cell->refine_flag_set() == RefinementCase<dim>::cut_yz)
7983 {
7984 flag_isotropic_mesh = false;
7985 break;
7986 }
7987
7988 if (flag_isotropic_mesh)
7989 return execute_refinement_isotropic(triangulation,
7990 check_for_distorted_cells);
7991 }
7992
7993 // this function probably also works for spacedim>3 but it
7994 // isn't tested. it will probably be necessary to pull new
7995 // vertices onto the manifold just as we do for the other
7996 // functions above.
7997 Assert(spacedim == 3, ExcNotImplemented());
7998
7999 // Check whether a new level is needed. We have to check for
8000 // this on the highest level only
8001 for (const auto &cell : triangulation.active_cell_iterators_on_level(
8002 triangulation.levels.size() - 1))
8003 if (cell->refine_flag_set())
8004 {
8006 triangulation.levels.size() < numbers::max_n_levels,
8008 triangulation.levels.push_back(
8009 std::make_unique<internal::TriangulationImplementation::
8011 triangulation.strides.max_children_per_cell,
8012 triangulation.strides.max_faces_per_cell,
8013 triangulation.strides.max_vertices_per_cell));
8014 break;
8015 }
8016
8017
8018 // first clear user flags for quads and lines; we're going to
8019 // use them to flag which lines and quads need refinement
8020 triangulation.faces->quads.clear_user_data();
8021
8023 triangulation.begin_line();
8024 line != triangulation.end_line();
8025 ++line)
8026 line->clear_user_flag();
8028 triangulation.begin_quad();
8029 quad != triangulation.end_quad();
8030 ++quad)
8031 quad->clear_user_flag();
8032
8033 // create an array of face refine cases. User indices of faces
8034 // will be set to values corresponding with indices in this
8035 // array.
8036 const RefinementCase<dim - 1> face_refinement_cases[4] = {
8037 RefinementCase<dim - 1>::no_refinement,
8038 RefinementCase<dim - 1>::cut_x,
8039 RefinementCase<dim - 1>::cut_y,
8040 RefinementCase<dim - 1>::cut_xy};
8041
8042 // check how much space is needed on every level. We need not
8043 // check the highest level since either
8044 // - on the highest level no cells are flagged for refinement
8045 // - there are, but prepare_refinement added another empty
8046 // level which then is the highest level
8047
8048 // variables to hold the number of newly to be created
8049 // vertices, lines and quads. as these are stored globally,
8050 // declare them outside the loop over al levels. we need lines
8051 // and quads in pairs for refinement of old ones and lines and
8052 // quads, that can be stored as single ones, as they are newly
8053 // created in the inside of an existing cell
8054 unsigned int needed_vertices = 0;
8055 unsigned int needed_lines_single = 0;
8056 unsigned int needed_quads_single = 0;
8057 unsigned int needed_lines_pair = 0;
8058 unsigned int needed_quads_pair = 0;
8059 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
8060 --level_no)
8061 {
8062 // count number of flagged cells on this level and compute
8063 // how many new vertices and new lines will be needed
8064 std::size_t needed_cells = 0;
8065
8066 for (const auto &acell :
8067 triangulation.active_cell_iterators_on_level(level_no))
8068 if (acell->refine_flag_set())
8069 {
8070 RefinementCase<dim> ref_case = acell->refine_flag_set();
8071
8072 // now for interior vertices, lines and quads, which
8073 // are needed in any case
8074 if (ref_case == RefinementCase<dim>::cut_x ||
8075 ref_case == RefinementCase<dim>::cut_y ||
8076 ref_case == RefinementCase<dim>::cut_z)
8077 {
8078 ++needed_quads_single;
8079 needed_cells += 2;
8080 triangulation.anisotropic_refinement = true;
8081 }
8082 else if (ref_case == RefinementCase<dim>::cut_xy ||
8083 ref_case == RefinementCase<dim>::cut_xz ||
8084 ref_case == RefinementCase<dim>::cut_yz)
8085 {
8086 ++needed_lines_single;
8087 needed_quads_single += 4;
8088 needed_cells += 4;
8089 triangulation.anisotropic_refinement = true;
8090 }
8091 else if (ref_case == RefinementCase<dim>::cut_xyz)
8092 {
8093 ++needed_vertices;
8094 needed_lines_single += 6;
8095 needed_quads_single += 12;
8096 needed_cells += 8;
8097 }
8098 else
8099 {
8100 // we should never get here
8102 }
8103
8104 // mark all faces for refinement; checking locally
8105 // if and how the neighbor would like to refine
8106 // these is difficult so we only flag them and after
8107 // visiting all cells, we decide which faces need
8108 // which refinement;
8109 for (const unsigned int face :
8111 {
8113 aface = acell->face(face);
8114 // get the RefineCase this faces has for the
8115 // given RefineCase of the cell
8116 RefinementCase<dim - 1> face_ref_case =
8118 ref_case,
8119 face,
8120 acell->face_orientation(face),
8121 acell->face_flip(face),
8122 acell->face_rotation(face));
8123 // only do something, if this face has to be
8124 // refined
8125 if (face_ref_case)
8126 {
8127 if (face_ref_case ==
8129 {
8130 if (aface->n_active_descendants() < 4)
8131 // we use user_flags to denote needed
8132 // isotropic refinement
8133 aface->set_user_flag();
8134 }
8135 else if (aface->refinement_case() != face_ref_case)
8136 // we use user_indices to denote needed
8137 // anisotropic refinement. note, that we
8138 // can have at most one anisotropic
8139 // refinement case for this face, as
8140 // otherwise prepare_refinement() would
8141 // have changed one of the cells to yield
8142 // isotropic refinement at this
8143 // face. therefore we set the user_index
8144 // uniquely
8145 {
8146 Assert(aface->refinement_case() ==
8148 dim - 1>::isotropic_refinement ||
8149 aface->refinement_case() ==
8152 aface->set_user_index(face_ref_case);
8153 }
8154 }
8155 } // for all faces
8156
8157 // flag all lines, that have to be refined
8158 for (unsigned int line = 0;
8159 line < GeometryInfo<dim>::lines_per_cell;
8160 ++line)
8162 line) &&
8163 !acell->line(line)->has_children())
8164 acell->line(line)->set_user_flag();
8165
8166 } // if refine_flag set and for all cells on this level
8167
8168 // count number of used cells on the next higher level
8169 auto &next_level = *triangulation.levels[level_no + 1];
8170 const auto used_cells = std::count(next_level.cells.used.begin(),
8171 next_level.cells.used.end(),
8172 true);
8173 if (used_cells + needed_cells > next_level.size())
8174 next_level.allocate_end(
8175 (used_cells + needed_cells) - next_level.size(),
8176 // We unconditionally store the orientation in 3d
8177 true,
8178 // TODO: we can get rid of this check (i.e., we don't need to
8179 // store this value for purely wedge meshes). This will be
8180 // simpler to do once we merge IsotropicRefinementChoice and
8181 // RefinementCase.
8182 !triangulation.all_reference_cells_are_hyper_cube());
8183
8184 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
8185 next_level.cells.allocate_end(needed_cells, 0);
8186 } // for all levels
8187 // now count the quads and lines which were flagged for
8188 // refinement
8190 triangulation.begin_quad();
8191 quad != triangulation.end_quad();
8192 ++quad)
8193 {
8194 if (quad->user_flag_set())
8195 {
8196 // isotropic refinement: 1 interior vertex, 4 quads
8197 // and 4 interior lines. we store the interior lines
8198 // in pairs in case the face is already or will be
8199 // refined anisotropically
8200 needed_quads_pair += 4;
8201 needed_lines_pair += 4;
8202 needed_vertices += 1;
8203 }
8204 if (quad->user_index())
8205 {
8206 // anisotropic refinement: 1 interior
8207 // line and two quads
8208 needed_quads_pair += 2;
8209 needed_lines_single += 1;
8210 // there is a kind of complicated situation here which
8211 // requires our attention. if the quad is refined
8212 // isotropcally, two of the interior lines will get a
8213 // new mother line - the interior line of our
8214 // anisotropically refined quad. if those two lines
8215 // are not consecutive, we cannot do so and have to
8216 // replace them by two lines that are consecutive. we
8217 // try to avoid that situation, but it may happen
8218 // nevertheless through repeated refinement and
8219 // coarsening. thus we have to check here, as we will
8220 // need some additional space to store those new lines
8221 // in case we need them...
8222 if (quad->has_children())
8223 {
8224 Assert(quad->refinement_case() ==
8227 if ((face_refinement_cases[quad->user_index()] ==
8229 (quad->child(0)->line_index(1) + 1 !=
8230 quad->child(2)->line_index(1))) ||
8231 (face_refinement_cases[quad->user_index()] ==
8233 (quad->child(0)->line_index(3) + 1 !=
8234 quad->child(1)->line_index(3))))
8235 needed_lines_pair += 2;
8236 }
8237 }
8238 }
8239
8241 triangulation.begin_line();
8242 line != triangulation.end_line();
8243 ++line)
8244 if (line->user_flag_set())
8245 {
8246 needed_lines_pair += 2;
8247 needed_vertices += 1;
8248 }
8249
8250 // reserve space for needed_lines new lines stored in pairs
8251 triangulation.faces->lines.allocate_end(needed_lines_pair,
8252 needed_lines_single);
8253
8254 // reserve space for needed_quads new quads stored in pairs
8255 triangulation.faces->allocate_end(needed_quads_pair,
8256 needed_quads_single);
8257
8258 // add to needed vertices how many vertices are already in use
8259 needed_vertices += std::count(triangulation.vertices_used.begin(),
8260 triangulation.vertices_used.end(),
8261 true);
8262 // if we need more vertices: create them, if not: leave the
8263 // array as is, since shrinking is not really possible because
8264 // some of the vertices at the end may be in use
8265 if (needed_vertices > triangulation.vertices.size())
8266 {
8267 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
8268 triangulation.vertices_used.resize(needed_vertices, false);
8269 }
8270
8271
8272 //-----------------------------------------
8273 // Before we start with the actual refinement, we do some
8274 // sanity checks if in debug mode. especially, we try to catch
8275 // the notorious problem with lines being twice refined,
8276 // i.e. there are cells adjacent at one line ("around the
8277 // edge", but not at a face), with two cells differing by more
8278 // than one refinement level
8279 //
8280 // this check is very simple to implement here, since we have
8281 // all lines flagged if they shall be refined
8282 if constexpr (running_in_debug_mode())
8283 {
8284 for (const auto &cell : triangulation.active_cell_iterators())
8285 if (!cell->refine_flag_set())
8286 for (unsigned int line = 0;
8287 line < GeometryInfo<dim>::lines_per_cell;
8288 ++line)
8289 if (cell->line(line)->has_children())
8290 for (unsigned int c = 0; c < 2; ++c)
8291 Assert(cell->line(line)->child(c)->user_flag_set() ==
8292 false,
8294 }
8295
8296 //-----------------------------------------
8297 // Do refinement on every level
8298 //
8299 // To make life a bit easier, we first refine those lines and
8300 // quads that were flagged for refinement and then compose the
8301 // newly to be created cells.
8302 //
8303 // index of next unused vertex
8304 unsigned int next_unused_vertex = 0;
8305
8306 // first for lines
8307 {
8308 // only active objects can be refined further
8310 line = triangulation.begin_active_line(),
8311 endl = triangulation.end_line();
8313 next_unused_line = triangulation.begin_raw_line();
8314
8315 for (; line != endl; ++line)
8316 if (line->user_flag_set())
8317 {
8318 // this line needs to be refined
8319
8320 // find the next unused vertex and set it
8321 // appropriately
8322 while (triangulation.vertices_used[next_unused_vertex] == true)
8323 ++next_unused_vertex;
8324 Assert(
8325 next_unused_vertex < triangulation.vertices.size(),
8326 ExcMessage(
8327 "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."));
8328 triangulation.vertices_used[next_unused_vertex] = true;
8329
8330 triangulation.vertices[next_unused_vertex] = line->center(true);
8331
8332 // now that we created the right point, make up the
8333 // two child lines (++ takes care of the end of the
8334 // vector)
8335 next_unused_line =
8336 triangulation.faces->lines.template next_free_pair_object<1>(
8337 triangulation);
8338 Assert(next_unused_line.state() == IteratorState::valid,
8340
8341 // now we found two consecutive unused lines, such
8342 // that the children of a line will be consecutive.
8343 // then set the child pointer of the present line
8344 line->set_children(0, next_unused_line->index());
8345
8346 // set the two new lines
8348 children[2] = {next_unused_line, ++next_unused_line};
8349
8350 // some tests; if any of the iterators should be
8351 // invalid, then already dereferencing will fail
8352 AssertIsNotUsed(children[0]);
8353 AssertIsNotUsed(children[1]);
8354
8355 children[0]->set_bounding_object_indices(
8356 {line->vertex_index(0), next_unused_vertex});
8357 children[1]->set_bounding_object_indices(
8358 {next_unused_vertex, line->vertex_index(1)});
8359
8360 children[0]->set_used_flag();
8361 children[1]->set_used_flag();
8362 children[0]->clear_children();
8363 children[1]->clear_children();
8364 children[0]->clear_user_data();
8365 children[1]->clear_user_data();
8366 children[0]->clear_user_flag();
8367 children[1]->clear_user_flag();
8368
8369 children[0]->set_boundary_id_internal(line->boundary_id());
8370 children[1]->set_boundary_id_internal(line->boundary_id());
8371
8372 children[0]->set_manifold_id(line->manifold_id());
8373 children[1]->set_manifold_id(line->manifold_id());
8374
8375 // finally clear flag
8376 // indicating the need
8377 // for refinement
8378 line->clear_user_flag();
8379 }
8380 }
8381
8382
8383 //-------------------------------------
8384 // now refine marked quads
8385 //-------------------------------------
8386
8387 // here we encounter several cases:
8388
8389 // a) the quad is unrefined and shall be refined isotropically
8390
8391 // b) the quad is unrefined and shall be refined
8392 // anisotropically
8393
8394 // c) the quad is unrefined and shall be refined both
8395 // anisotropically and isotropically (this is reduced to case
8396 // b) and then case b) for the children again)
8397
8398 // d) the quad is refined anisotropically and shall be refined
8399 // isotropically (this is reduced to case b) for the
8400 // anisotropic children)
8401
8402 // e) the quad is refined isotropically and shall be refined
8403 // anisotropically (this is transformed to case c), however we
8404 // might have to renumber/rename children...)
8405
8406 // we need a loop in cases c) and d), as the anisotropic
8407 // children might have a lower index than the mother quad
8408 for (unsigned int loop = 0; loop < 2; ++loop)
8409 {
8410 // usually, only active objects can be refined
8411 // further. however, in cases d) and e) that is not true,
8412 // so we have to use 'normal' iterators here
8414 quad = triangulation.begin_quad(),
8415 endq = triangulation.end_quad();
8417 next_unused_line = triangulation.begin_raw_line();
8419 next_unused_quad = triangulation.begin_raw_quad();
8420
8421 for (; quad != endq; ++quad)
8422 {
8423 if (quad->user_index())
8424 {
8425 RefinementCase<dim - 1> aniso_quad_ref_case =
8426 face_refinement_cases[quad->user_index()];
8427 // there is one unlikely event here, where we
8428 // already have refind the face: if the face was
8429 // refined anisotropically and we want to refine
8430 // it isotropically, both children are flagged for
8431 // anisotropic refinement. however, if those
8432 // children were already flagged for anisotropic
8433 // refinement, they might already be processed and
8434 // refined.
8435 if (aniso_quad_ref_case == quad->refinement_case())
8436 continue;
8437
8438 Assert(quad->refinement_case() ==
8440 quad->refinement_case() ==
8443
8444 // this quad needs to be refined anisotropically
8445 Assert(quad->user_index() ==
8447 quad->user_index() ==
8450
8451 // make the new line interior to the quad
8453 new_line;
8454
8455 new_line =
8456 triangulation.faces->lines
8457 .template next_free_single_object<1>(triangulation);
8458 AssertIsNotUsed(new_line);
8459
8460 // first collect the
8461 // indices of the vertices:
8462 // *--1--*
8463 // | | |
8464 // | | | cut_x
8465 // | | |
8466 // *--0--*
8467 //
8468 // *-----*
8469 // | |
8470 // 0-----1 cut_y
8471 // | |
8472 // *-----*
8473 unsigned int vertex_indices[2];
8474 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8475 {
8476 vertex_indices[0] =
8477 quad->line(2)->child(0)->vertex_index(1);
8478 vertex_indices[1] =
8479 quad->line(3)->child(0)->vertex_index(1);
8480 }
8481 else
8482 {
8483 vertex_indices[0] =
8484 quad->line(0)->child(0)->vertex_index(1);
8485 vertex_indices[1] =
8486 quad->line(1)->child(0)->vertex_index(1);
8487 }
8488
8489 new_line->set_bounding_object_indices(
8491 new_line->set_used_flag();
8492 new_line->clear_user_flag();
8493 new_line->clear_user_data();
8494 new_line->clear_children();
8495 new_line->set_boundary_id_internal(quad->boundary_id());
8496 new_line->set_manifold_id(quad->manifold_id());
8497
8498 // find some space (consecutive) for the two newly
8499 // to be created quads.
8501 new_quads[2];
8502
8503 next_unused_quad =
8504 triangulation.faces->quads
8505 .template next_free_pair_object<2>(triangulation);
8506 new_quads[0] = next_unused_quad;
8507 AssertIsNotUsed(new_quads[0]);
8508
8509 ++next_unused_quad;
8510 new_quads[1] = next_unused_quad;
8511 AssertIsNotUsed(new_quads[1]);
8512
8513 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8514 {
8515 new_quads[0]->set_bounding_object_indices(
8516 {static_cast<int>(quad->line_index(0)),
8517 new_line->index(),
8518 quad->line(2)
8519 ->child(
8520 child_line_index(0, quad->line_orientation(2)))
8521 ->index(),
8522 quad->line(3)
8523 ->child(
8524 child_line_index(0, quad->line_orientation(3)))
8525 ->index()});
8526 new_quads[1]->set_bounding_object_indices(
8527 {new_line->index(),
8528 static_cast<int>(quad->line_index(1)),
8529 quad->line(2)
8530 ->child(
8531 child_line_index(1, quad->line_orientation(2)))
8532 ->index(),
8533 quad->line(3)
8534 ->child(
8535 child_line_index(1, quad->line_orientation(3)))
8536 ->index()});
8537 }
8538 else
8539 {
8540 new_quads[0]->set_bounding_object_indices(
8541 {quad->line(0)
8542 ->child(
8543 child_line_index(0, quad->line_orientation(0)))
8544 ->index(),
8545 quad->line(1)
8546 ->child(
8547 child_line_index(0, quad->line_orientation(1)))
8548 ->index(),
8549 static_cast<int>(quad->line_index(2)),
8550 new_line->index()});
8551 new_quads[1]->set_bounding_object_indices(
8552 {quad->line(0)
8553 ->child(
8554 child_line_index(1, quad->line_orientation(0)))
8555 ->index(),
8556 quad->line(1)
8557 ->child(
8558 child_line_index(1, quad->line_orientation(1)))
8559 ->index(),
8560 new_line->index(),
8561 static_cast<int>(quad->line_index(3))});
8562 }
8563
8564 for (const auto &new_quad : new_quads)
8565 {
8566 new_quad->set_used_flag();
8567 new_quad->clear_user_flag();
8568 new_quad->clear_user_data();
8569 new_quad->clear_children();
8570 new_quad->set_boundary_id_internal(quad->boundary_id());
8571 new_quad->set_manifold_id(quad->manifold_id());
8572 // set all line orientations to true, change
8573 // this after the loop, as we have to consider
8574 // different lines for each child
8575 for (unsigned int j = 0;
8576 j < GeometryInfo<dim>::lines_per_face;
8577 ++j)
8578 new_quad->set_line_orientation(
8580 }
8581 // now set the line orientation of children of
8582 // outer lines correctly, the lines in the
8583 // interior of the refined quad are automatically
8584 // oriented conforming to the standard
8585 new_quads[0]->set_line_orientation(
8586 0, quad->line_orientation(0));
8587 new_quads[0]->set_line_orientation(
8588 2, quad->line_orientation(2));
8589 new_quads[1]->set_line_orientation(
8590 1, quad->line_orientation(1));
8591 new_quads[1]->set_line_orientation(
8592 3, quad->line_orientation(3));
8593 if (aniso_quad_ref_case == RefinementCase<dim - 1>::cut_x)
8594 {
8595 new_quads[0]->set_line_orientation(
8596 3, quad->line_orientation(3));
8597 new_quads[1]->set_line_orientation(
8598 2, quad->line_orientation(2));
8599 }
8600 else
8601 {
8602 new_quads[0]->set_line_orientation(
8603 1, quad->line_orientation(1));
8604 new_quads[1]->set_line_orientation(
8605 0, quad->line_orientation(0));
8606 }
8607
8608 // test, whether this face is refined
8609 // isotropically already. if so, set the correct
8610 // children pointers.
8611 if (quad->refinement_case() ==
8612 RefinementCase<dim - 1>::cut_xy)
8613 {
8614 // we will put a new refinemnt level of
8615 // anisotropic refinement between the
8616 // unrefined and isotropically refined quad
8617 // ending up with the same fine quads but
8618 // introducing anisotropically refined ones as
8619 // children of the unrefined quad and mother
8620 // cells of the original fine ones.
8621
8622 // this process includes the creation of a new
8623 // middle line which we will assign as the
8624 // mother line of two of the existing inner
8625 // lines. If those inner lines are not
8626 // consecutive in memory, we won't find them
8627 // later on, so we have to create new ones
8628 // instead and replace all occurrences of the
8629 // old ones with those new ones. As this is
8630 // kind of ugly, we hope we don't have to do
8631 // it often...
8633 old_child[2];
8634 if (aniso_quad_ref_case ==
8636 {
8637 old_child[0] = quad->child(0)->line(1);
8638 old_child[1] = quad->child(2)->line(1);
8639 }
8640 else
8641 {
8642 Assert(aniso_quad_ref_case ==
8645
8646 old_child[0] = quad->child(0)->line(3);
8647 old_child[1] = quad->child(1)->line(3);
8648 }
8649
8650 if (old_child[0]->index() + 1 != old_child[1]->index())
8651 {
8652 // this is exactly the ugly case we talked
8653 // about. so, no complaining, lets get
8654 // two new lines and copy all info
8655 typename Triangulation<dim,
8656 spacedim>::raw_line_iterator
8657 new_child[2];
8658
8659 new_child[0] = new_child[1] =
8660 triangulation.faces->lines
8661 .template next_free_pair_object<1>(
8662 triangulation);
8663 ++new_child[1];
8664
8665 new_child[0]->set_used_flag();
8666 new_child[1]->set_used_flag();
8667
8668 const int old_index_0 = old_child[0]->index(),
8669 old_index_1 = old_child[1]->index(),
8670 new_index_0 = new_child[0]->index(),
8671 new_index_1 = new_child[1]->index();
8672
8673 // loop over all quads and replace the old
8674 // lines
8675 for (unsigned int q = 0;
8676 q < triangulation.faces->quads.n_objects();
8677 ++q)
8678 for (unsigned int l = 0;
8679 l < GeometryInfo<dim>::lines_per_face;
8680 ++l)
8681 {
8682 const int this_index =
8683 triangulation.faces->quads
8684 .get_bounding_object_indices(q)[l];
8685 if (this_index == old_index_0)
8686 triangulation.faces->quads
8687 .get_bounding_object_indices(q)[l] =
8688 new_index_0;
8689 else if (this_index == old_index_1)
8690 triangulation.faces->quads
8691 .get_bounding_object_indices(q)[l] =
8692 new_index_1;
8693 }
8694 // now we have to copy all information of
8695 // the two lines
8696 for (unsigned int i = 0; i < 2; ++i)
8697 {
8698 Assert(!old_child[i]->has_children(),
8700
8701 new_child[i]->set_bounding_object_indices(
8702 {old_child[i]->vertex_index(0),
8703 old_child[i]->vertex_index(1)});
8704 new_child[i]->set_boundary_id_internal(
8705 old_child[i]->boundary_id());
8706 new_child[i]->set_manifold_id(
8707 old_child[i]->manifold_id());
8708 new_child[i]->set_user_index(
8709 old_child[i]->user_index());
8710 if (old_child[i]->user_flag_set())
8711 new_child[i]->set_user_flag();
8712 else
8713 new_child[i]->clear_user_flag();
8714
8715 new_child[i]->clear_children();
8716
8717 old_child[i]->clear_user_flag();
8718 old_child[i]->clear_user_index();
8719 old_child[i]->clear_used_flag();
8720 }
8721 }
8722 // now that we cared about the lines, go on
8723 // with the quads themselves, where we might
8724 // encounter similar situations...
8725 if (aniso_quad_ref_case ==
8727 {
8728 new_line->set_children(
8729 0, quad->child(0)->line_index(1));
8730 Assert(new_line->child(1) ==
8731 quad->child(2)->line(1),
8733 // now evereything is quite
8734 // complicated. we have the children
8735 // numbered according to
8736 //
8737 // *---*---*
8738 // |n+2|n+3|
8739 // *---*---*
8740 // | n |n+1|
8741 // *---*---*
8742 //
8743 // from the original isotropic
8744 // refinement. we have to reorder them as
8745 //
8746 // *---*---*
8747 // |n+1|n+3|
8748 // *---*---*
8749 // | n |n+2|
8750 // *---*---*
8751 //
8752 // such that n and n+1 are consecutive
8753 // children of m and n+2 and n+3 are
8754 // consecutive children of m+1, where m
8755 // and m+1 are given as in
8756 //
8757 // *---*---*
8758 // | | |
8759 // | m |m+1|
8760 // | | |
8761 // *---*---*
8762 //
8763 // this is a bit ugly, of course: loop
8764 // over all cells on all levels and look
8765 // for faces n+1 (switch_1) and n+2
8766 // (switch_2).
8767 const typename Triangulation<dim, spacedim>::
8768 quad_iterator switch_1 = quad->child(1),
8769 switch_2 = quad->child(2);
8770 const int switch_1_index = switch_1->index();
8771 const int switch_2_index = switch_2->index();
8772 for (unsigned int l = 0;
8773 l < triangulation.levels.size();
8774 ++l)
8775 for (unsigned int h = 0;
8776 h <
8777 triangulation.levels[l]->cells.n_objects();
8778 ++h)
8779 for (const unsigned int q :
8781 {
8782 const int face_index =
8783 triangulation.levels[l]
8784 ->cells.get_bounding_object_indices(
8785 h)[q];
8786 if (face_index == switch_1_index)
8787 triangulation.levels[l]
8788 ->cells.get_bounding_object_indices(
8789 h)[q] = switch_2_index;
8790 else if (face_index == switch_2_index)
8791 triangulation.levels[l]
8792 ->cells.get_bounding_object_indices(
8793 h)[q] = switch_1_index;
8794 }
8795 // now we have to copy all information of
8796 // the two quads
8797 int switch_1_lines[4], switch_2_lines[4];
8798 for (int i = 0; i < 4; ++i)
8799 {
8800 switch_1_lines[i] = switch_1->line(i)->index();
8801 switch_2_lines[i] = switch_2->line(i)->index();
8802 }
8804 switch_1_line_orientations[4] = {
8805 switch_1->line_orientation(0),
8806 switch_1->line_orientation(1),
8807 switch_1->line_orientation(2),
8808 switch_1->line_orientation(3)};
8809 const types::boundary_id switch_1_boundary_id =
8810 switch_1->boundary_id();
8811 const unsigned int switch_1_user_index =
8812 switch_1->user_index();
8813 const bool switch_1_user_flag =
8814 switch_1->user_flag_set();
8815 const RefinementCase<dim - 1>
8816 switch_1_refinement_case =
8817 switch_1->refinement_case();
8818 const int switch_1_first_child_pair =
8819 (switch_1_refinement_case ?
8820 switch_1->child_index(0) :
8821 -1);
8822 const int switch_1_second_child_pair =
8823 (switch_1_refinement_case ==
8824 RefinementCase<dim - 1>::cut_xy ?
8825 switch_1->child_index(2) :
8826 -1);
8827
8828 switch_1->set_bounding_object_indices(
8829 {switch_2_lines[0],
8830 switch_2_lines[1],
8831 switch_2_lines[2],
8832 switch_2_lines[3]});
8833 switch_1->set_line_orientation(
8834 0, switch_2->line_orientation(0));
8835 switch_1->set_line_orientation(
8836 1, switch_2->line_orientation(1));
8837 switch_1->set_line_orientation(
8838 2, switch_2->line_orientation(2));
8839 switch_1->set_line_orientation(
8840 3, switch_2->line_orientation(3));
8841 switch_1->set_boundary_id_internal(
8842 switch_2->boundary_id());
8843 switch_1->set_manifold_id(switch_2->manifold_id());
8844 switch_1->set_user_index(switch_2->user_index());
8845 if (switch_2->user_flag_set())
8846 switch_1->set_user_flag();
8847 else
8848 switch_1->clear_user_flag();
8849 switch_1->clear_refinement_case();
8850 switch_1->set_refinement_case(
8851 switch_2->refinement_case());
8852 switch_1->clear_children();
8853 if (switch_2->refinement_case())
8854 switch_1->set_children(0,
8855 switch_2->child_index(0));
8856 if (switch_2->refinement_case() ==
8857 RefinementCase<dim - 1>::cut_xy)
8858 switch_1->set_children(2,
8859 switch_2->child_index(2));
8860
8861 switch_2->set_bounding_object_indices(
8862 {switch_1_lines[0],
8863 switch_1_lines[1],
8864 switch_1_lines[2],
8865 switch_1_lines[3]});
8866 switch_2->set_line_orientation(
8867 0, switch_1_line_orientations[0]);
8868 switch_2->set_line_orientation(
8869 1, switch_1_line_orientations[1]);
8870 switch_2->set_line_orientation(
8871 2, switch_1_line_orientations[2]);
8872 switch_2->set_line_orientation(
8873 3, switch_1_line_orientations[3]);
8874 switch_2->set_boundary_id_internal(
8875 switch_1_boundary_id);
8876 switch_2->set_manifold_id(switch_1->manifold_id());
8877 switch_2->set_user_index(switch_1_user_index);
8878 if (switch_1_user_flag)
8879 switch_2->set_user_flag();
8880 else
8881 switch_2->clear_user_flag();
8882 switch_2->clear_refinement_case();
8883 switch_2->set_refinement_case(
8884 switch_1_refinement_case);
8885 switch_2->clear_children();
8886 switch_2->set_children(0,
8887 switch_1_first_child_pair);
8888 switch_2->set_children(2,
8889 switch_1_second_child_pair);
8890
8891 new_quads[0]->set_refinement_case(
8893 new_quads[0]->set_children(0, quad->child_index(0));
8894 new_quads[1]->set_refinement_case(
8896 new_quads[1]->set_children(0, quad->child_index(2));
8897 }
8898 else
8899 {
8900 new_quads[0]->set_refinement_case(
8902 new_quads[0]->set_children(0, quad->child_index(0));
8903 new_quads[1]->set_refinement_case(
8905 new_quads[1]->set_children(0, quad->child_index(2));
8906 new_line->set_children(
8907 0, quad->child(0)->line_index(3));
8908 Assert(new_line->child(1) ==
8909 quad->child(1)->line(3),
8911 }
8912 quad->clear_children();
8913 }
8914
8915 // note these quads as children to the present one
8916 quad->set_children(0, new_quads[0]->index());
8917
8918 quad->set_refinement_case(aniso_quad_ref_case);
8919
8920 // finally clear flag indicating the need for
8921 // refinement
8922 quad->clear_user_data();
8923 } // if (anisotropic refinement)
8924
8925 if (quad->user_flag_set())
8926 {
8927 // this quad needs to be refined isotropically
8928
8929 // first of all: we only get here in the first run
8930 // of the loop
8931 Assert(loop == 0, ExcInternalError());
8932
8933 // find the next unused vertex. we'll need this in
8934 // any case
8935 while (triangulation.vertices_used[next_unused_vertex] ==
8936 true)
8937 ++next_unused_vertex;
8938 Assert(
8939 next_unused_vertex < triangulation.vertices.size(),
8940 ExcMessage(
8941 "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."));
8942
8943 // now: if the quad is refined anisotropically
8944 // already, set the anisotropic refinement flag
8945 // for both children. Additionally, we have to
8946 // refine the inner line, as it is an outer line
8947 // of the two (anisotropic) children
8948 const RefinementCase<dim - 1> quad_ref_case =
8949 quad->refinement_case();
8950
8951 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8952 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8953 {
8954 // set the 'opposite' refine case for children
8955 quad->child(0)->set_user_index(
8956 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8957 quad->child(1)->set_user_index(
8958 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8959 // refine the inner line
8961 middle_line;
8962 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8963 middle_line = quad->child(0)->line(1);
8964 else
8965 middle_line = quad->child(0)->line(3);
8966
8967 // if the face has been refined
8968 // anisotropically in the last refinement step
8969 // it might be, that it is flagged already and
8970 // that the middle line is thus refined
8971 // already. if not create children.
8972 if (!middle_line->has_children())
8973 {
8974 // set the middle vertex
8975 // appropriately. double refinement of
8976 // quads can only happen in the interior
8977 // of the domain, so we need not care
8978 // about boundary quads here
8979 triangulation.vertices[next_unused_vertex] =
8980 middle_line->center(true);
8981 triangulation.vertices_used[next_unused_vertex] =
8982 true;
8983
8984 // now search a slot for the two
8985 // child lines
8986 next_unused_line =
8987 triangulation.faces->lines
8988 .template next_free_pair_object<1>(
8989 triangulation);
8990
8991 // set the child pointer of the present
8992 // line
8993 middle_line->set_children(
8994 0, next_unused_line->index());
8995
8996 // set the two new lines
8997 const typename Triangulation<dim, spacedim>::
8998 raw_line_iterator children[2] = {
8999 next_unused_line, ++next_unused_line};
9000
9001 // some tests; if any of the iterators
9002 // should be invalid, then already
9003 // dereferencing will fail
9004 AssertIsNotUsed(children[0]);
9005 AssertIsNotUsed(children[1]);
9006
9007 children[0]->set_bounding_object_indices(
9008 {middle_line->vertex_index(0),
9009 next_unused_vertex});
9010 children[1]->set_bounding_object_indices(
9011 {next_unused_vertex,
9012 middle_line->vertex_index(1)});
9013
9014 children[0]->set_used_flag();
9015 children[1]->set_used_flag();
9016 children[0]->clear_children();
9017 children[1]->clear_children();
9018 children[0]->clear_user_data();
9019 children[1]->clear_user_data();
9020 children[0]->clear_user_flag();
9021 children[1]->clear_user_flag();
9022
9023 children[0]->set_boundary_id_internal(
9024 middle_line->boundary_id());
9025 children[1]->set_boundary_id_internal(
9026 middle_line->boundary_id());
9027
9028 children[0]->set_manifold_id(
9029 middle_line->manifold_id());
9030 children[1]->set_manifold_id(
9031 middle_line->manifold_id());
9032 }
9033 // now remove the flag from the quad and go to
9034 // the next quad, the actual refinement of the
9035 // quad takes place later on in this pass of
9036 // the loop or in the next one
9037 quad->clear_user_flag();
9038 continue;
9039 } // if (several refinement cases)
9040
9041 // if we got here, we have an unrefined quad and
9042 // have to do the usual work like in an purely
9043 // isotropic refinement
9044 Assert(quad_ref_case ==
9047
9048 // set the middle vertex appropriately: it might be that
9049 // the quad itself is not at the boundary, but that one of
9050 // its lines actually is. in this case, the newly created
9051 // vertices at the centers of the lines are not
9052 // necessarily the mean values of the adjacent vertices,
9053 // so do not compute the new vertex as the mean value of
9054 // the 4 vertices of the face, but rather as a weighted
9055 // mean value of the 8 vertices which we already have (the
9056 // four old ones, and the four ones inserted as middle
9057 // points for the four lines). summing up some more points
9058 // is generally cheaper than first asking whether one of
9059 // the lines is at the boundary
9060 //
9061 // note that the exact weights are chosen such as to
9062 // minimize the distortion of the four new quads from the
9063 // optimal shape. their description uses the formulas
9064 // underlying the TransfiniteInterpolationManifold
9065 // implementation
9066 triangulation.vertices[next_unused_vertex] =
9067 quad->center(true, true);
9068 triangulation.vertices_used[next_unused_vertex] = true;
9069
9070 // now that we created the right point, make up
9071 // the four lines interior to the quad (++ takes
9072 // care of the end of the vector)
9074 new_lines[4];
9075
9076 for (unsigned int i = 0; i < 4; ++i)
9077 {
9078 if (i % 2 == 0)
9079 // search a free pair of lines for 0. and
9080 // 2. line, so that two of them end up
9081 // together, which is necessary if later on
9082 // we want to refine the quad
9083 // anisotropically and the two lines end up
9084 // as children of new line
9085 next_unused_line =
9086 triangulation.faces->lines
9087 .template next_free_pair_object<1>(triangulation);
9088
9089 new_lines[i] = next_unused_line;
9090 ++next_unused_line;
9091
9092 AssertIsNotUsed(new_lines[i]);
9093 }
9094
9095 // set the data of the four lines. first collect
9096 // the indices of the five vertices:
9097 //
9098 // *--3--*
9099 // | | |
9100 // 0--4--1
9101 // | | |
9102 // *--2--*
9103 //
9104 // the lines are numbered as follows:
9105 //
9106 // *--*--*
9107 // | 1 |
9108 // *2-*-3*
9109 // | 0 |
9110 // *--*--*
9111
9112 const unsigned int vertex_indices[5] = {
9113 quad->line(0)->child(0)->vertex_index(1),
9114 quad->line(1)->child(0)->vertex_index(1),
9115 quad->line(2)->child(0)->vertex_index(1),
9116 quad->line(3)->child(0)->vertex_index(1),
9117 next_unused_vertex};
9118
9119 new_lines[0]->set_bounding_object_indices(
9121 new_lines[1]->set_bounding_object_indices(
9123 new_lines[2]->set_bounding_object_indices(
9125 new_lines[3]->set_bounding_object_indices(
9127
9128 for (const auto &new_line : new_lines)
9129 {
9130 new_line->set_used_flag();
9131 new_line->clear_user_flag();
9132 new_line->clear_user_data();
9133 new_line->clear_children();
9134 new_line->set_boundary_id_internal(quad->boundary_id());
9135 new_line->set_manifold_id(quad->manifold_id());
9136 }
9137
9138 // now for the quads. again, first collect some
9139 // data about the indices of the lines, with the
9140 // following numbering:
9141 //
9142 // .-6-.-7-.
9143 // 1 9 3
9144 // .-10.11-.
9145 // 0 8 2
9146 // .-4-.-5-.
9147
9148 const int line_indices[12] = {
9149 quad->line(0)
9150 ->child(child_line_index(0, quad->line_orientation(0)))
9151 ->index(),
9152 quad->line(0)
9153 ->child(child_line_index(1, quad->line_orientation(0)))
9154 ->index(),
9155 quad->line(1)
9156 ->child(child_line_index(0, quad->line_orientation(1)))
9157 ->index(),
9158 quad->line(1)
9159 ->child(child_line_index(1, quad->line_orientation(1)))
9160 ->index(),
9161 quad->line(2)
9162 ->child(child_line_index(0, quad->line_orientation(2)))
9163 ->index(),
9164 quad->line(2)
9165 ->child(child_line_index(1, quad->line_orientation(2)))
9166 ->index(),
9167 quad->line(3)
9168 ->child(child_line_index(0, quad->line_orientation(3)))
9169 ->index(),
9170 quad->line(3)
9171 ->child(child_line_index(1, quad->line_orientation(3)))
9172 ->index(),
9173 new_lines[0]->index(),
9174 new_lines[1]->index(),
9175 new_lines[2]->index(),
9176 new_lines[3]->index()};
9177
9178 // find some space (consecutive)
9179 // for the first two newly to be
9180 // created quads.
9182 new_quads[4];
9183
9184 next_unused_quad =
9185 triangulation.faces->quads
9186 .template next_free_pair_object<2>(triangulation);
9187
9188 new_quads[0] = next_unused_quad;
9189 AssertIsNotUsed(new_quads[0]);
9190
9191 ++next_unused_quad;
9192 new_quads[1] = next_unused_quad;
9193 AssertIsNotUsed(new_quads[1]);
9194
9195 next_unused_quad =
9196 triangulation.faces->quads
9197 .template next_free_pair_object<2>(triangulation);
9198 new_quads[2] = next_unused_quad;
9199 AssertIsNotUsed(new_quads[2]);
9200
9201 ++next_unused_quad;
9202 new_quads[3] = next_unused_quad;
9203 AssertIsNotUsed(new_quads[3]);
9204
9205 // note these quads as children to the present one
9206 quad->set_children(0, new_quads[0]->index());
9207 quad->set_children(2, new_quads[2]->index());
9208 quad->set_refinement_case(RefinementCase<2>::cut_xy);
9209
9210 new_quads[0]->set_bounding_object_indices(
9211 {line_indices[0],
9212 line_indices[8],
9213 line_indices[4],
9214 line_indices[10]});
9215 new_quads[1]->set_bounding_object_indices(
9216 {line_indices[8],
9217 line_indices[2],
9218 line_indices[5],
9219 line_indices[11]});
9220 new_quads[2]->set_bounding_object_indices(
9221 {line_indices[1],
9222 line_indices[9],
9223 line_indices[10],
9224 line_indices[6]});
9225 new_quads[3]->set_bounding_object_indices(
9226 {line_indices[9],
9227 line_indices[3],
9228 line_indices[11],
9229 line_indices[7]});
9230 for (const auto &new_quad : new_quads)
9231 {
9232 new_quad->set_used_flag();
9233 new_quad->clear_user_flag();
9234 new_quad->clear_user_data();
9235 new_quad->clear_children();
9236 new_quad->set_boundary_id_internal(quad->boundary_id());
9237 new_quad->set_manifold_id(quad->manifold_id());
9238 // set all line orientations to true, change
9239 // this after the loop, as we have to consider
9240 // different lines for each child
9241 for (unsigned int j = 0;
9242 j < GeometryInfo<dim>::lines_per_face;
9243 ++j)
9244 new_quad->set_line_orientation(
9246 }
9247 // now set the line orientation of children of
9248 // outer lines correctly, the lines in the
9249 // interior of the refined quad are automatically
9250 // oriented conforming to the standard
9251 new_quads[0]->set_line_orientation(
9252 0, quad->line_orientation(0));
9253 new_quads[0]->set_line_orientation(
9254 2, quad->line_orientation(2));
9255 new_quads[1]->set_line_orientation(
9256 1, quad->line_orientation(1));
9257 new_quads[1]->set_line_orientation(
9258 2, quad->line_orientation(2));
9259 new_quads[2]->set_line_orientation(
9260 0, quad->line_orientation(0));
9261 new_quads[2]->set_line_orientation(
9262 3, quad->line_orientation(3));
9263 new_quads[3]->set_line_orientation(
9264 1, quad->line_orientation(1));
9265 new_quads[3]->set_line_orientation(
9266 3, quad->line_orientation(3));
9267
9268 // finally clear flag indicating the need for
9269 // refinement
9270 quad->clear_user_flag();
9271 } // if (isotropic refinement)
9272 } // for all quads
9273 } // looped two times over all quads, all quads refined now
9274
9275 //---------------------------------
9276 // Now, finally, set up the new
9277 // cells
9278 //---------------------------------
9279
9281 cells_with_distorted_children;
9282
9283 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
9284 ++level)
9285 {
9286 // only active objects can be refined further; remember
9287 // that we won't operate on the finest level, so
9288 // triangulation.begin_*(level+1) is allowed
9290 hex = triangulation.begin_active_hex(level),
9291 endh = triangulation.begin_active_hex(level + 1);
9293 next_unused_hex = triangulation.begin_raw_hex(level + 1);
9294
9295 for (; hex != endh; ++hex)
9296 if (hex->refine_flag_set())
9297 {
9298 // this hex needs to be refined
9299
9300 // clear flag indicating the need for refinement. do
9301 // it here already, since we can't do it anymore
9302 // once the cell has children
9303 const RefinementCase<dim> ref_case = hex->refine_flag_set();
9304 hex->clear_refine_flag();
9305 hex->set_refinement_case(ref_case);
9306
9307 // depending on the refine case we might have to
9308 // create additional vertices, lines and quads
9309 // interior of the hex before the actual children
9310 // can be set up.
9311
9312 // in a first step: reserve the needed space for
9313 // lines, quads and hexes and initialize them
9314 // correctly
9315
9316 unsigned int n_new_lines = 0;
9317 unsigned int n_new_quads = 0;
9318 unsigned int n_new_hexes = 0;
9319 switch (ref_case)
9320 {
9324 n_new_lines = 0;
9325 n_new_quads = 1;
9326 n_new_hexes = 2;
9327 break;
9331 n_new_lines = 1;
9332 n_new_quads = 4;
9333 n_new_hexes = 4;
9334 break;
9336 n_new_lines = 6;
9337 n_new_quads = 12;
9338 n_new_hexes = 8;
9339 break;
9340 default:
9342 break;
9343 }
9344
9345 // find some space for the newly to be created
9346 // interior lines and initialize them.
9347 std::vector<
9349 new_lines(n_new_lines);
9350 for (unsigned int i = 0; i < n_new_lines; ++i)
9351 {
9352 new_lines[i] =
9353 triangulation.faces->lines
9354 .template next_free_single_object<1>(triangulation);
9355
9356 AssertIsNotUsed(new_lines[i]);
9357 new_lines[i]->set_used_flag();
9358 new_lines[i]->clear_user_flag();
9359 new_lines[i]->clear_user_data();
9360 new_lines[i]->clear_children();
9361 // interior line
9362 new_lines[i]->set_boundary_id_internal(
9364 // they inherit geometry description of the hex they
9365 // belong to
9366 new_lines[i]->set_manifold_id(hex->manifold_id());
9367 }
9368
9369 // find some space for the newly to be created
9370 // interior quads and initialize them.
9371 std::vector<
9373 new_quads(n_new_quads);
9374 for (unsigned int i = 0; i < n_new_quads; ++i)
9375 {
9376 new_quads[i] =
9377 triangulation.faces->quads
9378 .template next_free_single_object<2>(triangulation);
9379
9380 AssertIsNotUsed(new_quads[i]);
9381 new_quads[i]->set_used_flag();
9382 new_quads[i]->clear_user_flag();
9383 new_quads[i]->clear_user_data();
9384 new_quads[i]->clear_children();
9385 // interior quad
9386 new_quads[i]->set_boundary_id_internal(
9388 // they inherit geometry description of the hex they
9389 // belong to
9390 new_quads[i]->set_manifold_id(hex->manifold_id());
9391 // set all line orientation flags to true by
9392 // default, change this afterwards, if necessary
9393 for (unsigned int j = 0;
9394 j < GeometryInfo<dim>::lines_per_face;
9395 ++j)
9396 new_quads[i]->set_line_orientation(
9398 }
9399
9400 types::subdomain_id subdomainid = hex->subdomain_id();
9401
9402 // find some space for the newly to be created hexes
9403 // and initialize them.
9404 std::vector<
9406 new_hexes(n_new_hexes);
9407 for (unsigned int i = 0; i < n_new_hexes; ++i)
9408 {
9409 if (i % 2 == 0)
9410 next_unused_hex =
9411 triangulation.levels[level + 1]->cells.next_free_hex(
9412 triangulation, level + 1);
9413 else
9414 ++next_unused_hex;
9415
9416 new_hexes[i] = next_unused_hex;
9417
9418 AssertIsNotUsed(new_hexes[i]);
9419 new_hexes[i]->set_used_flag();
9420 new_hexes[i]->clear_user_flag();
9421 new_hexes[i]->clear_user_data();
9422 new_hexes[i]->clear_children();
9423 // inherit material
9424 // properties
9425 new_hexes[i]->set_material_id(hex->material_id());
9426 new_hexes[i]->set_manifold_id(hex->manifold_id());
9427 new_hexes[i]->set_subdomain_id(subdomainid);
9428
9429 // We only store the parent for every second cell. That's
9430 // because cells are created during refinement in
9431 // multiples of two, and so two successive cells always
9432 // share the same parent.
9433 if (i % 2 == 0)
9434 new_hexes[i]->set_parent(hex->index());
9435
9436 // set the face_orientation flag to true for all
9437 // faces initially, as this is the default value
9438 // which is true for all faces interior to the
9439 // hex. later on go the other way round and
9440 // reset faces that are at the boundary of the
9441 // mother cube
9442 //
9443 // the same is true for the face_flip and
9444 // face_rotation flags. however, the latter two
9445 // are set to false by default as this is the
9446 // standard value
9447 for (const unsigned int f :
9449 new_hexes[i]->set_combined_face_orientation(
9451 }
9452 // note these hexes as children to the present cell
9453 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
9454 hex->set_children(2 * i, new_hexes[2 * i]->index());
9455
9456 // we have to take into account whether the
9457 // different faces are oriented correctly or in the
9458 // opposite direction, so store that up front
9459
9460 // face_orientation
9461 const bool f_or[6] = {hex->face_orientation(0),
9462 hex->face_orientation(1),
9463 hex->face_orientation(2),
9464 hex->face_orientation(3),
9465 hex->face_orientation(4),
9466 hex->face_orientation(5)};
9467
9468 // face_flip
9469 const bool f_fl[6] = {hex->face_flip(0),
9470 hex->face_flip(1),
9471 hex->face_flip(2),
9472 hex->face_flip(3),
9473 hex->face_flip(4),
9474 hex->face_flip(5)};
9475
9476 // face_rotation
9477 const bool f_ro[6] = {hex->face_rotation(0),
9478 hex->face_rotation(1),
9479 hex->face_rotation(2),
9480 hex->face_rotation(3),
9481 hex->face_rotation(4),
9482 hex->face_rotation(5)};
9483
9484 // combined orientation
9485 const types::geometric_orientation f_co[6] = {
9486 hex->combined_face_orientation(0),
9487 hex->combined_face_orientation(1),
9488 hex->combined_face_orientation(2),
9489 hex->combined_face_orientation(3),
9490 hex->combined_face_orientation(4),
9491 hex->combined_face_orientation(5)};
9492
9493 // little helper table, indicating, whether the
9494 // child with index 0 or with index 1 can be found
9495 // at the standard origin of an anisotropically
9496 // refined quads in real orientation index 1:
9497 // (RefineCase - 1) index 2: face_flip
9498
9499 // index 3: face rotation
9500 // note: face orientation has no influence
9501 const unsigned int child_at_origin[2][2][2] = {
9502 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
9503 // face_rotation=false and true
9504 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
9505 // face_rotation=false and true
9506 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
9507 // face_rotation=false and true
9508 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
9509 // face_rotation=false and true
9510
9511 //-------------------------------------
9512 //
9513 // in the following we will do the same thing for
9514 // each refinement case: create a new vertex (if
9515 // needed), create new interior lines (if needed),
9516 // create new interior quads and afterwards build
9517 // the children hexes out of these and the existing
9518 // subfaces of the outer quads (which have been
9519 // created above). However, even if the steps are
9520 // quite similar, the actual work strongly depends
9521 // on the actual refinement case. therefore, we use
9522 // separate blocks of code for each of these cases,
9523 // which hopefully increases the readability to some
9524 // extend.
9525
9526 switch (ref_case)
9527 {
9529 {
9530 //----------------------------
9531 //
9532 // RefinementCase<dim>::cut_x
9533 //
9534 // the refined cube will look
9535 // like this:
9536 //
9537 // *----*----*
9538 // / / /|
9539 // / / / |
9540 // / / / |
9541 // *----*----* |
9542 // | | | |
9543 // | | | *
9544 // | | | /
9545 // | | | /
9546 // | | |/
9547 // *----*----*
9548 //
9549 // again, first collect some data about the
9550 // indices of the lines, with the following
9551 // numbering:
9552
9553 // face 2: front plane
9554 // (note: x,y exchanged)
9555 // *---*---*
9556 // | | |
9557 // | 0 |
9558 // | | |
9559 // *---*---*
9560 // m0
9561 // face 3: back plane
9562 // (note: x,y exchanged)
9563 // m1
9564 // *---*---*
9565 // | | |
9566 // | 1 |
9567 // | | |
9568 // *---*---*
9569 // face 4: bottom plane
9570 // *---*---*
9571 // / / /
9572 // / 2 /
9573 // / / /
9574 // *---*---*
9575 // m0
9576 // face 5: top plane
9577 // m1
9578 // *---*---*
9579 // / / /
9580 // / 3 /
9581 // / / /
9582 // *---*---*
9583
9584 // set up a list of line iterators first. from
9585 // this, construct lists of line_indices and
9586 // line orientations later on
9587 const typename Triangulation<dim, spacedim>::
9588 raw_line_iterator lines[4] = {
9589 hex->face(2)->child(0)->line(
9590 (hex->face(2)->refinement_case() ==
9592 1 :
9593 3), // 0
9594 hex->face(3)->child(0)->line(
9595 (hex->face(3)->refinement_case() ==
9597 1 :
9598 3), // 1
9599 hex->face(4)->child(0)->line(
9600 (hex->face(4)->refinement_case() ==
9602 1 :
9603 3), // 2
9604 hex->face(5)->child(0)->line(
9605 (hex->face(5)->refinement_case() ==
9607 1 :
9608 3) // 3
9609 };
9610
9611 int line_indices[4];
9612 for (unsigned int i = 0; i < 4; ++i)
9613 line_indices[i] = lines[i]->index();
9614
9615 // the orientation of lines for the inner quads
9616 // is quite tricky. as these lines are newly
9617 // created ones and thus have no parents, they
9618 // cannot inherit this property. set up an array
9619 // and fill it with the respective values
9620 types::geometric_orientation line_orientation[4]{};
9621
9622 // the middle vertex marked as m0 above is the
9623 // start vertex for lines 0 and 2 in standard
9624 // orientation, whereas m1 is the end vertex of
9625 // lines 1 and 3 in standard orientation
9626 const unsigned int middle_vertices[2] = {
9627 hex->line(2)->child(0)->vertex_index(1),
9628 hex->line(7)->child(0)->vertex_index(1)};
9629
9630 for (unsigned int i = 0; i < 4; ++i)
9631 if (lines[i]->vertex_index(i % 2) ==
9632 middle_vertices[i % 2])
9633 line_orientation[i] =
9635 else
9636 {
9637 // it must be the other way round then
9638 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9639 middle_vertices[i % 2],
9641 line_orientation[i] =
9643 }
9644
9645 // set up the new quad, line numbering is as
9646 // indicated above
9647 new_quads[0]->set_bounding_object_indices(
9648 {line_indices[0],
9649 line_indices[1],
9650 line_indices[2],
9651 line_indices[3]});
9652
9653 new_quads[0]->set_line_orientation(
9654 0, line_orientation[0]);
9655 new_quads[0]->set_line_orientation(
9656 1, line_orientation[1]);
9657 new_quads[0]->set_line_orientation(
9658 2, line_orientation[2]);
9659 new_quads[0]->set_line_orientation(
9660 3, line_orientation[3]);
9661
9662 // the quads are numbered as follows:
9663 //
9664 // planes in the interior of the old hex:
9665 //
9666 // *
9667 // /|
9668 // / | x
9669 // / | *-------* *---------*
9670 // * | | | / /
9671 // | 0 | | | / /
9672 // | * | | / /
9673 // | / *-------*y *---------*x
9674 // | /
9675 // |/
9676 // *
9677 //
9678 // children of the faces of the old hex
9679 //
9680 // *---*---* *---*---*
9681 // /| | | / / /|
9682 // / | | | / 9 / 10/ |
9683 // / | 5 | 6 | / / / |
9684 // * | | | *---*---* |
9685 // | 1 *---*---* | | | 2 *
9686 // | / / / | | | /
9687 // | / 7 / 8 / | 3 | 4 | /
9688 // |/ / / | | |/
9689 // *---*---* *---*---*
9690 //
9691 // note that we have to take care of the
9692 // orientation of faces.
9693 const int quad_indices[11] = {
9694 new_quads[0]->index(), // 0
9695
9696 hex->face(0)->index(), // 1
9697
9698 hex->face(1)->index(), // 2
9699
9700 hex->face(2)->child_index(
9701 child_at_origin[hex->face(2)->refinement_case() -
9702 1][f_fl[2]][f_ro[2]]), // 3
9703 hex->face(2)->child_index(
9704 1 -
9705 child_at_origin[hex->face(2)->refinement_case() -
9706 1][f_fl[2]][f_ro[2]]),
9707
9708 hex->face(3)->child_index(
9709 child_at_origin[hex->face(3)->refinement_case() -
9710 1][f_fl[3]][f_ro[3]]), // 5
9711 hex->face(3)->child_index(
9712 1 -
9713 child_at_origin[hex->face(3)->refinement_case() -
9714 1][f_fl[3]][f_ro[3]]),
9715
9716 hex->face(4)->child_index(
9717 child_at_origin[hex->face(4)->refinement_case() -
9718 1][f_fl[4]][f_ro[4]]), // 7
9719 hex->face(4)->child_index(
9720 1 -
9721 child_at_origin[hex->face(4)->refinement_case() -
9722 1][f_fl[4]][f_ro[4]]),
9723
9724 hex->face(5)->child_index(
9725 child_at_origin[hex->face(5)->refinement_case() -
9726 1][f_fl[5]][f_ro[5]]), // 9
9727 hex->face(5)->child_index(
9728 1 -
9729 child_at_origin[hex->face(5)->refinement_case() -
9730 1][f_fl[5]][f_ro[5]])
9731
9732 };
9733
9734 new_hexes[0]->set_bounding_object_indices(
9735 {quad_indices[1],
9736 quad_indices[0],
9737 quad_indices[3],
9738 quad_indices[5],
9739 quad_indices[7],
9740 quad_indices[9]});
9741 new_hexes[1]->set_bounding_object_indices(
9742 {quad_indices[0],
9743 quad_indices[2],
9744 quad_indices[4],
9745 quad_indices[6],
9746 quad_indices[8],
9747 quad_indices[10]});
9748 break;
9749 }
9750
9752 {
9753 //----------------------------
9754 //
9755 // RefinementCase<dim>::cut_y
9756 //
9757 // the refined cube will look like this:
9758 //
9759 // *---------*
9760 // / /|
9761 // *---------* |
9762 // / /| |
9763 // *---------* | |
9764 // | | | |
9765 // | | | *
9766 // | | |/
9767 // | | *
9768 // | |/
9769 // *---------*
9770 //
9771 // again, first collect some data about the
9772 // indices of the lines, with the following
9773 // numbering:
9774
9775 // face 0: left plane
9776 // *
9777 // /|
9778 // * |
9779 // /| |
9780 // * | |
9781 // | 0 |
9782 // | | *
9783 // | |/
9784 // | *m0
9785 // |/
9786 // *
9787 // face 1: right plane
9788 // *
9789 // /|
9790 // m1* |
9791 // /| |
9792 // * | |
9793 // | 1 |
9794 // | | *
9795 // | |/
9796 // | *
9797 // |/
9798 // *
9799 // face 4: bottom plane
9800 // *-------*
9801 // / /
9802 // m0*---2---*
9803 // / /
9804 // *-------*
9805 // face 5: top plane
9806 // *-------*
9807 // / /
9808 // *---3---*m1
9809 // / /
9810 // *-------*
9811
9812 // set up a list of line iterators first. from
9813 // this, construct lists of line_indices and
9814 // line orientations later on
9815 const typename Triangulation<dim, spacedim>::
9816 raw_line_iterator lines[4] = {
9817 hex->face(0)->child(0)->line(
9818 (hex->face(0)->refinement_case() ==
9820 1 :
9821 3), // 0
9822 hex->face(1)->child(0)->line(
9823 (hex->face(1)->refinement_case() ==
9825 1 :
9826 3), // 1
9827 hex->face(4)->child(0)->line(
9828 (hex->face(4)->refinement_case() ==
9830 1 :
9831 3), // 2
9832 hex->face(5)->child(0)->line(
9833 (hex->face(5)->refinement_case() ==
9835 1 :
9836 3) // 3
9837 };
9838
9839 int line_indices[4];
9840 for (unsigned int i = 0; i < 4; ++i)
9841 line_indices[i] = lines[i]->index();
9842
9843 // the orientation of lines for the inner quads
9844 // is quite tricky. as these lines are newly
9845 // created ones and thus have no parents, they
9846 // cannot inherit this property. set up an array
9847 // and fill it with the respective values
9848 types::geometric_orientation line_orientation[4]{};
9849
9850 // the middle vertex marked as m0 above is the
9851 // start vertex for lines 0 and 2 in standard
9852 // orientation, whereas m1 is the end vertex of
9853 // lines 1 and 3 in standard orientation
9854 const unsigned int middle_vertices[2] = {
9855 hex->line(0)->child(0)->vertex_index(1),
9856 hex->line(5)->child(0)->vertex_index(1)};
9857
9858 for (unsigned int i = 0; i < 4; ++i)
9859 if (lines[i]->vertex_index(i % 2) ==
9860 middle_vertices[i % 2])
9861 line_orientation[i] =
9863 else
9864 {
9865 // it must be the other way round then
9866 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9867 middle_vertices[i % 2],
9869 line_orientation[i] =
9871 }
9872
9873 // set up the new quad, line numbering is as
9874 // indicated above
9875 new_quads[0]->set_bounding_object_indices(
9876 {line_indices[2],
9877 line_indices[3],
9878 line_indices[0],
9879 line_indices[1]});
9880
9881 new_quads[0]->set_line_orientation(
9882 0, line_orientation[2]);
9883 new_quads[0]->set_line_orientation(
9884 1, line_orientation[3]);
9885 new_quads[0]->set_line_orientation(
9886 2, line_orientation[0]);
9887 new_quads[0]->set_line_orientation(
9888 3, line_orientation[1]);
9889
9890 // the quads are numbered as follows:
9891 //
9892 // planes in the interior of the old hex:
9893 //
9894 // *
9895 // /|
9896 // / | x
9897 // / | *-------* *---------*
9898 // * | | | / /
9899 // | | | 0 | / /
9900 // | * | | / /
9901 // | / *-------*y *---------*x
9902 // | /
9903 // |/
9904 // *
9905 //
9906 // children of the faces of the old hex
9907 //
9908 // *-------* *-------*
9909 // /| | / 10 /|
9910 // * | | *-------* |
9911 // /| | 6 | / 9 /| |
9912 // * |2| | *-------* |4|
9913 // | | *-------* | | | *
9914 // |1|/ 8 / | |3|/
9915 // | *-------* | 5 | *
9916 // |/ 7 / | |/
9917 // *-------* *-------*
9918 //
9919 // note that we have to take care of the
9920 // orientation of faces.
9921 const int quad_indices[11] = {
9922 new_quads[0]->index(), // 0
9923
9924 hex->face(0)->child_index(
9925 child_at_origin[hex->face(0)->refinement_case() -
9926 1][f_fl[0]][f_ro[0]]), // 1
9927 hex->face(0)->child_index(
9928 1 -
9929 child_at_origin[hex->face(0)->refinement_case() -
9930 1][f_fl[0]][f_ro[0]]),
9931
9932 hex->face(1)->child_index(
9933 child_at_origin[hex->face(1)->refinement_case() -
9934 1][f_fl[1]][f_ro[1]]), // 3
9935 hex->face(1)->child_index(
9936 1 -
9937 child_at_origin[hex->face(1)->refinement_case() -
9938 1][f_fl[1]][f_ro[1]]),
9939
9940 hex->face(2)->index(), // 5
9941
9942 hex->face(3)->index(), // 6
9943
9944 hex->face(4)->child_index(
9945 child_at_origin[hex->face(4)->refinement_case() -
9946 1][f_fl[4]][f_ro[4]]), // 7
9947 hex->face(4)->child_index(
9948 1 -
9949 child_at_origin[hex->face(4)->refinement_case() -
9950 1][f_fl[4]][f_ro[4]]),
9951
9952 hex->face(5)->child_index(
9953 child_at_origin[hex->face(5)->refinement_case() -
9954 1][f_fl[5]][f_ro[5]]), // 9
9955 hex->face(5)->child_index(
9956 1 -
9957 child_at_origin[hex->face(5)->refinement_case() -
9958 1][f_fl[5]][f_ro[5]])
9959
9960 };
9961
9962 new_hexes[0]->set_bounding_object_indices(
9963 {quad_indices[1],
9964 quad_indices[3],
9965 quad_indices[5],
9966 quad_indices[0],
9967 quad_indices[7],
9968 quad_indices[9]});
9969 new_hexes[1]->set_bounding_object_indices(
9970 {quad_indices[2],
9971 quad_indices[4],
9972 quad_indices[0],
9973 quad_indices[6],
9974 quad_indices[8],
9975 quad_indices[10]});
9976 break;
9977 }
9978
9980 {
9981 //----------------------------
9982 //
9983 // RefinementCase<dim>::cut_z
9984 //
9985 // the refined cube will look like this:
9986 //
9987 // *---------*
9988 // / /|
9989 // / / |
9990 // / / *
9991 // *---------* /|
9992 // | | / |
9993 // | |/ *
9994 // *---------* /
9995 // | | /
9996 // | |/
9997 // *---------*
9998 //
9999 // again, first collect some data about the
10000 // indices of the lines, with the following
10001 // numbering:
10002
10003 // face 0: left plane
10004 // *
10005 // /|
10006 // / |
10007 // / *
10008 // * /|
10009 // | 0 |
10010 // |/ *
10011 // m0* /
10012 // | /
10013 // |/
10014 // *
10015 // face 1: right plane
10016 // *
10017 // /|
10018 // / |
10019 // / *m1
10020 // * /|
10021 // | 1 |
10022 // |/ *
10023 // * /
10024 // | /
10025 // |/
10026 // *
10027 // face 2: front plane
10028 // (note: x,y exchanged)
10029 // *-------*
10030 // | |
10031 // m0*---2---*
10032 // | |
10033 // *-------*
10034 // face 3: back plane
10035 // (note: x,y exchanged)
10036 // *-------*
10037 // | |
10038 // *---3---*m1
10039 // | |
10040 // *-------*
10041
10042 // set up a list of line iterators first. from
10043 // this, construct lists of line_indices and
10044 // line orientations later on
10045 const typename Triangulation<dim, spacedim>::
10046 raw_line_iterator lines[4] = {
10047 hex->face(0)->child(0)->line(
10048 (hex->face(0)->refinement_case() ==
10050 1 :
10051 3), // 0
10052 hex->face(1)->child(0)->line(
10053 (hex->face(1)->refinement_case() ==
10055 1 :
10056 3), // 1
10057 hex->face(2)->child(0)->line(
10058 (hex->face(2)->refinement_case() ==
10060 1 :
10061 3), // 2
10062 hex->face(3)->child(0)->line(
10063 (hex->face(3)->refinement_case() ==
10065 1 :
10066 3) // 3
10067 };
10068
10069 int line_indices[4];
10070 for (unsigned int i = 0; i < 4; ++i)
10071 line_indices[i] = lines[i]->index();
10072
10073 // the orientation of lines for the inner quads
10074 // is quite tricky. as these lines are newly
10075 // created ones and thus have no parents, they
10076 // cannot inherit this property. set up an array
10077 // and fill it with the respective values
10078 types::geometric_orientation line_orientation[4]{};
10079
10080 // the middle vertex marked as m0 above is the
10081 // start vertex for lines 0 and 2 in standard
10082 // orientation, whereas m1 is the end vertex of
10083 // lines 1 and 3 in standard orientation
10084 const unsigned int middle_vertices[2] = {
10085 middle_vertex_index<dim, spacedim>(hex->line(8)),
10086 middle_vertex_index<dim, spacedim>(hex->line(11))};
10087
10088 for (unsigned int i = 0; i < 4; ++i)
10089 if (lines[i]->vertex_index(i % 2) ==
10090 middle_vertices[i % 2])
10091 line_orientation[i] =
10093 else
10094 {
10095 // it must be the other way round then
10096 Assert(lines[i]->vertex_index((i + 1) % 2) ==
10097 middle_vertices[i % 2],
10099 line_orientation[i] =
10101 }
10102
10103 // set up the new quad, line numbering is as
10104 // indicated above
10105 new_quads[0]->set_bounding_object_indices(
10106 {line_indices[0],
10107 line_indices[1],
10108 line_indices[2],
10109 line_indices[3]});
10110
10111 new_quads[0]->set_line_orientation(
10112 0, line_orientation[0]);
10113 new_quads[0]->set_line_orientation(
10114 1, line_orientation[1]);
10115 new_quads[0]->set_line_orientation(
10116 2, line_orientation[2]);
10117 new_quads[0]->set_line_orientation(
10118 3, line_orientation[3]);
10119
10120 // the quads are numbered as follows:
10121 //
10122 // planes in the interior of the old hex:
10123 //
10124 // *
10125 // /|
10126 // / | x
10127 // / | *-------* *---------*
10128 // * | | | / /
10129 // | | | | / 0 /
10130 // | * | | / /
10131 // | / *-------*y *---------*x
10132 // | /
10133 // |/
10134 // *
10135 //
10136 // children of the faces of the old hex
10137 //
10138 // *---*---* *-------*
10139 // /| 8 | / /|
10140 // / | | / 10 / |
10141 // / *-------* / / *
10142 // * 2/| | *-------* 4/|
10143 // | / | 7 | | 6 | / |
10144 // |/1 *-------* | |/3 *
10145 // * / / *-------* /
10146 // | / 9 / | | /
10147 // |/ / | 5 |/
10148 // *-------* *---*---*
10149 //
10150 // note that we have to take care of the
10151 // orientation of faces.
10152 const int quad_indices[11] = {
10153 new_quads[0]->index(), // 0
10154
10155 hex->face(0)->child_index(
10156 child_at_origin[hex->face(0)->refinement_case() -
10157 1][f_fl[0]][f_ro[0]]), // 1
10158 hex->face(0)->child_index(
10159 1 -
10160 child_at_origin[hex->face(0)->refinement_case() -
10161 1][f_fl[0]][f_ro[0]]),
10162
10163 hex->face(1)->child_index(
10164 child_at_origin[hex->face(1)->refinement_case() -
10165 1][f_fl[1]][f_ro[1]]), // 3
10166 hex->face(1)->child_index(
10167 1 -
10168 child_at_origin[hex->face(1)->refinement_case() -
10169 1][f_fl[1]][f_ro[1]]),
10170
10171 hex->face(2)->child_index(
10172 child_at_origin[hex->face(2)->refinement_case() -
10173 1][f_fl[2]][f_ro[2]]), // 5
10174 hex->face(2)->child_index(
10175 1 -
10176 child_at_origin[hex->face(2)->refinement_case() -
10177 1][f_fl[2]][f_ro[2]]),
10178
10179 hex->face(3)->child_index(
10180 child_at_origin[hex->face(3)->refinement_case() -
10181 1][f_fl[3]][f_ro[3]]), // 7
10182 hex->face(3)->child_index(
10183 1 -
10184 child_at_origin[hex->face(3)->refinement_case() -
10185 1][f_fl[3]][f_ro[3]]),
10186
10187 hex->face(4)->index(), // 9
10188
10189 hex->face(5)->index() // 10
10190 };
10191
10192 new_hexes[0]->set_bounding_object_indices(
10193 {quad_indices[1],
10194 quad_indices[3],
10195 quad_indices[5],
10196 quad_indices[7],
10197 quad_indices[9],
10198 quad_indices[0]});
10199 new_hexes[1]->set_bounding_object_indices(
10200 {quad_indices[2],
10201 quad_indices[4],
10202 quad_indices[6],
10203 quad_indices[8],
10204 quad_indices[0],
10205 quad_indices[10]});
10206 break;
10207 }
10208
10210 {
10211 //----------------------------
10212 //
10213 // RefinementCase<dim>::cut_xy
10214 //
10215 // the refined cube will look like this:
10216 //
10217 // *----*----*
10218 // / / /|
10219 // *----*----* |
10220 // / / /| |
10221 // *----*----* | |
10222 // | | | | |
10223 // | | | | *
10224 // | | | |/
10225 // | | | *
10226 // | | |/
10227 // *----*----*
10228 //
10229
10230 // first, create the new internal line
10231 new_lines[0]->set_bounding_object_indices(
10232 {middle_vertex_index<dim, spacedim>(hex->face(4)),
10233 middle_vertex_index<dim, spacedim>(hex->face(5))});
10234
10235 // again, first collect some data about the
10236 // indices of the lines, with the following
10237 // numbering:
10238
10239 // face 0: left plane
10240 // *
10241 // /|
10242 // * |
10243 // /| |
10244 // * | |
10245 // | 0 |
10246 // | | *
10247 // | |/
10248 // | *
10249 // |/
10250 // *
10251 // face 1: right plane
10252 // *
10253 // /|
10254 // * |
10255 // /| |
10256 // * | |
10257 // | 1 |
10258 // | | *
10259 // | |/
10260 // | *
10261 // |/
10262 // *
10263 // face 2: front plane
10264 // (note: x,y exchanged)
10265 // *---*---*
10266 // | | |
10267 // | 2 |
10268 // | | |
10269 // *-------*
10270 // face 3: back plane
10271 // (note: x,y exchanged)
10272 // *---*---*
10273 // | | |
10274 // | 3 |
10275 // | | |
10276 // *---*---*
10277 // face 4: bottom plane
10278 // *---*---*
10279 // / 5 /
10280 // *-6-*-7-*
10281 // / 4 /
10282 // *---*---*
10283 // face 5: top plane
10284 // *---*---*
10285 // / 9 /
10286 // *10-*-11*
10287 // / 8 /
10288 // *---*---*
10289 // middle planes
10290 // *-------* *---*---*
10291 // / / | | |
10292 // / / | 12 |
10293 // / / | | |
10294 // *-------* *---*---*
10295
10296 // set up a list of line iterators first. from
10297 // this, construct lists of line_indices and
10298 // line orientations later on
10299 const typename Triangulation<
10300 dim,
10301 spacedim>::raw_line_iterator lines[13] = {
10302 hex->face(0)->child(0)->line(
10303 (hex->face(0)->refinement_case() ==
10305 1 :
10306 3), // 0
10307 hex->face(1)->child(0)->line(
10308 (hex->face(1)->refinement_case() ==
10310 1 :
10311 3), // 1
10312 hex->face(2)->child(0)->line(
10313 (hex->face(2)->refinement_case() ==
10315 1 :
10316 3), // 2
10317 hex->face(3)->child(0)->line(
10318 (hex->face(3)->refinement_case() ==
10320 1 :
10321 3), // 3
10322
10323 hex->face(4)
10324 ->isotropic_child(
10326 0, f_or[4], f_fl[4], f_ro[4]))
10327 ->line(
10329 1, f_or[4], f_fl[4], f_ro[4])), // 4
10330 hex->face(4)
10331 ->isotropic_child(
10333 3, f_or[4], f_fl[4], f_ro[4]))
10334 ->line(
10336 0, f_or[4], f_fl[4], f_ro[4])), // 5
10337 hex->face(4)
10338 ->isotropic_child(
10340 0, f_or[4], f_fl[4], f_ro[4]))
10341 ->line(
10343 3, f_or[4], f_fl[4], f_ro[4])), // 6
10344 hex->face(4)
10345 ->isotropic_child(
10347 3, f_or[4], f_fl[4], f_ro[4]))
10348 ->line(
10350 2, f_or[4], f_fl[4], f_ro[4])), // 7
10351
10352 hex->face(5)
10353 ->isotropic_child(
10355 0, f_or[5], f_fl[5], f_ro[5]))
10356 ->line(
10358 1, f_or[5], f_fl[5], f_ro[5])), // 8
10359 hex->face(5)
10360 ->isotropic_child(
10362 3, f_or[5], f_fl[5], f_ro[5]))
10363 ->line(
10365 0, f_or[5], f_fl[5], f_ro[5])), // 9
10366 hex->face(5)
10367 ->isotropic_child(
10369 0, f_or[5], f_fl[5], f_ro[5]))
10370 ->line(
10372 3, f_or[5], f_fl[5], f_ro[5])), // 10
10373 hex->face(5)
10374 ->isotropic_child(
10376 3, f_or[5], f_fl[5], f_ro[5]))
10377 ->line(
10379 2, f_or[5], f_fl[5], f_ro[5])), // 11
10380
10381 new_lines[0] // 12
10382 };
10383
10384 int line_indices[13];
10385 for (unsigned int i = 0; i < 13; ++i)
10386 line_indices[i] = lines[i]->index();
10387
10388 // the orientation of lines for the inner quads
10389 // is quite tricky. as these lines are newly
10390 // created ones and thus have no parents, they
10391 // cannot inherit this property. set up an array
10392 // and fill it with the respective values
10393 types::geometric_orientation line_orientation[13]{};
10394
10395 // the middle vertices of the lines of our
10396 // bottom face
10397 const unsigned int middle_vertices[4] = {
10398 hex->line(0)->child(0)->vertex_index(1),
10399 hex->line(1)->child(0)->vertex_index(1),
10400 hex->line(2)->child(0)->vertex_index(1),
10401 hex->line(3)->child(0)->vertex_index(1),
10402 };
10403
10404 // note: for lines 0 to 3 the orientation of the
10405 // line is 'true', if vertex 0 is on the bottom
10406 // face
10407 for (unsigned int i = 0; i < 4; ++i)
10408 if (lines[i]->vertex_index(0) == middle_vertices[i])
10409 line_orientation[i] =
10411 else
10412 {
10413 // it must be the other way round then
10414 Assert(lines[i]->vertex_index(1) ==
10415 middle_vertices[i],
10417 line_orientation[i] =
10419 }
10420
10421 // note: for lines 4 to 11 (inner lines of the
10422 // outer quads) the following holds: the second
10423 // vertex of the even lines in standard
10424 // orientation is the vertex in the middle of
10425 // the quad, whereas for odd lines the first
10426 // vertex is the same middle vertex.
10427 for (unsigned int i = 4; i < 12; ++i)
10428 if (lines[i]->vertex_index((i + 1) % 2) ==
10429 middle_vertex_index<dim, spacedim>(
10430 hex->face(3 + i / 4)))
10431 line_orientation[i] =
10433 else
10434 {
10435 // it must be the other way round then
10436 Assert(lines[i]->vertex_index(i % 2) ==
10437 (middle_vertex_index<dim, spacedim>(
10438 hex->face(3 + i / 4))),
10440 line_orientation[i] =
10442 }
10443 // for the last line the line orientation is
10444 // always true, since it was just constructed
10445 // that way
10446 line_orientation[12] =
10448
10449 // set up the 4 quads, numbered as follows (left
10450 // quad numbering, right line numbering
10451 // extracted from above)
10452 //
10453 // * *
10454 // /| 9|
10455 // * | * |
10456 // y/| | 8| 3
10457 // * |1| * | |
10458 // | | |x | 12|
10459 // |0| * | | *
10460 // | |/ 2 |5
10461 // | * | *
10462 // |/ |4
10463 // * *
10464 //
10465 // x
10466 // *---*---* *10-*-11*
10467 // | | | | | |
10468 // | 2 | 3 | 0 12 1
10469 // | | | | | |
10470 // *---*---*y *-6-*-7-*
10471
10472 new_quads[0]->set_bounding_object_indices(
10473 {line_indices[2],
10474 line_indices[12],
10475 line_indices[4],
10476 line_indices[8]});
10477 new_quads[1]->set_bounding_object_indices(
10478 {line_indices[12],
10479 line_indices[3],
10480 line_indices[5],
10481 line_indices[9]});
10482 new_quads[2]->set_bounding_object_indices(
10483 {line_indices[6],
10484 line_indices[10],
10485 line_indices[0],
10486 line_indices[12]});
10487 new_quads[3]->set_bounding_object_indices(
10488 {line_indices[7],
10489 line_indices[11],
10490 line_indices[12],
10491 line_indices[1]});
10492
10493 new_quads[0]->set_line_orientation(
10494 0, line_orientation[2]);
10495 new_quads[0]->set_line_orientation(
10496 2, line_orientation[4]);
10497 new_quads[0]->set_line_orientation(
10498 3, line_orientation[8]);
10499
10500 new_quads[1]->set_line_orientation(
10501 1, line_orientation[3]);
10502 new_quads[1]->set_line_orientation(
10503 2, line_orientation[5]);
10504 new_quads[1]->set_line_orientation(
10505 3, line_orientation[9]);
10506
10507 new_quads[2]->set_line_orientation(
10508 0, line_orientation[6]);
10509 new_quads[2]->set_line_orientation(
10510 1, line_orientation[10]);
10511 new_quads[2]->set_line_orientation(
10512 2, line_orientation[0]);
10513
10514 new_quads[3]->set_line_orientation(
10515 0, line_orientation[7]);
10516 new_quads[3]->set_line_orientation(
10517 1, line_orientation[11]);
10518 new_quads[3]->set_line_orientation(
10519 3, line_orientation[1]);
10520
10521 // the quads are numbered as follows:
10522 //
10523 // planes in the interior of the old hex:
10524 //
10525 // *
10526 // /|
10527 // * | x
10528 // /| | *---*---* *---------*
10529 // * |1| | | | / /
10530 // | | | | 2 | 3 | / /
10531 // |0| * | | | / /
10532 // | |/ *---*---*y *---------*x
10533 // | *
10534 // |/
10535 // *
10536 //
10537 // children of the faces of the old hex
10538 //
10539 // *---*---* *---*---*
10540 // /| | | /18 / 19/|
10541 // * |10 | 11| /---/---* |
10542 // /| | | | /16 / 17/| |
10543 // * |5| | | *---*---* |7|
10544 // | | *---*---* | | | | *
10545 // |4|/14 / 15/ | | |6|/
10546 // | *---/---/ | 8 | 9 | *
10547 // |/12 / 13/ | | |/
10548 // *---*---* *---*---*
10549 //
10550 // note that we have to take care of the
10551 // orientation of faces.
10552 const int quad_indices[20] = {
10553 new_quads[0]->index(), // 0
10554 new_quads[1]->index(),
10555 new_quads[2]->index(),
10556 new_quads[3]->index(),
10557
10558 hex->face(0)->child_index(
10559 child_at_origin[hex->face(0)->refinement_case() -
10560 1][f_fl[0]][f_ro[0]]), // 4
10561 hex->face(0)->child_index(
10562 1 -
10563 child_at_origin[hex->face(0)->refinement_case() -
10564 1][f_fl[0]][f_ro[0]]),
10565
10566 hex->face(1)->child_index(
10567 child_at_origin[hex->face(1)->refinement_case() -
10568 1][f_fl[1]][f_ro[1]]), // 6
10569 hex->face(1)->child_index(
10570 1 -
10571 child_at_origin[hex->face(1)->refinement_case() -
10572 1][f_fl[1]][f_ro[1]]),
10573
10574 hex->face(2)->child_index(
10575 child_at_origin[hex->face(2)->refinement_case() -
10576 1][f_fl[2]][f_ro[2]]), // 8
10577 hex->face(2)->child_index(
10578 1 -
10579 child_at_origin[hex->face(2)->refinement_case() -
10580 1][f_fl[2]][f_ro[2]]),
10581
10582 hex->face(3)->child_index(
10583 child_at_origin[hex->face(3)->refinement_case() -
10584 1][f_fl[3]][f_ro[3]]), // 10
10585 hex->face(3)->child_index(
10586 1 -
10587 child_at_origin[hex->face(3)->refinement_case() -
10588 1][f_fl[3]][f_ro[3]]),
10589
10590 hex->face(4)->isotropic_child_index(
10592 0, f_or[4], f_fl[4], f_ro[4])), // 12
10593 hex->face(4)->isotropic_child_index(
10595 1, f_or[4], f_fl[4], f_ro[4])),
10596 hex->face(4)->isotropic_child_index(
10598 2, f_or[4], f_fl[4], f_ro[4])),
10599 hex->face(4)->isotropic_child_index(
10601 3, f_or[4], f_fl[4], f_ro[4])),
10602
10603 hex->face(5)->isotropic_child_index(
10605 0, f_or[5], f_fl[5], f_ro[5])), // 16
10606 hex->face(5)->isotropic_child_index(
10608 1, f_or[5], f_fl[5], f_ro[5])),
10609 hex->face(5)->isotropic_child_index(
10611 2, f_or[5], f_fl[5], f_ro[5])),
10612 hex->face(5)->isotropic_child_index(
10614 3, f_or[5], f_fl[5], f_ro[5]))};
10615
10616 new_hexes[0]->set_bounding_object_indices(
10617 {quad_indices[4],
10618 quad_indices[0],
10619 quad_indices[8],
10620 quad_indices[2],
10621 quad_indices[12],
10622 quad_indices[16]});
10623 new_hexes[1]->set_bounding_object_indices(
10624 {quad_indices[0],
10625 quad_indices[6],
10626 quad_indices[9],
10627 quad_indices[3],
10628 quad_indices[13],
10629 quad_indices[17]});
10630 new_hexes[2]->set_bounding_object_indices(
10631 {quad_indices[5],
10632 quad_indices[1],
10633 quad_indices[2],
10634 quad_indices[10],
10635 quad_indices[14],
10636 quad_indices[18]});
10637 new_hexes[3]->set_bounding_object_indices(
10638 {quad_indices[1],
10639 quad_indices[7],
10640 quad_indices[3],
10641 quad_indices[11],
10642 quad_indices[15],
10643 quad_indices[19]});
10644 break;
10645 }
10646
10648 {
10649 //----------------------------
10650 //
10651 // RefinementCase<dim>::cut_xz
10652 //
10653 // the refined cube will look like this:
10654 //
10655 // *----*----*
10656 // / / /|
10657 // / / / |
10658 // / / / *
10659 // *----*----* /|
10660 // | | | / |
10661 // | | |/ *
10662 // *----*----* /
10663 // | | | /
10664 // | | |/
10665 // *----*----*
10666 //
10667
10668 // first, create the new internal line
10669 new_lines[0]->set_bounding_object_indices(
10670 {middle_vertex_index<dim, spacedim>(hex->face(2)),
10671 middle_vertex_index<dim, spacedim>(hex->face(3))});
10672
10673 // again, first collect some data about the
10674 // indices of the lines, with the following
10675 // numbering:
10676
10677 // face 0: left plane
10678 // *
10679 // /|
10680 // / |
10681 // / *
10682 // * /|
10683 // | 0 |
10684 // |/ *
10685 // * /
10686 // | /
10687 // |/
10688 // *
10689 // face 1: right plane
10690 // *
10691 // /|
10692 // / |
10693 // / *
10694 // * /|
10695 // | 1 |
10696 // |/ *
10697 // * /
10698 // | /
10699 // |/
10700 // *
10701 // face 2: front plane
10702 // (note: x,y exchanged)
10703 // *---*---*
10704 // | 5 |
10705 // *-6-*-7-*
10706 // | 4 |
10707 // *---*---*
10708 // face 3: back plane
10709 // (note: x,y exchanged)
10710 // *---*---*
10711 // | 9 |
10712 // *10-*-11*
10713 // | 8 |
10714 // *---*---*
10715 // face 4: bottom plane
10716 // *---*---*
10717 // / / /
10718 // / 2 /
10719 // / / /
10720 // *---*---*
10721 // face 5: top plane
10722 // *---*---*
10723 // / / /
10724 // / 3 /
10725 // / / /
10726 // *---*---*
10727 // middle planes
10728 // *---*---* *-------*
10729 // / / / | |
10730 // / 12 / | |
10731 // / / / | |
10732 // *---*---* *-------*
10733
10734 // set up a list of line iterators first. from
10735 // this, construct lists of line_indices and
10736 // line orientations later on
10737 const typename Triangulation<
10738 dim,
10739 spacedim>::raw_line_iterator lines[13] = {
10740 hex->face(0)->child(0)->line(
10741 (hex->face(0)->refinement_case() ==
10743 1 :
10744 3), // 0
10745 hex->face(1)->child(0)->line(
10746 (hex->face(1)->refinement_case() ==
10748 1 :
10749 3), // 1
10750 hex->face(4)->child(0)->line(
10751 (hex->face(4)->refinement_case() ==
10753 1 :
10754 3), // 2
10755 hex->face(5)->child(0)->line(
10756 (hex->face(5)->refinement_case() ==
10758 1 :
10759 3), // 3
10760
10761 hex->face(2)
10762 ->isotropic_child(
10764 0, f_or[2], f_fl[2], f_ro[2]))
10765 ->line(
10767 3, f_or[2], f_fl[2], f_ro[2])), // 4
10768 hex->face(2)
10769 ->isotropic_child(
10771 3, f_or[2], f_fl[2], f_ro[2]))
10772 ->line(
10774 2, f_or[2], f_fl[2], f_ro[2])), // 5
10775 hex->face(2)
10776 ->isotropic_child(
10778 0, f_or[2], f_fl[2], f_ro[2]))
10779 ->line(
10781 1, f_or[2], f_fl[2], f_ro[2])), // 6
10782 hex->face(2)
10783 ->isotropic_child(
10785 3, f_or[2], f_fl[2], f_ro[2]))
10786 ->line(
10788 0, f_or[2], f_fl[2], f_ro[2])), // 7
10789
10790 hex->face(3)
10791 ->isotropic_child(
10793 0, f_or[3], f_fl[3], f_ro[3]))
10794 ->line(
10796 3, f_or[3], f_fl[3], f_ro[3])), // 8
10797 hex->face(3)
10798 ->isotropic_child(
10800 3, f_or[3], f_fl[3], f_ro[3]))
10801 ->line(
10803 2, f_or[3], f_fl[3], f_ro[3])), // 9
10804 hex->face(3)
10805 ->isotropic_child(
10807 0, f_or[3], f_fl[3], f_ro[3]))
10808 ->line(
10810 1, f_or[3], f_fl[3], f_ro[3])), // 10
10811 hex->face(3)
10812 ->isotropic_child(
10814 3, f_or[3], f_fl[3], f_ro[3]))
10815 ->line(
10817 0, f_or[3], f_fl[3], f_ro[3])), // 11
10818
10819 new_lines[0] // 12
10820 };
10821
10822 int line_indices[13];
10823 for (unsigned int i = 0; i < 13; ++i)
10824 line_indices[i] = lines[i]->index();
10825
10826 // the orientation of lines for the inner quads
10827 // is quite tricky. as these lines are newly
10828 // created ones and thus have no parents, they
10829 // cannot inherit this property. set up an array
10830 // and fill it with the respective values
10831 types::geometric_orientation line_orientation[13]{};
10832
10833 // the middle vertices of the
10834 // lines of our front face
10835 const unsigned int middle_vertices[4] = {
10836 hex->line(8)->child(0)->vertex_index(1),
10837 hex->line(9)->child(0)->vertex_index(1),
10838 hex->line(2)->child(0)->vertex_index(1),
10839 hex->line(6)->child(0)->vertex_index(1),
10840 };
10841
10842 // note: for lines 0 to 3 the orientation of the
10843 // line is 'true', if vertex 0 is on the front
10844 for (unsigned int i = 0; i < 4; ++i)
10845 if (lines[i]->vertex_index(0) == middle_vertices[i])
10846 line_orientation[i] =
10848 else
10849 {
10850 // it must be the other way round then
10851 Assert(lines[i]->vertex_index(1) ==
10852 middle_vertices[i],
10854 line_orientation[i] =
10856 }
10857
10858 // note: for lines 4 to 11 (inner lines of the
10859 // outer quads) the following holds: the second
10860 // vertex of the even lines in standard
10861 // orientation is the vertex in the middle of
10862 // the quad, whereas for odd lines the first
10863 // vertex is the same middle vertex.
10864 for (unsigned int i = 4; i < 12; ++i)
10865 if (lines[i]->vertex_index((i + 1) % 2) ==
10866 middle_vertex_index<dim, spacedim>(
10867 hex->face(1 + i / 4)))
10868 line_orientation[i] =
10870 else
10871 {
10872 // it must be the other way
10873 // round then
10874 Assert(lines[i]->vertex_index(i % 2) ==
10875 (middle_vertex_index<dim, spacedim>(
10876 hex->face(1 + i / 4))),
10878 line_orientation[i] =
10880 }
10881 // for the last line the line orientation is
10882 // always true, since it was just constructed
10883 // that way
10884 line_orientation[12] =
10886
10887 // set up the 4 quads, numbered as follows (left
10888 // quad numbering, right line numbering
10889 // extracted from above), the drawings denote
10890 // middle planes
10891 //
10892 // * *
10893 // /| /|
10894 // / | 3 9
10895 // y/ * / *
10896 // * 3/| * /|
10897 // | / |x 5 12|8
10898 // |/ * |/ *
10899 // * 2/ * /
10900 // | / 4 2
10901 // |/ |/
10902 // * *
10903 //
10904 // y
10905 // *----*----* *-10-*-11-*
10906 // / / / / / /
10907 // / 0 / 1 / 0 12 1
10908 // / / / / / /
10909 // *----*----*x *--6-*--7-*
10910
10911 new_quads[0]->set_bounding_object_indices(
10912 {line_indices[0],
10913 line_indices[12],
10914 line_indices[6],
10915 line_indices[10]});
10916 new_quads[1]->set_bounding_object_indices(
10917 {line_indices[12],
10918 line_indices[1],
10919 line_indices[7],
10920 line_indices[11]});
10921 new_quads[2]->set_bounding_object_indices(
10922 {line_indices[4],
10923 line_indices[8],
10924 line_indices[2],
10925 line_indices[12]});
10926 new_quads[3]->set_bounding_object_indices(
10927 {line_indices[5],
10928 line_indices[9],
10929 line_indices[12],
10930 line_indices[3]});
10931
10932 new_quads[0]->set_line_orientation(
10933 0, line_orientation[0]);
10934 new_quads[0]->set_line_orientation(
10935 2, line_orientation[6]);
10936 new_quads[0]->set_line_orientation(
10937 3, line_orientation[10]);
10938
10939 new_quads[1]->set_line_orientation(
10940 1, line_orientation[1]);
10941 new_quads[1]->set_line_orientation(
10942 2, line_orientation[7]);
10943 new_quads[1]->set_line_orientation(
10944 3, line_orientation[11]);
10945
10946 new_quads[2]->set_line_orientation(
10947 0, line_orientation[4]);
10948 new_quads[2]->set_line_orientation(
10949 1, line_orientation[8]);
10950 new_quads[2]->set_line_orientation(
10951 2, line_orientation[2]);
10952
10953 new_quads[3]->set_line_orientation(
10954 0, line_orientation[5]);
10955 new_quads[3]->set_line_orientation(
10956 1, line_orientation[9]);
10957 new_quads[3]->set_line_orientation(
10958 3, line_orientation[3]);
10959
10960 // the quads are numbered as follows:
10961 //
10962 // planes in the interior of the old hex:
10963 //
10964 // *
10965 // /|
10966 // / | x
10967 // /3 * *-------* *----*----*
10968 // * /| | | / / /
10969 // | / | | | / 0 / 1 /
10970 // |/ * | | / / /
10971 // * 2/ *-------*y *----*----*x
10972 // | /
10973 // |/
10974 // *
10975 //
10976 // children of the faces
10977 // of the old hex
10978 // *---*---* *---*---*
10979 // /|13 | 15| / / /|
10980 // / | | | /18 / 19/ |
10981 // / *---*---* / / / *
10982 // * 5/| | | *---*---* 7/|
10983 // | / |12 | 14| | 9 | 11| / |
10984 // |/4 *---*---* | | |/6 *
10985 // * / / / *---*---* /
10986 // | /16 / 17/ | | | /
10987 // |/ / / | 8 | 10|/
10988 // *---*---* *---*---*
10989 //
10990 // note that we have to take care of the
10991 // orientation of faces.
10992 const int quad_indices[20] = {
10993 new_quads[0]->index(), // 0
10994 new_quads[1]->index(),
10995 new_quads[2]->index(),
10996 new_quads[3]->index(),
10997
10998 hex->face(0)->child_index(
10999 child_at_origin[hex->face(0)->refinement_case() -
11000 1][f_fl[0]][f_ro[0]]), // 4
11001 hex->face(0)->child_index(
11002 1 -
11003 child_at_origin[hex->face(0)->refinement_case() -
11004 1][f_fl[0]][f_ro[0]]),
11005
11006 hex->face(1)->child_index(
11007 child_at_origin[hex->face(1)->refinement_case() -
11008 1][f_fl[1]][f_ro[1]]), // 6
11009 hex->face(1)->child_index(
11010 1 -
11011 child_at_origin[hex->face(1)->refinement_case() -
11012 1][f_fl[1]][f_ro[1]]),
11013
11014 hex->face(2)->isotropic_child_index(
11016 0, f_or[2], f_fl[2], f_ro[2])), // 8
11017 hex->face(2)->isotropic_child_index(
11019 1, f_or[2], f_fl[2], f_ro[2])),
11020 hex->face(2)->isotropic_child_index(
11022 2, f_or[2], f_fl[2], f_ro[2])),
11023 hex->face(2)->isotropic_child_index(
11025 3, f_or[2], f_fl[2], f_ro[2])),
11026
11027 hex->face(3)->isotropic_child_index(
11029 0, f_or[3], f_fl[3], f_ro[3])), // 12
11030 hex->face(3)->isotropic_child_index(
11032 1, f_or[3], f_fl[3], f_ro[3])),
11033 hex->face(3)->isotropic_child_index(
11035 2, f_or[3], f_fl[3], f_ro[3])),
11036 hex->face(3)->isotropic_child_index(
11038 3, f_or[3], f_fl[3], f_ro[3])),
11039
11040 hex->face(4)->child_index(
11041 child_at_origin[hex->face(4)->refinement_case() -
11042 1][f_fl[4]][f_ro[4]]), // 16
11043 hex->face(4)->child_index(
11044 1 -
11045 child_at_origin[hex->face(4)->refinement_case() -
11046 1][f_fl[4]][f_ro[4]]),
11047
11048 hex->face(5)->child_index(
11049 child_at_origin[hex->face(5)->refinement_case() -
11050 1][f_fl[5]][f_ro[5]]), // 18
11051 hex->face(5)->child_index(
11052 1 -
11053 child_at_origin[hex->face(5)->refinement_case() -
11054 1][f_fl[5]][f_ro[5]])};
11055
11056 // due to the exchange of x and y for the front
11057 // and back face, we order the children
11058 // according to
11059 //
11060 // *---*---*
11061 // | 1 | 3 |
11062 // *---*---*
11063 // | 0 | 2 |
11064 // *---*---*
11065 new_hexes[0]->set_bounding_object_indices(
11066 {quad_indices[4],
11067 quad_indices[2],
11068 quad_indices[8],
11069 quad_indices[12],
11070 quad_indices[16],
11071 quad_indices[0]});
11072 new_hexes[1]->set_bounding_object_indices(
11073 {quad_indices[5],
11074 quad_indices[3],
11075 quad_indices[9],
11076 quad_indices[13],
11077 quad_indices[0],
11078 quad_indices[18]});
11079 new_hexes[2]->set_bounding_object_indices(
11080 {quad_indices[2],
11081 quad_indices[6],
11082 quad_indices[10],
11083 quad_indices[14],
11084 quad_indices[17],
11085 quad_indices[1]});
11086 new_hexes[3]->set_bounding_object_indices(
11087 {quad_indices[3],
11088 quad_indices[7],
11089 quad_indices[11],
11090 quad_indices[15],
11091 quad_indices[1],
11092 quad_indices[19]});
11093 break;
11094 }
11095
11097 {
11098 //----------------------------
11099 //
11100 // RefinementCase<dim>::cut_yz
11101 //
11102 // the refined cube will look like this:
11103 //
11104 // *---------*
11105 // / /|
11106 // *---------* |
11107 // / /| |
11108 // *---------* |/|
11109 // | | * |
11110 // | |/| *
11111 // *---------* |/
11112 // | | *
11113 // | |/
11114 // *---------*
11115 //
11116
11117 // first, create the new
11118 // internal line
11119 new_lines[0]->set_bounding_object_indices(
11120
11121 {middle_vertex_index<dim, spacedim>(hex->face(0)),
11122 middle_vertex_index<dim, spacedim>(hex->face(1))});
11123
11124 // again, first collect some data about the
11125 // indices of the lines, with the following
11126 // numbering: (note that face 0 and 1 each are
11127 // shown twice for better readability)
11128
11129 // face 0: left plane
11130 // * *
11131 // /| /|
11132 // * | * |
11133 // /| * /| *
11134 // * 5/| * |7|
11135 // | * | | * |
11136 // |/| * |6| *
11137 // * 4/ * |/
11138 // | * | *
11139 // |/ |/
11140 // * *
11141 // face 1: right plane
11142 // * *
11143 // /| /|
11144 // * | * |
11145 // /| * /| *
11146 // * 9/| * |11
11147 // | * | | * |
11148 // |/| * |10 *
11149 // * 8/ * |/
11150 // | * | *
11151 // |/ |/
11152 // * *
11153 // face 2: front plane
11154 // (note: x,y exchanged)
11155 // *-------*
11156 // | |
11157 // *---0---*
11158 // | |
11159 // *-------*
11160 // face 3: back plane
11161 // (note: x,y exchanged)
11162 // *-------*
11163 // | |
11164 // *---1---*
11165 // | |
11166 // *-------*
11167 // face 4: bottom plane
11168 // *-------*
11169 // / /
11170 // *---2---*
11171 // / /
11172 // *-------*
11173 // face 5: top plane
11174 // *-------*
11175 // / /
11176 // *---3---*
11177 // / /
11178 // *-------*
11179 // middle planes
11180 // *-------* *-------*
11181 // / / | |
11182 // *---12--* | |
11183 // / / | |
11184 // *-------* *-------*
11185
11186 // set up a list of line iterators first. from
11187 // this, construct lists of line_indices and
11188 // line orientations later on
11189 const typename Triangulation<
11190 dim,
11191 spacedim>::raw_line_iterator lines[13] = {
11192 hex->face(2)->child(0)->line(
11193 (hex->face(2)->refinement_case() ==
11195 1 :
11196 3), // 0
11197 hex->face(3)->child(0)->line(
11198 (hex->face(3)->refinement_case() ==
11200 1 :
11201 3), // 1
11202 hex->face(4)->child(0)->line(
11203 (hex->face(4)->refinement_case() ==
11205 1 :
11206 3), // 2
11207 hex->face(5)->child(0)->line(
11208 (hex->face(5)->refinement_case() ==
11210 1 :
11211 3), // 3
11212
11213 hex->face(0)
11214 ->isotropic_child(
11216 0, f_or[0], f_fl[0], f_ro[0]))
11217 ->line(
11219 1, f_or[0], f_fl[0], f_ro[0])), // 4
11220 hex->face(0)
11221 ->isotropic_child(
11223 3, f_or[0], f_fl[0], f_ro[0]))
11224 ->line(
11226 0, f_or[0], f_fl[0], f_ro[0])), // 5
11227 hex->face(0)
11228 ->isotropic_child(
11230 0, f_or[0], f_fl[0], f_ro[0]))
11231 ->line(
11233 3, f_or[0], f_fl[0], f_ro[0])), // 6
11234 hex->face(0)
11235 ->isotropic_child(
11237 3, f_or[0], f_fl[0], f_ro[0]))
11238 ->line(
11240 2, f_or[0], f_fl[0], f_ro[0])), // 7
11241
11242 hex->face(1)
11243 ->isotropic_child(
11245 0, f_or[1], f_fl[1], f_ro[1]))
11246 ->line(
11248 1, f_or[1], f_fl[1], f_ro[1])), // 8
11249 hex->face(1)
11250 ->isotropic_child(
11252 3, f_or[1], f_fl[1], f_ro[1]))
11253 ->line(
11255 0, f_or[1], f_fl[1], f_ro[1])), // 9
11256 hex->face(1)
11257 ->isotropic_child(
11259 0, f_or[1], f_fl[1], f_ro[1]))
11260 ->line(
11262 3, f_or[1], f_fl[1], f_ro[1])), // 10
11263 hex->face(1)
11264 ->isotropic_child(
11266 3, f_or[1], f_fl[1], f_ro[1]))
11267 ->line(
11269 2, f_or[1], f_fl[1], f_ro[1])), // 11
11270
11271 new_lines[0] // 12
11272 };
11273
11274 int line_indices[13];
11275 for (unsigned int i = 0; i < 13; ++i)
11276 line_indices[i] = lines[i]->index();
11277
11278 // the orientation of lines for the inner quads
11279 // is quite tricky. as these lines are newly
11280 // created ones and thus have no parents, they
11281 // cannot inherit this property. set up an array
11282 // and fill it with the respective values
11283 types::geometric_orientation line_orientation[13]{};
11284
11285 // the middle vertices of the lines of our front
11286 // face
11287 const unsigned int middle_vertices[4] = {
11288 hex->line(8)->child(0)->vertex_index(1),
11289 hex->line(10)->child(0)->vertex_index(1),
11290 hex->line(0)->child(0)->vertex_index(1),
11291 hex->line(4)->child(0)->vertex_index(1),
11292 };
11293
11294 // note: for lines 0 to 3 the orientation of the
11295 // line is 'true', if vertex 0 is on the front
11296 for (unsigned int i = 0; i < 4; ++i)
11297 if (lines[i]->vertex_index(0) == middle_vertices[i])
11298 line_orientation[i] =
11300 else
11301 {
11302 // it must be the other way round then
11303 Assert(lines[i]->vertex_index(1) ==
11304 middle_vertices[i],
11306 line_orientation[i] =
11308 }
11309
11310 // note: for lines 4 to 11 (inner lines of the
11311 // outer quads) the following holds: the second
11312 // vertex of the even lines in standard
11313 // orientation is the vertex in the middle of
11314 // the quad, whereas for odd lines the first
11315 // vertex is the same middle vertex.
11316 for (unsigned int i = 4; i < 12; ++i)
11317 if (lines[i]->vertex_index((i + 1) % 2) ==
11318 middle_vertex_index<dim, spacedim>(
11319 hex->face(i / 4 - 1)))
11320 line_orientation[i] =
11322 else
11323 {
11324 // it must be the other way round then
11325 Assert(lines[i]->vertex_index(i % 2) ==
11326 (middle_vertex_index<dim, spacedim>(
11327 hex->face(i / 4 - 1))),
11329 line_orientation[i] =
11331 }
11332 // for the last line the line orientation is always
11333 // the default, since it was just constructed that way
11334 line_orientation[12] =
11336
11337 // set up the 4 quads, numbered as follows (left
11338 // quad numbering, right line numbering
11339 // extracted from above)
11340 //
11341 // x
11342 // *-------* *---3---*
11343 // | 3 | 5 9
11344 // *-------* *---12--*
11345 // | 2 | 4 8
11346 // *-------*y *---2---*
11347 //
11348 // y
11349 // *---------* *----1----*
11350 // / 1 / 7 11
11351 // *---------* *----12---*
11352 // / 0 / 6 10
11353 // *---------*x *----0----*
11354
11355 new_quads[0]->set_bounding_object_indices(
11356 {line_indices[6],
11357 line_indices[10],
11358 line_indices[0],
11359 line_indices[12]});
11360 new_quads[1]->set_bounding_object_indices(
11361 {line_indices[7],
11362 line_indices[11],
11363 line_indices[12],
11364 line_indices[1]});
11365 new_quads[2]->set_bounding_object_indices(
11366 {line_indices[2],
11367 line_indices[12],
11368 line_indices[4],
11369 line_indices[8]});
11370 new_quads[3]->set_bounding_object_indices(
11371 {line_indices[12],
11372 line_indices[3],
11373 line_indices[5],
11374 line_indices[9]});
11375
11376 new_quads[0]->set_line_orientation(
11377 0, line_orientation[6]);
11378 new_quads[0]->set_line_orientation(
11379 1, line_orientation[10]);
11380 new_quads[0]->set_line_orientation(
11381 2, line_orientation[0]);
11382
11383 new_quads[1]->set_line_orientation(
11384 0, line_orientation[7]);
11385 new_quads[1]->set_line_orientation(
11386 1, line_orientation[11]);
11387 new_quads[1]->set_line_orientation(
11388 3, line_orientation[1]);
11389
11390 new_quads[2]->set_line_orientation(
11391 0, line_orientation[2]);
11392 new_quads[2]->set_line_orientation(
11393 2, line_orientation[4]);
11394 new_quads[2]->set_line_orientation(
11395 3, line_orientation[8]);
11396
11397 new_quads[3]->set_line_orientation(
11398 1, line_orientation[3]);
11399 new_quads[3]->set_line_orientation(
11400 2, line_orientation[5]);
11401 new_quads[3]->set_line_orientation(
11402 3, line_orientation[9]);
11403
11404 // the quads are numbered as follows:
11405 //
11406 // planes in the interior of the old hex:
11407 //
11408 // *
11409 // /|
11410 // / | x
11411 // / | *-------* *---------*
11412 // * | | 3 | / 1 /
11413 // | | *-------* *---------*
11414 // | * | 2 | / 0 /
11415 // | / *-------*y *---------*x
11416 // | /
11417 // |/
11418 // *
11419 //
11420 // children of the faces
11421 // of the old hex
11422 // *-------* *-------*
11423 // /| | / 19 /|
11424 // * | 15 | *-------* |
11425 // /|7*-------* / 18 /|11
11426 // * |/| | *-------* |/|
11427 // |6* | 14 | | 10* |
11428 // |/|5*-------* | 13 |/|9*
11429 // * |/ 17 / *-------* |/
11430 // |4*-------* | |8*
11431 // |/ 16 / | 12 |/
11432 // *-------* *-------*
11433 //
11434 // note that we have to take care of the
11435 // orientation of faces.
11436 const int quad_indices[20] = {
11437 new_quads[0]->index(), // 0
11438 new_quads[1]->index(),
11439 new_quads[2]->index(),
11440 new_quads[3]->index(),
11441
11442 hex->face(0)->isotropic_child_index(
11444 0, f_or[0], f_fl[0], f_ro[0])), // 4
11445 hex->face(0)->isotropic_child_index(
11447 1, f_or[0], f_fl[0], f_ro[0])),
11448 hex->face(0)->isotropic_child_index(
11450 2, f_or[0], f_fl[0], f_ro[0])),
11451 hex->face(0)->isotropic_child_index(
11453 3, f_or[0], f_fl[0], f_ro[0])),
11454
11455 hex->face(1)->isotropic_child_index(
11457 0, f_or[1], f_fl[1], f_ro[1])), // 8
11458 hex->face(1)->isotropic_child_index(
11460 1, f_or[1], f_fl[1], f_ro[1])),
11461 hex->face(1)->isotropic_child_index(
11463 2, f_or[1], f_fl[1], f_ro[1])),
11464 hex->face(1)->isotropic_child_index(
11466 3, f_or[1], f_fl[1], f_ro[1])),
11467
11468 hex->face(2)->child_index(
11469 child_at_origin[hex->face(2)->refinement_case() -
11470 1][f_fl[2]][f_ro[2]]), // 12
11471 hex->face(2)->child_index(
11472 1 -
11473 child_at_origin[hex->face(2)->refinement_case() -
11474 1][f_fl[2]][f_ro[2]]),
11475
11476 hex->face(3)->child_index(
11477 child_at_origin[hex->face(3)->refinement_case() -
11478 1][f_fl[3]][f_ro[3]]), // 14
11479 hex->face(3)->child_index(
11480 1 -
11481 child_at_origin[hex->face(3)->refinement_case() -
11482 1][f_fl[3]][f_ro[3]]),
11483
11484 hex->face(4)->child_index(
11485 child_at_origin[hex->face(4)->refinement_case() -
11486 1][f_fl[4]][f_ro[4]]), // 16
11487 hex->face(4)->child_index(
11488 1 -
11489 child_at_origin[hex->face(4)->refinement_case() -
11490 1][f_fl[4]][f_ro[4]]),
11491
11492 hex->face(5)->child_index(
11493 child_at_origin[hex->face(5)->refinement_case() -
11494 1][f_fl[5]][f_ro[5]]), // 18
11495 hex->face(5)->child_index(
11496 1 -
11497 child_at_origin[hex->face(5)->refinement_case() -
11498 1][f_fl[5]][f_ro[5]])};
11499
11500 new_hexes[0]->set_bounding_object_indices(
11501 {quad_indices[4],
11502 quad_indices[8],
11503 quad_indices[12],
11504 quad_indices[2],
11505 quad_indices[16],
11506 quad_indices[0]});
11507 new_hexes[1]->set_bounding_object_indices(
11508 {quad_indices[5],
11509 quad_indices[9],
11510 quad_indices[2],
11511 quad_indices[14],
11512 quad_indices[17],
11513 quad_indices[1]});
11514 new_hexes[2]->set_bounding_object_indices(
11515 {quad_indices[6],
11516 quad_indices[10],
11517 quad_indices[13],
11518 quad_indices[3],
11519 quad_indices[0],
11520 quad_indices[18]});
11521 new_hexes[3]->set_bounding_object_indices(
11522 {quad_indices[7],
11523 quad_indices[11],
11524 quad_indices[3],
11525 quad_indices[15],
11526 quad_indices[1],
11527 quad_indices[19]});
11528 break;
11529 }
11530
11532 {
11533 //----------------------------
11534 //
11535 // RefinementCase<dim>::cut_xyz
11536 // isotropic refinement
11537 //
11538 // the refined cube will look
11539 // like this:
11540 //
11541 // *----*----*
11542 // / / /|
11543 // *----*----* |
11544 // / / /| *
11545 // *----*----* |/|
11546 // | | | * |
11547 // | | |/| *
11548 // *----*----* |/
11549 // | | | *
11550 // | | |/
11551 // *----*----*
11552 //
11553
11554 // find the next unused vertex and set it
11555 // appropriately
11556 while (
11557 triangulation.vertices_used[next_unused_vertex] ==
11558 true)
11559 ++next_unused_vertex;
11560 Assert(
11561 next_unused_vertex < triangulation.vertices.size(),
11562 ExcMessage(
11563 "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."));
11564 triangulation.vertices_used[next_unused_vertex] =
11565 true;
11566
11567 // the new vertex is definitely in the interior,
11568 // so we need not worry about the
11569 // boundary. However we need to worry about
11570 // Manifolds. Let the cell compute its own
11571 // center, by querying the underlying manifold
11572 // object.
11573 triangulation.vertices[next_unused_vertex] =
11574 hex->center(true, true);
11575
11576 // set the data of the six lines. first collect
11577 // the indices of the seven vertices (consider
11578 // the two planes to be crossed to form the
11579 // planes cutting the hex in two vertically and
11580 // horizontally)
11581 //
11582 // *--3--* *--5--*
11583 // / / / | | |
11584 // 0--6--1 0--6--1
11585 // / / / | | |
11586 // *--2--* *--4--*
11587 // the lines are numbered
11588 // as follows:
11589 // *--*--* *--*--*
11590 // / 1 / | 5 |
11591 // *2-*-3* *2-*-3*
11592 // / 0 / | 4 |
11593 // *--*--* *--*--*
11594 //
11595 const unsigned int vertex_indices[7] = {
11596 middle_vertex_index<dim, spacedim>(hex->face(0)),
11597 middle_vertex_index<dim, spacedim>(hex->face(1)),
11598 middle_vertex_index<dim, spacedim>(hex->face(2)),
11599 middle_vertex_index<dim, spacedim>(hex->face(3)),
11600 middle_vertex_index<dim, spacedim>(hex->face(4)),
11601 middle_vertex_index<dim, spacedim>(hex->face(5)),
11602 next_unused_vertex};
11603
11604 new_lines[0]->set_bounding_object_indices(
11606 new_lines[1]->set_bounding_object_indices(
11608 new_lines[2]->set_bounding_object_indices(
11610 new_lines[3]->set_bounding_object_indices(
11612 new_lines[4]->set_bounding_object_indices(
11614 new_lines[5]->set_bounding_object_indices(
11616
11617 // again, first collect some data about the
11618 // indices of the lines, with the following
11619 // numbering: (note that face 0 and 1 each are
11620 // shown twice for better readability)
11621
11622 // face 0: left plane
11623 // * *
11624 // /| /|
11625 // * | * |
11626 // /| * /| *
11627 // * 1/| * |3|
11628 // | * | | * |
11629 // |/| * |2| *
11630 // * 0/ * |/
11631 // | * | *
11632 // |/ |/
11633 // * *
11634 // face 1: right plane
11635 // * *
11636 // /| /|
11637 // * | * |
11638 // /| * /| *
11639 // * 5/| * |7|
11640 // | * | | * |
11641 // |/| * |6| *
11642 // * 4/ * |/
11643 // | * | *
11644 // |/ |/
11645 // * *
11646 // face 2: front plane
11647 // (note: x,y exchanged)
11648 // *---*---*
11649 // | 11 |
11650 // *-8-*-9-*
11651 // | 10 |
11652 // *---*---*
11653 // face 3: back plane
11654 // (note: x,y exchanged)
11655 // *---*---*
11656 // | 15 |
11657 // *12-*-13*
11658 // | 14 |
11659 // *---*---*
11660 // face 4: bottom plane
11661 // *---*---*
11662 // / 17 /
11663 // *18-*-19*
11664 // / 16 /
11665 // *---*---*
11666 // face 5: top plane
11667 // *---*---*
11668 // / 21 /
11669 // *22-*-23*
11670 // / 20 /
11671 // *---*---*
11672 // middle planes
11673 // *---*---* *---*---*
11674 // / 25 / | 29 |
11675 // *26-*-27* *26-*-27*
11676 // / 24 / | 28 |
11677 // *---*---* *---*---*
11678
11679 // set up a list of line iterators first. from
11680 // this, construct lists of line_indices and
11681 // line orientations later on
11682 const typename Triangulation<
11683 dim,
11684 spacedim>::raw_line_iterator lines[30] = {
11685 hex->face(0)
11686 ->isotropic_child(
11688 0, f_or[0], f_fl[0], f_ro[0]))
11689 ->line(
11691 1, f_or[0], f_fl[0], f_ro[0])), // 0
11692 hex->face(0)
11693 ->isotropic_child(
11695 3, f_or[0], f_fl[0], f_ro[0]))
11696 ->line(
11698 0, f_or[0], f_fl[0], f_ro[0])), // 1
11699 hex->face(0)
11700 ->isotropic_child(
11702 0, f_or[0], f_fl[0], f_ro[0]))
11703 ->line(
11705 3, f_or[0], f_fl[0], f_ro[0])), // 2
11706 hex->face(0)
11707 ->isotropic_child(
11709 3, f_or[0], f_fl[0], f_ro[0]))
11710 ->line(
11712 2, f_or[0], f_fl[0], f_ro[0])), // 3
11713
11714 hex->face(1)
11715 ->isotropic_child(
11717 0, f_or[1], f_fl[1], f_ro[1]))
11718 ->line(
11720 1, f_or[1], f_fl[1], f_ro[1])), // 4
11721 hex->face(1)
11722 ->isotropic_child(
11724 3, f_or[1], f_fl[1], f_ro[1]))
11725 ->line(
11727 0, f_or[1], f_fl[1], f_ro[1])), // 5
11728 hex->face(1)
11729 ->isotropic_child(
11731 0, f_or[1], f_fl[1], f_ro[1]))
11732 ->line(
11734 3, f_or[1], f_fl[1], f_ro[1])), // 6
11735 hex->face(1)
11736 ->isotropic_child(
11738 3, f_or[1], f_fl[1], f_ro[1]))
11739 ->line(
11741 2, f_or[1], f_fl[1], f_ro[1])), // 7
11742
11743 hex->face(2)
11744 ->isotropic_child(
11746 0, f_or[2], f_fl[2], f_ro[2]))
11747 ->line(
11749 1, f_or[2], f_fl[2], f_ro[2])), // 8
11750 hex->face(2)
11751 ->isotropic_child(
11753 3, f_or[2], f_fl[2], f_ro[2]))
11754 ->line(
11756 0, f_or[2], f_fl[2], f_ro[2])), // 9
11757 hex->face(2)
11758 ->isotropic_child(
11760 0, f_or[2], f_fl[2], f_ro[2]))
11761 ->line(
11763 3, f_or[2], f_fl[2], f_ro[2])), // 10
11764 hex->face(2)
11765 ->isotropic_child(
11767 3, f_or[2], f_fl[2], f_ro[2]))
11768 ->line(
11770 2, f_or[2], f_fl[2], f_ro[2])), // 11
11771
11772 hex->face(3)
11773 ->isotropic_child(
11775 0, f_or[3], f_fl[3], f_ro[3]))
11776 ->line(
11778 1, f_or[3], f_fl[3], f_ro[3])), // 12
11779 hex->face(3)
11780 ->isotropic_child(
11782 3, f_or[3], f_fl[3], f_ro[3]))
11783 ->line(
11785 0, f_or[3], f_fl[3], f_ro[3])), // 13
11786 hex->face(3)
11787 ->isotropic_child(
11789 0, f_or[3], f_fl[3], f_ro[3]))
11790 ->line(
11792 3, f_or[3], f_fl[3], f_ro[3])), // 14
11793 hex->face(3)
11794 ->isotropic_child(
11796 3, f_or[3], f_fl[3], f_ro[3]))
11797 ->line(
11799 2, f_or[3], f_fl[3], f_ro[3])), // 15
11800
11801 hex->face(4)
11802 ->isotropic_child(
11804 0, f_or[4], f_fl[4], f_ro[4]))
11805 ->line(
11807 1, f_or[4], f_fl[4], f_ro[4])), // 16
11808 hex->face(4)
11809 ->isotropic_child(
11811 3, f_or[4], f_fl[4], f_ro[4]))
11812 ->line(
11814 0, f_or[4], f_fl[4], f_ro[4])), // 17
11815 hex->face(4)
11816 ->isotropic_child(
11818 0, f_or[4], f_fl[4], f_ro[4]))
11819 ->line(
11821 3, f_or[4], f_fl[4], f_ro[4])), // 18
11822 hex->face(4)
11823 ->isotropic_child(
11825 3, f_or[4], f_fl[4], f_ro[4]))
11826 ->line(
11828 2, f_or[4], f_fl[4], f_ro[4])), // 19
11829
11830 hex->face(5)
11831 ->isotropic_child(
11833 0, f_or[5], f_fl[5], f_ro[5]))
11834 ->line(
11836 1, f_or[5], f_fl[5], f_ro[5])), // 20
11837 hex->face(5)
11838 ->isotropic_child(
11840 3, f_or[5], f_fl[5], f_ro[5]))
11841 ->line(
11843 0, f_or[5], f_fl[5], f_ro[5])), // 21
11844 hex->face(5)
11845 ->isotropic_child(
11847 0, f_or[5], f_fl[5], f_ro[5]))
11848 ->line(
11850 3, f_or[5], f_fl[5], f_ro[5])), // 22
11851 hex->face(5)
11852 ->isotropic_child(
11854 3, f_or[5], f_fl[5], f_ro[5]))
11855 ->line(
11857 2, f_or[5], f_fl[5], f_ro[5])), // 23
11858
11859 new_lines[0], // 24
11860 new_lines[1], // 25
11861 new_lines[2], // 26
11862 new_lines[3], // 27
11863 new_lines[4], // 28
11864 new_lines[5] // 29
11865 };
11866
11867 int line_indices[30];
11868 for (unsigned int i = 0; i < 30; ++i)
11869 line_indices[i] = lines[i]->index();
11870
11871 // the orientation of lines for the inner quads
11872 // is quite tricky. as these lines are newly
11873 // created ones and thus have no parents, they
11874 // cannot inherit this property. set up an array
11875 // and fill it with the respective values
11876 types::geometric_orientation line_orientation[30]{};
11877
11878 // note: for the first 24 lines (inner lines of
11879 // the outer quads) the following holds: the
11880 // second vertex of the even lines in standard
11881 // orientation is the vertex in the middle of
11882 // the quad, whereas for odd lines the first
11883 // vertex is the same middle vertex.
11884 for (unsigned int i = 0; i < 24; ++i)
11885 if (lines[i]->vertex_index((i + 1) % 2) ==
11886 vertex_indices[i / 4])
11887 line_orientation[i] =
11889 else
11890 {
11891 // it must be the other way
11892 // round then
11893 Assert(lines[i]->vertex_index(i % 2) ==
11894 vertex_indices[i / 4],
11896 line_orientation[i] =
11898 }
11899 // for the last 6 lines the line orientation is
11900 // always true, since they were just constructed
11901 // that way
11902 for (unsigned int i = 24; i < 30; ++i)
11903 line_orientation[i] =
11905
11906 // set up the 12 quads, numbered as follows
11907 // (left quad numbering, right line numbering
11908 // extracted from above)
11909 //
11910 // * *
11911 // /| 21|
11912 // * | * 15
11913 // y/|3* 20| *
11914 // * |/| * |/|
11915 // |2* |x 11 * 14
11916 // |/|1* |/| *
11917 // * |/ * |17
11918 // |0* 10 *
11919 // |/ |16
11920 // * *
11921 //
11922 // x
11923 // *---*---* *22-*-23*
11924 // | 5 | 7 | 1 29 5
11925 // *---*---* *26-*-27*
11926 // | 4 | 6 | 0 28 4
11927 // *---*---*y *18-*-19*
11928 //
11929 // y
11930 // *----*----* *-12-*-13-*
11931 // / 10 / 11 / 3 25 7
11932 // *----*----* *-26-*-27-*
11933 // / 8 / 9 / 2 24 6
11934 // *----*----*x *--8-*--9-*
11935
11936 new_quads[0]->set_bounding_object_indices(
11937 {line_indices[10],
11938 line_indices[28],
11939 line_indices[16],
11940 line_indices[24]});
11941 new_quads[1]->set_bounding_object_indices(
11942 {line_indices[28],
11943 line_indices[14],
11944 line_indices[17],
11945 line_indices[25]});
11946 new_quads[2]->set_bounding_object_indices(
11947 {line_indices[11],
11948 line_indices[29],
11949 line_indices[24],
11950 line_indices[20]});
11951 new_quads[3]->set_bounding_object_indices(
11952 {line_indices[29],
11953 line_indices[15],
11954 line_indices[25],
11955 line_indices[21]});
11956 new_quads[4]->set_bounding_object_indices(
11957 {line_indices[18],
11958 line_indices[26],
11959 line_indices[0],
11960 line_indices[28]});
11961 new_quads[5]->set_bounding_object_indices(
11962 {line_indices[26],
11963 line_indices[22],
11964 line_indices[1],
11965 line_indices[29]});
11966 new_quads[6]->set_bounding_object_indices(
11967 {line_indices[19],
11968 line_indices[27],
11969 line_indices[28],
11970 line_indices[4]});
11971 new_quads[7]->set_bounding_object_indices(
11972 {line_indices[27],
11973 line_indices[23],
11974 line_indices[29],
11975 line_indices[5]});
11976 new_quads[8]->set_bounding_object_indices(
11977 {line_indices[2],
11978 line_indices[24],
11979 line_indices[8],
11980 line_indices[26]});
11981 new_quads[9]->set_bounding_object_indices(
11982 {line_indices[24],
11983 line_indices[6],
11984 line_indices[9],
11985 line_indices[27]});
11986 new_quads[10]->set_bounding_object_indices(
11987 {line_indices[3],
11988 line_indices[25],
11989 line_indices[26],
11990 line_indices[12]});
11991 new_quads[11]->set_bounding_object_indices(
11992 {line_indices[25],
11993 line_indices[7],
11994 line_indices[27],
11995 line_indices[13]});
11996
11997 // now reset the line_orientation flags of outer
11998 // lines as they cannot be set in a loop (at
11999 // least not easily)
12000 new_quads[0]->set_line_orientation(
12001 0, line_orientation[10]);
12002 new_quads[0]->set_line_orientation(
12003 2, line_orientation[16]);
12004
12005 new_quads[1]->set_line_orientation(
12006 1, line_orientation[14]);
12007 new_quads[1]->set_line_orientation(
12008 2, line_orientation[17]);
12009
12010 new_quads[2]->set_line_orientation(
12011 0, line_orientation[11]);
12012 new_quads[2]->set_line_orientation(
12013 3, line_orientation[20]);
12014
12015 new_quads[3]->set_line_orientation(
12016 1, line_orientation[15]);
12017 new_quads[3]->set_line_orientation(
12018 3, line_orientation[21]);
12019
12020 new_quads[4]->set_line_orientation(
12021 0, line_orientation[18]);
12022 new_quads[4]->set_line_orientation(
12023 2, line_orientation[0]);
12024
12025 new_quads[5]->set_line_orientation(
12026 1, line_orientation[22]);
12027 new_quads[5]->set_line_orientation(
12028 2, line_orientation[1]);
12029
12030 new_quads[6]->set_line_orientation(
12031 0, line_orientation[19]);
12032 new_quads[6]->set_line_orientation(
12033 3, line_orientation[4]);
12034
12035 new_quads[7]->set_line_orientation(
12036 1, line_orientation[23]);
12037 new_quads[7]->set_line_orientation(
12038 3, line_orientation[5]);
12039
12040 new_quads[8]->set_line_orientation(
12041 0, line_orientation[2]);
12042 new_quads[8]->set_line_orientation(
12043 2, line_orientation[8]);
12044
12045 new_quads[9]->set_line_orientation(
12046 1, line_orientation[6]);
12047 new_quads[9]->set_line_orientation(
12048 2, line_orientation[9]);
12049
12050 new_quads[10]->set_line_orientation(
12051 0, line_orientation[3]);
12052 new_quads[10]->set_line_orientation(
12053 3, line_orientation[12]);
12054
12055 new_quads[11]->set_line_orientation(
12056 1, line_orientation[7]);
12057 new_quads[11]->set_line_orientation(
12058 3, line_orientation[13]);
12059
12060 //-------------------------------
12061 // create the eight new hexes
12062 //
12063 // again first collect some data. here, we need
12064 // the indices of a whole lotta quads.
12065
12066 // the quads are numbered as follows:
12067 //
12068 // planes in the interior of the old hex:
12069 //
12070 // *
12071 // /|
12072 // * |
12073 // /|3* *---*---* *----*----*
12074 // * |/| | 5 | 7 | / 10 / 11 /
12075 // |2* | *---*---* *----*----*
12076 // |/|1* | 4 | 6 | / 8 / 9 /
12077 // * |/ *---*---*y *----*----*x
12078 // |0*
12079 // |/
12080 // *
12081 //
12082 // children of the faces
12083 // of the old hex
12084 // *-------* *-------*
12085 // /|25 27| /34 35/|
12086 // 15| | / /19
12087 // / | | /32 33/ |
12088 // * |24 26| *-------*18 |
12089 // 1413*-------* |21 23| 17*
12090 // | /30 31/ | | /
12091 // 12/ / | |16
12092 // |/28 29/ |20 22|/
12093 // *-------* *-------*
12094 //
12095 // note that we have to
12096 // take care of the
12097 // orientation of
12098 // faces.
12099 const int quad_indices[36] = {
12100 new_quads[0]->index(), // 0
12101 new_quads[1]->index(),
12102 new_quads[2]->index(),
12103 new_quads[3]->index(),
12104 new_quads[4]->index(),
12105 new_quads[5]->index(),
12106 new_quads[6]->index(),
12107 new_quads[7]->index(),
12108 new_quads[8]->index(),
12109 new_quads[9]->index(),
12110 new_quads[10]->index(),
12111 new_quads[11]->index(), // 11
12112
12113 hex->face(0)->isotropic_child_index(
12115 0, f_or[0], f_fl[0], f_ro[0])), // 12
12116 hex->face(0)->isotropic_child_index(
12118 1, f_or[0], f_fl[0], f_ro[0])),
12119 hex->face(0)->isotropic_child_index(
12121 2, f_or[0], f_fl[0], f_ro[0])),
12122 hex->face(0)->isotropic_child_index(
12124 3, f_or[0], f_fl[0], f_ro[0])),
12125
12126 hex->face(1)->isotropic_child_index(
12128 0, f_or[1], f_fl[1], f_ro[1])), // 16
12129 hex->face(1)->isotropic_child_index(
12131 1, f_or[1], f_fl[1], f_ro[1])),
12132 hex->face(1)->isotropic_child_index(
12134 2, f_or[1], f_fl[1], f_ro[1])),
12135 hex->face(1)->isotropic_child_index(
12137 3, f_or[1], f_fl[1], f_ro[1])),
12138
12139 hex->face(2)->isotropic_child_index(
12141 0, f_or[2], f_fl[2], f_ro[2])), // 20
12142 hex->face(2)->isotropic_child_index(
12144 1, f_or[2], f_fl[2], f_ro[2])),
12145 hex->face(2)->isotropic_child_index(
12147 2, f_or[2], f_fl[2], f_ro[2])),
12148 hex->face(2)->isotropic_child_index(
12150 3, f_or[2], f_fl[2], f_ro[2])),
12151
12152 hex->face(3)->isotropic_child_index(
12154 0, f_or[3], f_fl[3], f_ro[3])), // 24
12155 hex->face(3)->isotropic_child_index(
12157 1, f_or[3], f_fl[3], f_ro[3])),
12158 hex->face(3)->isotropic_child_index(
12160 2, f_or[3], f_fl[3], f_ro[3])),
12161 hex->face(3)->isotropic_child_index(
12163 3, f_or[3], f_fl[3], f_ro[3])),
12164
12165 hex->face(4)->isotropic_child_index(
12167 0, f_or[4], f_fl[4], f_ro[4])), // 28
12168 hex->face(4)->isotropic_child_index(
12170 1, f_or[4], f_fl[4], f_ro[4])),
12171 hex->face(4)->isotropic_child_index(
12173 2, f_or[4], f_fl[4], f_ro[4])),
12174 hex->face(4)->isotropic_child_index(
12176 3, f_or[4], f_fl[4], f_ro[4])),
12177
12178 hex->face(5)->isotropic_child_index(
12180 0, f_or[5], f_fl[5], f_ro[5])), // 32
12181 hex->face(5)->isotropic_child_index(
12183 1, f_or[5], f_fl[5], f_ro[5])),
12184 hex->face(5)->isotropic_child_index(
12186 2, f_or[5], f_fl[5], f_ro[5])),
12187 hex->face(5)->isotropic_child_index(
12189 3, f_or[5], f_fl[5], f_ro[5]))};
12190
12191 // bottom children
12192 new_hexes[0]->set_bounding_object_indices(
12193 {quad_indices[12],
12194 quad_indices[0],
12195 quad_indices[20],
12196 quad_indices[4],
12197 quad_indices[28],
12198 quad_indices[8]});
12199 new_hexes[1]->set_bounding_object_indices(
12200 {quad_indices[0],
12201 quad_indices[16],
12202 quad_indices[22],
12203 quad_indices[6],
12204 quad_indices[29],
12205 quad_indices[9]});
12206 new_hexes[2]->set_bounding_object_indices(
12207 {quad_indices[13],
12208 quad_indices[1],
12209 quad_indices[4],
12210 quad_indices[24],
12211 quad_indices[30],
12212 quad_indices[10]});
12213 new_hexes[3]->set_bounding_object_indices(
12214 {quad_indices[1],
12215 quad_indices[17],
12216 quad_indices[6],
12217 quad_indices[26],
12218 quad_indices[31],
12219 quad_indices[11]});
12220
12221 // top children
12222 new_hexes[4]->set_bounding_object_indices(
12223 {quad_indices[14],
12224 quad_indices[2],
12225 quad_indices[21],
12226 quad_indices[5],
12227 quad_indices[8],
12228 quad_indices[32]});
12229 new_hexes[5]->set_bounding_object_indices(
12230 {quad_indices[2],
12231 quad_indices[18],
12232 quad_indices[23],
12233 quad_indices[7],
12234 quad_indices[9],
12235 quad_indices[33]});
12236 new_hexes[6]->set_bounding_object_indices(
12237 {quad_indices[15],
12238 quad_indices[3],
12239 quad_indices[5],
12240 quad_indices[25],
12241 quad_indices[10],
12242 quad_indices[34]});
12243 new_hexes[7]->set_bounding_object_indices(
12244 {quad_indices[3],
12245 quad_indices[19],
12246 quad_indices[7],
12247 quad_indices[27],
12248 quad_indices[11],
12249 quad_indices[35]});
12250 break;
12251 }
12252 default:
12253 // all refinement cases have been treated, there
12254 // only remains
12255 // RefinementCase<dim>::no_refinement as
12256 // untreated enumeration value. However, in that
12257 // case we should have aborted much
12258 // earlier. thus we should never get here
12260 break;
12261 } // switch (ref_case)
12262
12263 // and set face orientation flags. note that new
12264 // faces in the interior of the mother cell always
12265 // have a correctly oriented face, but the ones on
12266 // the outer faces will inherit this flag
12267 //
12268 // the flag have been set to true for all faces
12269 // initially, now go the other way round and reset
12270 // faces that are at the boundary of the mother cube
12271 //
12272 // the same is true for the face_flip and
12273 // face_rotation flags. however, the latter two are
12274 // set to false by default as this is the standard
12275 // value
12276
12277 // loop over all faces and all (relevant) subfaces
12278 // of that in order to set the correct values for
12279 // face_orientation, face_flip and face_rotation,
12280 // which are inherited from the corresponding face
12281 // of the mother cube
12282 for (const unsigned int f : GeometryInfo<dim>::face_indices())
12283 for (unsigned int s = 0;
12286 ref_case, f)),
12287 1U);
12288 ++s)
12289 {
12290 const unsigned int current_child =
12292 ref_case,
12293 f,
12294 s,
12295 f_or[f],
12296 f_fl[f],
12297 f_ro[f],
12299 ref_case, f, f_or[f], f_fl[f], f_ro[f]));
12300 new_hexes[current_child]->set_combined_face_orientation(
12301 f, f_co[f]);
12302 }
12303
12304 // now see if we have created cells that are
12305 // distorted and if so add them to our list
12306 if (check_for_distorted_cells &&
12307 has_distorted_children<dim, spacedim>(hex))
12308 cells_with_distorted_children.distorted_cells.push_back(
12309 hex);
12310
12311 // note that the refinement flag was already cleared
12312 // at the beginning of this loop
12313
12314 // inform all listeners that cell refinement is done
12315 triangulation.signals.post_refinement_on_cell(hex);
12316 }
12317 }
12318
12319 // clear user data on quads. we used some of this data to
12320 // indicate anisotropic refinemnt cases on faces. all data
12321 // should be cleared by now, but the information whether we
12322 // used indices or pointers is still present. reset it now to
12323 // enable the user to use whichever they like later on.
12324 triangulation.faces->quads.clear_user_data();
12325
12326 // return the list with distorted children
12327 return cells_with_distorted_children;
12328 }
12329
12330
12343 template <int spacedim>
12344 static void
12347
12348
12349
12350 template <int dim, int spacedim>
12351 static void
12353 Triangulation<dim, spacedim> &triangulation)
12354 {
12355 // If the codimension is one, we cannot perform this check
12356 // yet.
12357 if (spacedim > dim)
12358 return;
12359
12360 for (const auto &cell : triangulation.cell_iterators())
12361 if (cell->at_boundary() && cell->refine_flag_set() &&
12362 cell->refine_flag_set() !=
12364 {
12365 // The cell is at the boundary and it is flagged for
12366 // anisotropic refinement. Therefore, we have a closer
12367 // look
12368 const RefinementCase<dim> ref_case = cell->refine_flag_set();
12369 for (const unsigned int face_no :
12371 if (cell->face(face_no)->at_boundary())
12372 {
12373 // this is the critical face at the boundary.
12375 face_no) !=
12377 {
12378 // up to now, we do not want to refine this
12379 // cell along the face under consideration
12380 // here.
12381 const typename Triangulation<dim,
12382 spacedim>::face_iterator
12383 face = cell->face(face_no);
12384 // the new point on the boundary would be this
12385 // one.
12386 const Point<spacedim> new_bound = face->center(true);
12387 // to check it, transform to the unit cell
12388 // with a linear mapping
12389 const Point<dim> new_unit =
12390 cell->reference_cell()
12391 .template get_default_linear_mapping<spacedim>()
12392 .transform_real_to_unit_cell(cell, new_bound);
12393
12394 // Now, we have to calculate the distance from
12395 // the face in the unit cell.
12396
12397 // take the correct coordinate direction (0
12398 // for faces 0 and 1, 1 for faces 2 and 3, 2
12399 // for faces 4 and 5) and subtract the correct
12400 // boundary value of the face (0 for faces 0,
12401 // 2, and 4; 1 for faces 1, 3 and 5)
12402 const double dist =
12403 std::fabs(new_unit[face_no / 2] - face_no % 2);
12404
12405 // compare this with the empirical value
12406 // allowed. if it is too big, flag the face
12407 // for isotropic refinement
12408 const double allowed = 0.25;
12409
12410 if (dist > allowed)
12411 cell->flag_for_face_refinement(face_no);
12412 } // if flagged for anistropic refinement
12413 } // if (cell->face(face)->at_boundary())
12414 } // for all cells
12415 }
12416
12417
12430 template <int dim, int spacedim>
12431 static void
12433 {
12434 Assert(dim < 3,
12435 ExcMessage("Wrong function called -- there should "
12436 "be a specialization."));
12437 }
12438
12439
12440 template <int spacedim>
12441 static void
12443 Triangulation<3, spacedim> &triangulation)
12444 {
12445 const unsigned int dim = 3;
12446 using raw_line_iterator =
12448
12449 // variable to store whether the mesh was changed in the
12450 // present loop and in the whole process
12451 bool mesh_changed = false;
12452
12453 do
12454 {
12455 mesh_changed = false;
12456
12457 // for this following, we need to know which cells are
12458 // going to be coarsened, if we had to make a
12459 // decision. the following function sets these flags:
12460 triangulation.fix_coarsen_flags();
12461
12462 // first clear flags on lines, since we need them to determine
12463 // which lines will be refined
12464 triangulation.clear_user_flags_line();
12465
12466 // flag those lines that are refined and will not be
12467 // coarsened and those that will be refined
12468 for (const auto &cell : triangulation.cell_iterators())
12469 if (cell->refine_flag_set())
12470 {
12471 const std::array<unsigned int, 12> line_indices =
12472 TriaAccessorImplementation::Implementation::
12473 get_line_indices_of_cell(*cell);
12474 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12476 cell->refine_flag_set(), l) ==
12478 {
12479 raw_line_iterator line(&triangulation,
12480 0,
12481 line_indices[l]);
12482 // flag a line, that will be refined
12483 line->set_user_flag();
12484 }
12485 }
12486 else if (cell->has_children() &&
12487 !cell->child(0)->coarsen_flag_set())
12488 {
12489 const std::array<unsigned int, 12> line_indices =
12490 TriaAccessorImplementation::Implementation::
12491 get_line_indices_of_cell(*cell);
12492 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12494 cell->refinement_case(), l) ==
12496 {
12497 raw_line_iterator line(&triangulation,
12498 0,
12499 line_indices[l]);
12500 // flag a line, that is refined and will stay so
12501 line->set_user_flag();
12502 }
12503 }
12504 else if (cell->has_children() &&
12505 cell->child(0)->coarsen_flag_set())
12506 cell->set_user_flag();
12507
12508
12509 // now check whether there are cells with lines that are
12510 // more than once refined or that will be more than once
12511 // refined. The first thing should never be the case, in
12512 // the second case we flag the cell for refinement
12514 cell = triangulation.last_active();
12515 cell != triangulation.end();
12516 --cell)
12517 {
12518 const std::array<unsigned int, 12> line_indices =
12519 TriaAccessorImplementation::Implementation::
12520 get_line_indices_of_cell(*cell);
12521 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12522 {
12523 raw_line_iterator line(&triangulation, 0, line_indices[l]);
12524 if (line->has_children())
12525 {
12526 // if this line is refined, its children should
12527 // not have further children
12528 //
12529 // however, if any of the children is flagged
12530 // for further refinement, we need to refine
12531 // this cell also (at least, if the cell is not
12532 // already flagged)
12533 bool offending_line_found = false;
12534
12535 for (unsigned int c = 0; c < 2; ++c)
12536 {
12537 Assert(line->child(c)->has_children() == false,
12539
12540 if (line->child(c)->user_flag_set() &&
12542 cell->refine_flag_set(), l) ==
12544 {
12545 // tag this cell for refinement
12546 cell->clear_coarsen_flag();
12547 // if anisotropic coarsening is allowed:
12548 // extend the refine_flag in the needed
12549 // direction, else set refine_flag
12550 // (isotropic)
12551 if (triangulation.smooth_grid &
12553 allow_anisotropic_smoothing)
12554 cell->flag_for_line_refinement(l);
12555 else
12556 cell->set_refine_flag();
12557
12558 for (unsigned int k = 0; k < cell->n_lines();
12559 ++k)
12561 cell->refine_flag_set(), l) ==
12563 // flag a line, that will be refined
12564 raw_line_iterator(&triangulation,
12565 0,
12566 line_indices[k])
12567 ->set_user_flag();
12568
12569 // note that we have changed the grid
12570 offending_line_found = true;
12571
12572 // it may save us several loop
12573 // iterations if we flag all lines of
12574 // this cell now (and not at the outset
12575 // of the next iteration) for refinement
12576 for (unsigned int k = 0; k < cell->n_lines();
12577 ++k)
12578 {
12579 const auto line =
12580 raw_line_iterator(&triangulation,
12581 0,
12582 line_indices[k]);
12583 if (!line->has_children() &&
12585 line_refinement_case(
12586 cell->refine_flag_set(), k) !=
12588 line->set_user_flag();
12589 }
12590
12591 break;
12592 }
12593 }
12594
12595 if (offending_line_found)
12596 {
12597 mesh_changed = true;
12598 break;
12599 }
12600 }
12601 }
12602 }
12603
12604
12605 // there is another thing here: if any of the lines will
12606 // be refined, then we may not coarsen the present cell
12607 // similarly, if any of the lines *is* already refined, we
12608 // may not coarsen the current cell. however, there's a
12609 // catch: if the line is refined, but the cell behind it
12610 // is going to be coarsened, then the situation
12611 // changes. if we forget this second condition, the
12612 // refine_and_coarsen_3d test will start to fail. note
12613 // that to know which cells are going to be coarsened, the
12614 // call for fix_coarsen_flags above is necessary
12616 triangulation.last();
12617 cell != triangulation.end();
12618 --cell)
12619 if (cell->user_flag_set())
12620 {
12621 const std::array<unsigned int, 12> line_indices =
12622 TriaAccessorImplementation::Implementation::
12623 get_line_indices_of_cell(*cell);
12624 for (unsigned int l = 0; l < cell->n_lines(); ++l)
12625 {
12626 raw_line_iterator line(&triangulation,
12627 0,
12628 line_indices[l]);
12629 if (line->has_children() &&
12630 (line->child(0)->user_flag_set() ||
12631 line->child(1)->user_flag_set()))
12632 {
12633 for (unsigned int c = 0; c < cell->n_children(); ++c)
12634 cell->child(c)->clear_coarsen_flag();
12635 cell->clear_user_flag();
12636 for (unsigned int k = 0; k < cell->n_lines(); ++k)
12638 cell->refinement_case(), k) ==
12640 // flag a line, that is refined and will
12641 // stay so
12642 raw_line_iterator(&triangulation,
12643 0,
12644 line_indices[k])
12645 ->set_user_flag();
12646 mesh_changed = true;
12647 break;
12648 }
12649 }
12650 }
12651 }
12652 while (mesh_changed == true);
12653 }
12654
12655
12656
12663 template <int dim, int spacedim>
12664 static bool
12667 {
12668 // in 1d, coarsening is always allowed since we don't enforce
12669 // the 2:1 constraint there
12670 if (dim == 1)
12671 return true;
12672
12673 const RefinementCase<dim> ref_case = cell->refinement_case();
12674 for (const unsigned int n : GeometryInfo<dim>::face_indices())
12675 {
12676 // if the cell is not refined along that face, coarsening
12677 // will not change anything, so do nothing. the same
12678 // applies, if the face is at the boundary
12679 const RefinementCase<dim - 1> face_ref_case =
12680 GeometryInfo<dim>::face_refinement_case(cell->refinement_case(),
12681 n);
12682
12683 const unsigned int n_subfaces =
12684 GeometryInfo<dim - 1>::n_children(face_ref_case);
12685
12686 if (n_subfaces == 0 || cell->at_boundary(n))
12687 continue;
12688 for (unsigned int c = 0; c < n_subfaces; ++c)
12689 {
12691 child = cell->child(
12693
12695 child_neighbor = child->neighbor(n);
12696 if (!child->neighbor_is_coarser(n))
12697 {
12698 // in 2d, if the child's neighbor is coarser, then it has
12699 // no children. however, in 3d it might be
12700 // otherwise. consider for example, that our face might be
12701 // refined with cut_x, but the neighbor is refined with
12702 // cut_xy at that face. then the neighbor pointers of the
12703 // children of our cell will point to the common neighbor
12704 // cell, not to its children. what we really want to know
12705 // in the following is, whether the neighbor cell is
12706 // refined twice with reference to our cell. that only
12707 // has to be asked, if the child's neighbor is not a
12708 // coarser one. we check whether some of the children on
12709 // the neighbor are not flagged for coarsening, in that
12710 // case we may not coarsen. it is enough to check the
12711 // first child because we have already fixed the coarsen
12712 // flags on finer levels
12713 if (child_neighbor->has_children() &&
12714 !(child_neighbor->child(0)->is_active() &&
12715 child_neighbor->child(0)->coarsen_flag_set()))
12716 return false;
12717
12718 // the same applies, if the neighbors children are not
12719 // refined but will be after refinement
12720 if (child_neighbor->refine_flag_set())
12721 return false;
12722 }
12723 }
12724 }
12725 return true;
12726 }
12727 };
12728
12729
12734 {
12735 template <int spacedim>
12736 static void
12739
12740 template <int dim, int spacedim>
12741 static void
12743 {
12744 std::vector<std::pair<int, int>> adjacent_cells(
12745 2 * triangulation.n_raw_faces(), {-1, -1});
12746
12747 const auto set_entry = [&](const auto &face_index, const auto &cell) {
12748 const std::pair<int, int> cell_pair = {cell->level(), cell->index()};
12749
12751 if (adjacent_cells[2 * face_index].first == -1 &&
12752 adjacent_cells[2 * face_index].second == -1)
12753 {
12754 index = 2 * face_index + 0;
12755 }
12756 else
12757 {
12758 Assert(((adjacent_cells[2 * face_index + 1].first == -1) &&
12759 (adjacent_cells[2 * face_index + 1].second == -1)),
12761 index = 2 * face_index + 1;
12762 }
12763
12764 adjacent_cells[index] = cell_pair;
12765 };
12766
12767 const auto get_entry =
12768 [&](const auto &face_index,
12769 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
12770 auto test = adjacent_cells[2 * face_index];
12771
12772 if (test == std::make_pair(cell->level(), cell->index()))
12773 test = adjacent_cells[2 * face_index + 1];
12774
12775 return TriaIterator<CellAccessor<dim, spacedim>>(&triangulation,
12776 test.first,
12777 test.second);
12778 };
12779
12780 for (const auto &cell : triangulation.cell_iterators())
12781 for (const auto &face : cell->face_iterators())
12782 {
12783 set_entry(face->index(), cell);
12784
12785 if (cell->is_active() && face->has_children())
12786 for (unsigned int c = 0; c < face->n_children(); ++c)
12787 set_entry(face->child(c)->index(), cell);
12788 }
12789
12790 for (const auto &cell : triangulation.cell_iterators())
12791 for (auto f : cell->face_indices())
12792 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
12793 }
12794
12795 template <int dim, int spacedim>
12796 static void
12798 Triangulation<dim, spacedim> & /*triangulation*/,
12800 std::vector<unsigned int> & /*line_cell_count*/,
12801 std::vector<unsigned int> & /*quad_cell_count*/)
12802 {
12804 }
12805
12806 template <int dim, int spacedim>
12809 const bool check_for_distorted_cells)
12810 {
12811 return Implementation::execute_refinement_isotropic(
12812 triangulation, check_for_distorted_cells);
12813 }
12814
12815 template <int dim, int spacedim>
12816 static void
12818 Triangulation<dim, spacedim> & /*triangulation*/)
12819 {
12820 // nothing to do since anisotropy is not supported
12821 }
12822
12823 template <int dim, int spacedim>
12824 static void
12826 Triangulation<dim, spacedim> &triangulation)
12827 {
12828 Implementation::prepare_refinement_dim_dependent(triangulation);
12829 }
12830
12831 template <int dim, int spacedim>
12832 static bool
12835 {
12837
12838 return false;
12839 }
12840 };
12841 } // namespace TriangulationImplementation
12842} // namespace internal
12843
12844#ifndef DOXYGEN
12845
12846template <int dim, int spacedim>
12849
12850
12851
12852template <int dim, int spacedim>
12855 const MeshSmoothing smooth_grid,
12856 const bool check_for_distorted_cells)
12857 : cell_attached_data({0, 0, {}, {}})
12858 , smooth_grid(smooth_grid)
12859 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12860 , anisotropic_refinement(false)
12861 , check_for_distorted_cells(check_for_distorted_cells)
12862{
12863 if (dim == 1)
12864 {
12865 vertex_to_boundary_id_map_1d =
12866 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12867 vertex_to_manifold_id_map_1d =
12868 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12869 }
12870
12871 // connect the any_change signal to the other top level signals
12872 signals.create.connect(signals.any_change);
12873 signals.post_refinement.connect(signals.any_change);
12874 signals.clear.connect(signals.any_change);
12875 signals.mesh_movement.connect(signals.any_change);
12876}
12877
12878
12879
12880template <int dim, int spacedim>
12883 Triangulation<dim, spacedim> &&tria) noexcept
12884 : EnableObserverPointer(std::move(tria))
12885 , cell_attached_data(std::move(tria.cell_attached_data))
12886 , smooth_grid(tria.smooth_grid)
12887 , reference_cells(std::move(tria.reference_cells))
12888 , strides(tria.strides)
12889 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12890 , periodic_face_map(std::move(tria.periodic_face_map))
12891 , levels(std::move(tria.levels))
12892 , faces(std::move(tria.faces))
12893 , vertices(std::move(tria.vertices))
12894 , vertices_used(std::move(tria.vertices_used))
12895 , manifolds(std::move(tria.manifolds))
12896 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12897 , anisotropic_refinement(tria.anisotropic_refinement)
12898 , check_for_distorted_cells(tria.check_for_distorted_cells)
12899 , number_cache(std::move(tria.number_cache))
12900 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12901 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12902{
12904 tria.strides = {};
12905
12906 if (tria.policy)
12907 this->policy = tria.policy->clone();
12908}
12909
12910
12911template <int dim, int spacedim>
12914 Triangulation<dim, spacedim> &&tria) noexcept
12915{
12916 EnableObserverPointer::operator=(std::move(tria));
12917
12918 cell_attached_data = std::move(tria.cell_attached_data);
12919 smooth_grid = tria.smooth_grid;
12920 reference_cells = std::move(tria.reference_cells);
12921 strides = tria.strides;
12922 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12923 periodic_face_map = std::move(tria.periodic_face_map);
12924 levels = std::move(tria.levels);
12925 faces = std::move(tria.faces);
12926 vertices = std::move(tria.vertices);
12927 vertices_used = std::move(tria.vertices_used);
12928 manifolds = std::move(tria.manifolds);
12929 anisotropic_refinement = tria.anisotropic_refinement;
12930 number_cache = tria.number_cache;
12931 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12932 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12933
12935 tria.strides = {};
12936
12937 if (tria.policy)
12938 this->policy = tria.policy->clone();
12939
12940 return *this;
12941}
12942
12943
12944
12945template <int dim, int spacedim>
12948{
12949 // notify listeners that the triangulation is going down...
12950 try
12951 {
12952 signals.clear();
12953 }
12954 catch (...)
12955 {}
12956
12957 levels.clear();
12958
12959 // the vertex_to_boundary_id_map_1d field should be unused except in
12960 // 1d. double check this here, as destruction is a good place to
12961 // ensure that what we've done over the course of the lifetime of
12962 // this object makes sense
12963 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12965
12966 // the vertex_to_manifold_id_map_1d field should be also unused
12967 // except in 1d. check this as well
12968 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12970}
12971
12972
12973
12974template <int dim, int spacedim>
12977{
12978 // notify listeners that the triangulation is going down...
12979 signals.clear();
12980
12981 // ...and then actually clear all content of it
12982 clear_despite_subscriptions();
12983 periodic_face_pairs_level_0.clear();
12984 periodic_face_map.clear();
12985 reference_cells.clear();
12986
12987 cell_attached_data = {0, 0, {}, {}};
12988 data_serializer.clear();
12989}
12990
12991template <int dim, int spacedim>
12994{
12995 return MPI_COMM_SELF;
12996}
12997
12998
12999
13000template <int dim, int spacedim>
13002std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13004{
13005 return number_cache.active_cell_index_partitioner;
13006}
13007
13008
13009
13010template <int dim, int spacedim>
13012std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13013 global_level_cell_index_partitioner(const unsigned int level) const
13014{
13015 AssertIndexRange(level, this->n_levels());
13016
13017 return number_cache.level_cell_index_partitioners[level];
13018}
13019
13020
13021
13022template <int dim, int spacedim>
13025 const MeshSmoothing mesh_smoothing)
13026{
13027 smooth_grid = mesh_smoothing;
13028}
13029
13030
13031
13032template <int dim, int spacedim>
13036{
13037 return smooth_grid;
13038}
13039
13040
13041
13042template <int dim, int spacedim>
13045 const types::manifold_id m_number,
13046 const Manifold<dim, spacedim> &manifold_object)
13047{
13049
13050 manifolds[m_number] = manifold_object.clone();
13051}
13052
13053
13054
13055template <int dim, int spacedim>
13058 const types::manifold_id m_number)
13059{
13061
13062 // delete the entry located at number.
13063 manifolds[m_number] = default_flat_manifold->clone();
13064}
13065
13066
13067template <int dim, int spacedim>
13070{
13071 for (auto &m : manifolds)
13072 m.second = default_flat_manifold->clone();
13073}
13074
13075
13076template <int dim, int spacedim>
13079 const types::manifold_id m_number)
13080{
13081 Assert(
13082 n_cells() > 0,
13083 ExcMessage(
13084 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
13085
13086 for (const auto &cell : this->active_cell_iterators())
13087 cell->set_all_manifold_ids(m_number);
13088}
13089
13090
13091template <int dim, int spacedim>
13094 const types::manifold_id m_number)
13095{
13096 Assert(
13097 n_cells() > 0,
13098 ExcMessage(
13099 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13100
13101 for (const auto &cell : this->active_cell_iterators())
13102 for (auto f : GeometryInfo<dim>::face_indices())
13103 if (cell->face(f)->at_boundary())
13104 cell->face(f)->set_all_manifold_ids(m_number);
13105}
13106
13107
13108template <int dim, int spacedim>
13111 const types::boundary_id b_id,
13112 const types::manifold_id m_number)
13113{
13114 Assert(
13115 n_cells() > 0,
13116 ExcMessage(
13117 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13118
13119 bool boundary_found = false;
13120 for (const auto &cell : this->active_cell_iterators())
13121 {
13122 // loop on faces
13123 for (auto f : GeometryInfo<dim>::face_indices())
13124 if (cell->face(f)->at_boundary() &&
13125 cell->face(f)->boundary_id() == b_id)
13126 {
13127 boundary_found = true;
13128 cell->face(f)->set_manifold_id(m_number);
13129 }
13130
13131 // loop on edges if dim >= 3
13132 if (dim >= 3)
13133 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
13134 if (cell->line(e)->at_boundary() &&
13135 cell->line(e)->boundary_id() == b_id)
13136 {
13137 boundary_found = true;
13138 cell->line(e)->set_manifold_id(m_number);
13139 }
13140 }
13141
13142 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
13143}
13144
13145
13146
13147template <int dim, int spacedim>
13150 const types::manifold_id m_number) const
13151{
13152 // check if flat manifold has been queried
13153 if (m_number == numbers::flat_manifold_id)
13154 return *default_flat_manifold;
13155
13156 // look, if there is a manifold stored at
13157 // manifold_id number.
13158 const auto it = manifolds.find(m_number);
13159
13160 if (it != manifolds.end())
13161 {
13162 // if we have found an entry, return it
13163 return *(it->second);
13164 }
13165
13166 Assert(
13167 false,
13168 ExcMessage(
13169 "No manifold of the manifold id " + std::to_string(m_number) +
13170 " has been attached to the triangulation. "
13171 "Please attach the right manifold with Triangulation::set_manifold()."));
13172
13173 return *default_flat_manifold; // never reached
13174}
13175
13176
13177
13178template <int dim, int spacedim>
13180std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
13181 const
13182{
13183 std::set<types::boundary_id> boundary_ids;
13184 for (const auto &cell : active_cell_iterators())
13185 if (cell->is_locally_owned())
13186 for (const auto &face : cell->face_indices())
13187 if (cell->at_boundary(face))
13188 boundary_ids.insert(cell->face(face)->boundary_id());
13189
13190 return {boundary_ids.begin(), boundary_ids.end()};
13191}
13192
13193
13194
13195template <int dim, int spacedim>
13197std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
13198 const
13199{
13200 std::set<types::manifold_id> m_ids;
13201 for (const auto &cell : active_cell_iterators())
13202 if (cell->is_locally_owned())
13203 {
13204 m_ids.insert(cell->manifold_id());
13205 for (const auto &face : cell->face_iterators())
13206 m_ids.insert(face->manifold_id());
13207 if (dim == 3)
13208 {
13209 const auto line_indices = internal::TriaAccessorImplementation::
13210 Implementation::get_line_indices_of_cell(*cell);
13211 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13212 {
13213 raw_line_iterator line(this, 0, line_indices[l]);
13214 m_ids.insert(line->manifold_id());
13215 }
13216 }
13217 }
13218 return {m_ids.begin(), m_ids.end()};
13219}
13220
13221#endif
13222/*-----------------------------------------------------------------*/
13223
13224#ifndef DOXYGEN
13225
13226template <int dim, int spacedim>
13229 const Triangulation<dim, spacedim> &other_tria)
13230{
13231 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13232 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13233 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
13234 (dim == 1 || other_tria.faces != nullptr),
13235 ExcMessage(
13236 "When calling Triangulation::copy_triangulation(), "
13237 "the target triangulation must be empty but the source "
13238 "triangulation (the argument to this function) must contain "
13239 "something. Here, it seems like the source does not "
13240 "contain anything at all."));
13241
13242
13243 // copy normal elements
13244 vertices = other_tria.vertices;
13245 vertices_used = other_tria.vertices_used;
13246 anisotropic_refinement = other_tria.anisotropic_refinement;
13247 smooth_grid = other_tria.smooth_grid;
13248 reference_cells = other_tria.reference_cells;
13249 strides = other_tria.strides;
13250
13251 if (dim > 1)
13252 faces =
13253 std::make_unique<internal::TriangulationImplementation::TriaFaces<dim>>(
13254 *other_tria.faces);
13255
13256 for (const auto &p : other_tria.manifolds)
13257 set_manifold(p.first, *p.second);
13258
13259
13260 Assert(other_tria.levels.size() <= numbers::max_n_levels, ExcInternalError());
13261 levels.reserve(other_tria.levels.size());
13262 for (const auto &level : other_tria.levels)
13263 levels.push_back(
13264 std::make_unique<
13265 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>(
13266 *level));
13267
13268 number_cache = other_tria.number_cache;
13269
13270 if (dim == 1)
13271 {
13272 vertex_to_boundary_id_map_1d =
13273 std::make_unique<std::map<unsigned int, types::boundary_id>>(
13274 *other_tria.vertex_to_boundary_id_map_1d);
13275
13276 vertex_to_manifold_id_map_1d =
13277 std::make_unique<std::map<unsigned int, types::manifold_id>>(
13278 *other_tria.vertex_to_manifold_id_map_1d);
13279 }
13280
13281 if (other_tria.policy)
13282 this->policy = other_tria.policy->clone();
13283
13284 // periodic faces
13285 this->periodic_face_pairs_level_0.reserve(
13286 other_tria.periodic_face_pairs_level_0.size());
13287
13288 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
13289 {
13290 auto entry = other_entry;
13291 entry.cell[0] =
13292 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
13293 entry.cell[1] =
13294 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
13295 periodic_face_pairs_level_0.emplace_back(entry);
13296 }
13297
13298 for (auto [first_cell_, second_cell_and_orientation] :
13299 other_tria.periodic_face_map)
13300 {
13301 auto first_cell = first_cell_; // make copy since key is const
13302 first_cell.first = cell_iterator(this,
13303 first_cell.first->level(),
13304 first_cell.first->index());
13305 second_cell_and_orientation.first.first =
13306 cell_iterator(this,
13307 second_cell_and_orientation.first.first->level(),
13308 second_cell_and_orientation.first.first->index());
13309
13310 this->periodic_face_map[first_cell] = second_cell_and_orientation;
13311 }
13312
13313 // inform those who are listening on other_tria of the copy operation
13314 other_tria.signals.copy(*this);
13315 // also inform all listeners of the current triangulation that the
13316 // triangulation has been created
13317 signals.create();
13318
13319 // note that we need not copy the
13320 // subscriptor!
13321}
13322
13323
13324
13325template <int dim, int spacedim>
13328{
13329 if (this->all_reference_cells_are_hyper_cube())
13330 {
13331 this->policy =
13333 dim,
13334 spacedim,
13336 }
13337 else
13338 {
13339 this->policy =
13341 dim,
13342 spacedim,
13344 }
13345}
13346
13347
13348
13349template <int dim, int spacedim>
13352 const std::vector<Point<spacedim>> &v,
13353 const std::vector<CellData<dim>> &cells,
13354 const SubCellData &subcelldata)
13355{
13356 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13357 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13358 // check that no forbidden arrays
13359 // are used
13360 Assert(subcelldata.check_consistency(dim), ExcInternalError());
13361
13362 // try to create a triangulation; if this fails, we still want to
13363 // throw an exception but if we just do so we'll get into trouble
13364 // because sometimes other objects are already attached to it:
13365 try
13366 {
13368 create_triangulation(v, cells, subcelldata, *this);
13369 }
13370 catch (...)
13371 {
13372 clear_despite_subscriptions();
13373 throw;
13374 }
13375
13376 reset_policy();
13377
13378 // update our counts of the various elements of a triangulation, and set
13379 // active_cell_indices of all cells
13380 reset_cell_vertex_indices_cache();
13382 *this, levels.size(), number_cache);
13383 reset_active_cell_indices();
13384 reset_global_cell_indices();
13385
13386 // now verify that there are indeed no distorted cells. as per the
13387 // documentation of this class, we first collect all distorted cells
13388 // and then throw an exception if there are any
13389 if (check_for_distorted_cells)
13390 {
13391 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
13392 // throw the array (and fill the various location fields) if
13393 // there are distorted cells. otherwise, just fall off the end
13394 // of the function
13395 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
13396 }
13397
13398
13399 /*
13400 When the triangulation is a manifold (dim < spacedim) and made of
13401 quadrilaterals, the normal field provided from the map class depends on
13402 the order of the vertices. It may happen that this normal field is
13403 discontinuous. The following code takes care that this is not the case by
13404 setting the cell direction flag on those cell that produce the wrong
13405 orientation.
13406
13407 To determine if 2 neighbors have the same or opposite orientation we use
13408 a truth table. Its entries are indexed by the local indices of the
13409 common face. For example if two elements share a face, and this face is
13410 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
13411 whether the orientation are the same (true) or opposite (false).
13412
13413 Even though there may be a combinatorial/graph theory argument to get this
13414 table in any dimension, I tested by hand all the different possible cases
13415 in 1D and 2D to generate the table.
13416
13417 Assuming that a surface respects the standard orientation for 2d meshes,
13418 the truth tables are symmetric and their true values are the following
13419
13420 - 1D curves: (0,1)
13421 - 2D surface: (0,1),(0,2),(1,3),(2,3)
13422
13423 We store this data using an n_faces x n_faces full matrix, which is
13424 actually much bigger than the minimal data required, but it makes the code
13425 more readable.
13426
13427 */
13428 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
13429 {
13432 switch (dim)
13433 {
13434 case 1:
13435 {
13436 const bool values[][2] = {{false, true}, {true, false}};
13437 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13438 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13439 correct(i, j) = values[i][j];
13440 break;
13441 }
13442 case 2:
13443 {
13444 const bool values[][4] = {{false, true, true, false},
13445 {true, false, false, true},
13446 {true, false, false, true},
13447 {false, true, true, false}};
13448 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13449 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13450 correct(i, j) = (values[i][j]);
13451 break;
13452 }
13453 default:
13455 }
13456
13457
13458 std::list<active_cell_iterator> this_round, next_round;
13459 active_cell_iterator neighbor;
13460
13461 // Start with the first cell and (arbitrarily) decide that its
13462 // direction flag should be 'true':
13463 this_round.push_back(begin_active());
13464 begin_active()->set_direction_flag(true);
13465 begin_active()->set_user_flag();
13466
13467 while (this_round.size() > 0)
13468 {
13469 for (const auto &cell : this_round)
13470 {
13471 for (const unsigned int i : cell->face_indices())
13472 {
13473 if (cell->face(i)->at_boundary() == false)
13474 {
13475 // Consider the i'th neighbor of a cell for
13476 // which we have already set the direction:
13477 neighbor = cell->neighbor(i);
13478
13479 const unsigned int nb_of_nb =
13480 cell->neighbor_of_neighbor(i);
13481
13482 // If we already saw this neighboring cell,
13483 // check that everything is fine:
13484 if (neighbor->user_flag_set())
13485 {
13486 Assert(
13487 !(correct(i, nb_of_nb) ^
13488 (neighbor->direction_flag() ==
13489 cell->direction_flag())),
13490 ExcMessage(
13491 "The triangulation you are trying to create is not orientable."));
13492 }
13493 else
13494 {
13495 // We had not seen this cell yet. Set its
13496 // orientation flag (if necessary), mark it
13497 // as treated via the user flag, and push it
13498 // onto the list of cells to start work from
13499 // the next time around:
13500 if (correct(i, nb_of_nb) ^
13501 (neighbor->direction_flag() ==
13502 cell->direction_flag()))
13503 neighbor->set_direction_flag(
13504 !neighbor->direction_flag());
13505 neighbor->set_user_flag();
13506 next_round.push_back(neighbor);
13507 }
13508 }
13509 }
13510 }
13511
13512 // Before we quit let's check that if the triangulation is
13513 // disconnected that we still get all cells by starting
13514 // again from the first cell we haven't treated yet -- that
13515 // is, the first cell of the next disconnected component we
13516 // had not yet touched.
13517 if (next_round.empty())
13518 for (const auto &cell : this->active_cell_iterators())
13519 if (cell->user_flag_set() == false)
13520 {
13521 next_round.push_back(cell);
13522 cell->set_direction_flag(true);
13523 cell->set_user_flag();
13524 break;
13525 }
13526
13527 // Go on to the next round:
13528 next_round.swap(this_round);
13529 next_round.clear();
13530 }
13531 clear_user_flags();
13532 }
13533
13534 this->update_cell_relations();
13535
13536 // inform all listeners that the triangulation has been created
13537 signals.create();
13538}
13539
13540
13541
13542template <int dim, int spacedim>
13546{
13547 // 1) create coarse grid
13549 construction_data.coarse_cells,
13550 SubCellData());
13551
13552 // create a copy of cell_infos such that we can sort them
13553 auto cell_infos = construction_data.cell_infos;
13554
13555 // sort cell_infos on each level separately
13556 for (auto &cell_info : cell_infos)
13557 std::sort(
13558 cell_info.begin(),
13559 cell_info.end(),
13562 const CellId a_id(a.id);
13563 const CellId b_id(b.id);
13564
13565 const auto a_coarse_cell_index =
13566 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
13567 const auto b_coarse_cell_index =
13568 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
13569
13570 // according to their coarse-cell index and if that is
13571 // same according to their cell id (the result is that
13572 // cells on each level are sorted according to their
13573 // index on that level - what we need in the following
13574 // operations)
13575 if (a_coarse_cell_index != b_coarse_cell_index)
13576 return a_coarse_cell_index < b_coarse_cell_index;
13577 else
13578 return a_id < b_id;
13579 });
13580
13581 // 2) create all levels via a sequence of refinements. note that
13582 // we must make sure that we actually have cells on this level,
13583 // which is not clear in a parallel context for some processes
13584 for (unsigned int level = 0;
13585 level < cell_infos.size() && !cell_infos[level].empty();
13586 ++level)
13587 {
13588 // a) set material and manifold ids here (because new vertices
13589 // have to be positioned correctly during each refinement step)
13590 {
13591 auto cell = this->begin(level);
13592 auto cell_info = cell_infos[level].begin();
13593 for (; cell_info != cell_infos[level].end(); ++cell_info)
13594 {
13595 while (cell_info->id != cell->id().template to_binary<dim>())
13596 ++cell;
13597
13598 if (level == 0)
13599 {
13600 Assert(cell->material_id() == cell_info->material_id,
13601 ExcMessage(
13602 "The coarsest level material_ids must match."));
13603 Assert(cell->manifold_id() == cell_info->manifold_id,
13604 ExcMessage(
13605 "The coarsest level manifold_ids must match."));
13606 }
13607
13608 cell->set_material_id(cell_info->material_id);
13609 if (dim == 2)
13610 for (const auto face : cell->face_indices())
13611 cell->face(face)->set_manifold_id(
13612 cell_info->manifold_line_ids[face]);
13613 else if (dim == 3)
13614 {
13615 for (const auto face : cell->face_indices())
13616 cell->face(face)->set_manifold_id(
13617 cell_info->manifold_quad_ids[face]);
13618
13619 const auto line_indices = internal::TriaAccessorImplementation::
13620 Implementation::get_line_indices_of_cell(*cell);
13621 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13622 {
13623 raw_line_iterator line(this, 0, line_indices[l]);
13624 line->set_manifold_id(cell_info->manifold_line_ids[l]);
13625 }
13626 }
13627
13628 cell->set_manifold_id(cell_info->manifold_id);
13629 }
13630 }
13631
13632 // b) perform refinement on all levels but on the finest
13633 if (level + 1 != cell_infos.size())
13634 {
13635 // find cells that should have children and mark them for
13636 // refinement
13637 auto coarse_cell = this->begin(level);
13638 auto fine_cell_info = cell_infos[level + 1].begin();
13639
13640 // loop over all cells on the next level
13641 for (; fine_cell_info != cell_infos[level + 1].end();
13642 ++fine_cell_info)
13643 {
13644 // find the parent of that cell
13645 while (
13646 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
13647 ++coarse_cell;
13648
13649 // set parent for refinement
13650 coarse_cell->set_refine_flag();
13651 }
13652
13653 // execute refinement
13654 ::Triangulation<dim,
13655 spacedim>::execute_coarsening_and_refinement();
13656 }
13657 }
13658
13659 // 3) set boundary ids
13660 for (unsigned int level = 0;
13661 level < cell_infos.size() && !cell_infos[level].empty();
13662 ++level)
13663 {
13664 auto cell = this->begin(level);
13665 auto cell_info = cell_infos[level].begin();
13666 for (; cell_info != cell_infos[level].end(); ++cell_info)
13667 {
13668 // find cell that has the correct cell
13669 while (cell_info->id != cell->id().template to_binary<dim>())
13670 ++cell;
13671
13672 // boundary ids
13673 for (auto pair : cell_info->boundary_ids)
13674 if (cell->face(pair.first)->at_boundary())
13675 cell->face(pair.first)->set_boundary_id(pair.second);
13676 }
13677 }
13678
13679 // inform all listeners that the triangulation has been created
13680 signals.create();
13681}
13682
13683
13684template <int dim, int spacedim>
13687{
13688 AssertThrow(dim + 1 == spacedim,
13689 ExcMessage(
13690 "This function can only be called if dim == spacedim-1."));
13691 for (const auto &cell : this->active_cell_iterators())
13692 cell->set_direction_flag(!cell->direction_flag());
13693}
13694
13695
13696
13697template <int dim, int spacedim>
13700{
13701 if constexpr (dim == 3)
13702 {
13703 // Compute the vertex to cell map
13704 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
13706
13707 // Compute the line-neighbors
13708 if (this->line_to_adjacent_cells_map)
13709 // If the std::optional ready has a value attached to it, just change
13710 // the size of the table stored inside it.
13711 this->line_to_adjacent_cells_map->reinit(
13712 this->n_active_cells(),
13713 (is_mixed_mesh() ?
13714 GeometryInfo<dim>::lines_per_cell : // err on the safe side: choose
13715 // the largest number of lines
13716 // per cell
13717 get_reference_cells()[0]
13718 .n_lines()) // choose the right number of lines per cell for the
13719 // mesh type used
13720 );
13721 else
13722 // Else if the std::optional has no value attached to it, create a table
13723 // of the corresponding size and store it inside the std::optional.
13724 this->line_to_adjacent_cells_map =
13725 std::make_optional<Table<2, std::set<active_cell_iterator>>>(
13727 this->n_active_cells(),
13728 (is_mixed_mesh() ? GeometryInfo<dim>::lines_per_cell :
13729 get_reference_cells()[0].n_lines())));
13730
13731
13732 // Loop over all cells -> lines -> vertices
13733 for (const auto &cell : this->active_cell_iterators())
13734 for (unsigned int line : cell->line_indices())
13735 {
13736 const unsigned int vertex_0 = cell->vertex_index(
13738 const unsigned int vertex_1 = cell->vertex_index(
13740 const std::set<
13742 &adjacent_cells_to_vertex_0 = vertex_to_cell[vertex_0];
13743 const std::set<
13745 &adjacent_cells_to_vertex_1 = vertex_to_cell[vertex_1];
13746
13747 // add all cells that are adjacent to vertex_0 and vertex_1
13748 std::set_intersection(
13749 adjacent_cells_to_vertex_0.begin(),
13750 adjacent_cells_to_vertex_0.end(),
13751 adjacent_cells_to_vertex_1.begin(),
13752 adjacent_cells_to_vertex_1.end(),
13753 std::inserter(line_to_adjacent_cells_map
13754 .value()[cell->active_cell_index()][line],
13755 line_to_adjacent_cells_map
13756 .value()[cell->active_cell_index()][line]
13757 .begin()));
13758 }
13759 }
13760}
13761
13762
13763
13764template <int dim, int spacedim>
13767{
13768 Assert(n_cells() > 0,
13769 ExcMessage("Error: An empty Triangulation can not be refined."));
13770
13771 for (const auto &cell : this->active_cell_iterators())
13772 {
13773 cell->clear_coarsen_flag();
13774 cell->set_refine_flag();
13775 cell->set_refine_choice();
13776 }
13777}
13778
13779
13780
13781template <int dim, int spacedim>
13783void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
13784{
13785 Assert(n_cells() > 0,
13786 ExcMessage("Error: An empty Triangulation can not be refined."));
13787
13788 for (unsigned int i = 0; i < times; ++i)
13789 {
13790 set_all_refine_flags();
13791 execute_coarsening_and_refinement();
13792 }
13793}
13794
13795
13796
13797template <int dim, int spacedim>
13799void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
13800{
13801 for (unsigned int i = 0; i < times; ++i)
13802 {
13803 for (const auto &cell : this->active_cell_iterators())
13804 {
13805 cell->clear_refine_flag();
13806 cell->set_coarsen_flag();
13807 }
13808 execute_coarsening_and_refinement();
13809 }
13810}
13811
13812
13813#endif
13814/*-------------------- refine/coarsen flags -------------------------*/
13815
13816#ifndef DOXYGEN
13817
13818template <int dim, int spacedim>
13820void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
13821{
13822 v.resize(dim * n_active_cells(), false);
13823 std::vector<bool>::iterator i = v.begin();
13824
13825 for (const auto &cell : this->active_cell_iterators())
13826 for (unsigned int j = 0; j < dim; ++j, ++i)
13827 if (cell->refine_flag_set() & (1 << j))
13828 *i = true;
13829
13830 Assert(i == v.end(), ExcInternalError());
13831}
13832
13833
13834
13835template <int dim, int spacedim>
13837void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
13838{
13839 std::vector<bool> v;
13840 save_refine_flags(v);
13841 write_bool_vector(mn_tria_refine_flags_begin,
13842 v,
13844 out);
13845}
13846
13847
13848
13849template <int dim, int spacedim>
13852{
13853 std::vector<bool> v;
13854 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
13855 load_refine_flags(v);
13856}
13857
13858
13859
13860template <int dim, int spacedim>
13862void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
13863{
13864 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
13865
13866 std::vector<bool>::const_iterator i = v.begin();
13867 for (const auto &cell : this->active_cell_iterators())
13868 {
13869 unsigned int ref_case = 0;
13870
13871 for (unsigned int j = 0; j < dim; ++j, ++i)
13872 if (*i == true)
13873 ref_case += 1 << j;
13875 ExcGridReadError());
13876 if (ref_case > 0)
13877 cell->set_refine_flag(RefinementCase<dim>(ref_case));
13878 else
13879 cell->clear_refine_flag();
13880 }
13881
13882 Assert(i == v.end(), ExcInternalError());
13883}
13884
13885
13886
13887template <int dim, int spacedim>
13890 std::vector<bool> &v) const
13891{
13892 v.resize(n_active_cells(), false);
13893 std::vector<bool>::iterator i = v.begin();
13894 for (const auto &cell : this->active_cell_iterators())
13895 {
13896 *i = cell->coarsen_flag_set();
13897 ++i;
13898 }
13899
13900 Assert(i == v.end(), ExcInternalError());
13901}
13902
13903
13904
13905template <int dim, int spacedim>
13907void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13908{
13909 std::vector<bool> v;
13910 save_coarsen_flags(v);
13911 write_bool_vector(mn_tria_coarsen_flags_begin,
13912 v,
13914 out);
13915}
13916
13917
13918
13919template <int dim, int spacedim>
13922{
13923 std::vector<bool> v;
13924 read_bool_vector(mn_tria_coarsen_flags_begin,
13925 v,
13927 in);
13928 load_coarsen_flags(v);
13929}
13930
13931
13932
13933template <int dim, int spacedim>
13936 const std::vector<bool> &v)
13937{
13938 Assert(v.size() == n_active_cells(), ExcGridReadError());
13939
13940 std::vector<bool>::const_iterator i = v.begin();
13941 for (const auto &cell : this->active_cell_iterators())
13942 {
13943 if (*i == true)
13944 cell->set_coarsen_flag();
13945 else
13946 cell->clear_coarsen_flag();
13947 ++i;
13948 }
13949
13950 Assert(i == v.end(), ExcInternalError());
13951}
13952
13953
13954template <int dim, int spacedim>
13957{
13958 return anisotropic_refinement;
13959}
13960
13961
13962#endif
13963
13964namespace internal
13965{
13966 namespace
13967 {
13968 template <int dim, int spacedim>
13969 std::vector<std::vector<bool>>
13970 extract_raw_coarsen_flags(
13971 const std::vector<
13972 std::unique_ptr<::internal::TriangulationImplementation::
13973 TriaLevel<dim, spacedim>>> &levels)
13974 {
13975 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13976 for (unsigned int level = 0; level < levels.size(); ++level)
13977 coarsen_flags[level] = levels[level]->coarsen_flags;
13978 return coarsen_flags;
13979 }
13980
13981 template <int dim, int spacedim>
13982 std::vector<std::vector<std::uint8_t>>
13983 extract_raw_refine_flags(
13984 const std::vector<
13985 std::unique_ptr<::internal::TriangulationImplementation::
13986 TriaLevel<dim, spacedim>>> &levels)
13987 {
13988 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13989 for (unsigned int level = 0; level < levels.size(); ++level)
13990 refine_flags[level] = levels[level]->refine_flags;
13991 return refine_flags;
13992 }
13993 } // namespace
13994} // namespace internal
13995
13996
13997/*-------------------- user data/flags -------------------------*/
13998
13999
14000namespace
14001{
14002 // clear user data of cells
14003 template <int dim, int spacedim>
14004 void
14005 clear_user_data(
14006 std::vector<std::unique_ptr<
14008 {
14009 for (auto &level : levels)
14010 level->cells.clear_user_data();
14011 }
14012
14013
14014 // clear user data of faces
14015 template <int dim>
14016 void
14018 {
14019 if (dim == 2)
14020 {
14021 faces->lines.clear_user_data();
14022 }
14023
14024
14025 if (dim == 3)
14026 {
14027 faces->lines.clear_user_data();
14028 faces->quads.clear_user_data();
14029 }
14030 }
14031} // namespace
14032
14033#ifndef DOXYGEN
14034
14035template <int dim, int spacedim>
14038{
14039 // let functions in anonymous namespace do their work
14040 ::clear_user_data(levels);
14041 if (dim > 1)
14042 ::clear_user_data(faces.get());
14043}
14044
14045
14046
14047namespace
14048{
14049 template <int dim, int spacedim>
14050 void
14051 clear_user_flags_line(
14052 std::vector<std::unique_ptr<
14055 {
14056 if (dim == 1)
14057 {
14058 for (const auto &level : levels)
14059 level->cells.clear_user_flags();
14060 }
14061 else if (dim == 2 || dim == 3)
14062 {
14063 faces->lines.clear_user_flags();
14064 }
14065 else
14066 {
14068 }
14069 }
14070} // namespace
14071
14072
14073template <int dim, int spacedim>
14076{
14077 ::clear_user_flags_line(levels, faces.get());
14078}
14079
14080
14081
14082namespace
14083{
14084 template <int dim, int spacedim>
14085 void
14086 clear_user_flags_quad(
14087 std::vector<std::unique_ptr<
14090 {
14091 if (dim == 1)
14092 {
14093 // nothing to do in 1d
14094 }
14095 else if (dim == 2)
14096 {
14097 for (const auto &level : levels)
14098 level->cells.clear_user_flags();
14099 }
14100 else if (dim == 3)
14101 {
14102 faces->quads.clear_user_flags();
14103 }
14104 else
14105 {
14107 }
14108 }
14109} // namespace
14110
14111
14112template <int dim, int spacedim>
14115{
14116 ::clear_user_flags_quad(levels, faces.get());
14117}
14118
14119
14120
14121namespace
14122{
14123 template <int dim, int spacedim>
14124 void
14125 clear_user_flags_hex(
14126 std::vector<std::unique_ptr<
14129 {
14130 if (dim == 1)
14131 {
14132 // nothing to do in 1d
14133 }
14134 else if (dim == 2)
14135 {
14136 // nothing to do in 2d
14137 }
14138 else if (dim == 3)
14139 {
14140 for (const auto &level : levels)
14141 level->cells.clear_user_flags();
14142 }
14143 else
14144 {
14146 }
14147 }
14148} // namespace
14149
14150
14151template <int dim, int spacedim>
14154{
14155 ::clear_user_flags_hex(levels, faces.get());
14156}
14157
14158
14159
14160template <int dim, int spacedim>
14163{
14164 clear_user_flags_line();
14165 clear_user_flags_quad();
14166 clear_user_flags_hex();
14167}
14168
14169
14170
14171template <int dim, int spacedim>
14173void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
14174{
14175 save_user_flags_line(out);
14176
14177 if (dim >= 2)
14178 save_user_flags_quad(out);
14179
14180 if (dim >= 3)
14181 save_user_flags_hex(out);
14182
14183 if (dim >= 4)
14185}
14186
14187
14188
14189template <int dim, int spacedim>
14191void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
14192{
14193 // clear vector and append
14194 // all the stuff later on
14195 v.clear();
14196
14197 std::vector<bool> tmp;
14198
14199 save_user_flags_line(tmp);
14200 v.insert(v.end(), tmp.begin(), tmp.end());
14201
14202 if (dim >= 2)
14203 {
14204 save_user_flags_quad(tmp);
14205 v.insert(v.end(), tmp.begin(), tmp.end());
14206 }
14207
14208 if (dim >= 3)
14209 {
14210 save_user_flags_hex(tmp);
14211 v.insert(v.end(), tmp.begin(), tmp.end());
14212 }
14213
14214 if (dim >= 4)
14216}
14217
14218
14219
14220template <int dim, int spacedim>
14223{
14224 load_user_flags_line(in);
14225
14226 if (dim >= 2)
14227 load_user_flags_quad(in);
14228
14229 if (dim >= 3)
14230 load_user_flags_hex(in);
14231
14232 if (dim >= 4)
14234}
14235
14236
14237
14238template <int dim, int spacedim>
14240void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
14241{
14242 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14243 std::vector<bool> tmp;
14244
14245 // first extract the flags
14246 // belonging to lines
14247 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14248 // and set the lines
14249 load_user_flags_line(tmp);
14250
14251 if (dim >= 2)
14252 {
14253 tmp.clear();
14254 tmp.insert(tmp.end(),
14255 v.begin() + n_lines(),
14256 v.begin() + n_lines() + n_quads());
14257 load_user_flags_quad(tmp);
14258 }
14259
14260 if (dim >= 3)
14261 {
14262 tmp.clear();
14263 tmp.insert(tmp.end(),
14264 v.begin() + n_lines() + n_quads(),
14265 v.begin() + n_lines() + n_quads() + n_hexs());
14266 load_user_flags_hex(tmp);
14267 }
14268
14269 if (dim >= 4)
14271}
14272
14273
14274
14275template <int dim, int spacedim>
14278 std::vector<bool> &v) const
14279{
14280 v.resize(n_lines(), false);
14281 std::vector<bool>::iterator i = v.begin();
14282 line_iterator line = begin_line(), endl = end_line();
14283 for (; line != endl; ++line, ++i)
14284 *i = line->user_flag_set();
14285
14286 Assert(i == v.end(), ExcInternalError());
14287}
14288
14289
14290
14291template <int dim, int spacedim>
14293void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
14294{
14295 std::vector<bool> v;
14296 save_user_flags_line(v);
14297 write_bool_vector(mn_tria_line_user_flags_begin,
14298 v,
14300 out);
14301}
14302
14303
14304
14305template <int dim, int spacedim>
14308{
14309 std::vector<bool> v;
14310 read_bool_vector(mn_tria_line_user_flags_begin,
14311 v,
14313 in);
14314 load_user_flags_line(v);
14315}
14316
14317
14318
14319template <int dim, int spacedim>
14322 const std::vector<bool> &v)
14323{
14324 Assert(v.size() == n_lines(), ExcGridReadError());
14325
14326 line_iterator line = begin_line(), endl = end_line();
14327 std::vector<bool>::const_iterator i = v.begin();
14328 for (; line != endl; ++line, ++i)
14329 if (*i == true)
14330 line->set_user_flag();
14331 else
14332 line->clear_user_flag();
14333
14334 Assert(i == v.end(), ExcInternalError());
14335}
14336
14337#endif
14338
14339namespace
14340{
14341 template <typename Iterator>
14342 bool
14343 get_user_flag(const Iterator &i)
14344 {
14345 return i->user_flag_set();
14346 }
14347
14348
14349
14350 template <int structdim, int dim, int spacedim>
14351 bool
14353 {
14355 return false;
14356 }
14357
14358
14359
14360 template <typename Iterator>
14361 void
14362 set_user_flag(const Iterator &i)
14363 {
14364 i->set_user_flag();
14365 }
14366
14367
14368
14369 template <int structdim, int dim, int spacedim>
14370 void
14372 {
14374 }
14375
14376
14377
14378 template <typename Iterator>
14379 void
14380 clear_user_flag(const Iterator &i)
14381 {
14382 i->clear_user_flag();
14383 }
14384
14385
14386
14387 template <int structdim, int dim, int spacedim>
14388 void
14389 clear_user_flag(
14391 {
14393 }
14394} // namespace
14395
14396#ifndef DOXYGEN
14397
14398template <int dim, int spacedim>
14401 std::vector<bool> &v) const
14402{
14403 v.resize(n_quads(), false);
14404
14405 if (dim >= 2)
14406 {
14407 std::vector<bool>::iterator i = v.begin();
14408 quad_iterator quad = begin_quad(), endq = end_quad();
14409 for (; quad != endq; ++quad, ++i)
14410 *i = get_user_flag(quad);
14411
14412 Assert(i == v.end(), ExcInternalError());
14413 }
14414}
14415
14416
14417
14418template <int dim, int spacedim>
14420void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
14421{
14422 std::vector<bool> v;
14423 save_user_flags_quad(v);
14424 write_bool_vector(mn_tria_quad_user_flags_begin,
14425 v,
14427 out);
14428}
14429
14430
14431
14432template <int dim, int spacedim>
14435{
14436 std::vector<bool> v;
14437 read_bool_vector(mn_tria_quad_user_flags_begin,
14438 v,
14440 in);
14441 load_user_flags_quad(v);
14442}
14443
14444
14445
14446template <int dim, int spacedim>
14449 const std::vector<bool> &v)
14450{
14451 Assert(v.size() == n_quads(), ExcGridReadError());
14452
14453 if (dim >= 2)
14454 {
14455 quad_iterator quad = begin_quad(), endq = end_quad();
14456 std::vector<bool>::const_iterator i = v.begin();
14457 for (; quad != endq; ++quad, ++i)
14458 if (*i == true)
14459 set_user_flag(quad);
14460 else
14461 clear_user_flag(quad);
14462
14463 Assert(i == v.end(), ExcInternalError());
14464 }
14465}
14466
14467
14468
14469template <int dim, int spacedim>
14472 std::vector<bool> &v) const
14473{
14474 v.resize(n_hexs(), false);
14475
14476 if (dim >= 3)
14477 {
14478 std::vector<bool>::iterator i = v.begin();
14479 hex_iterator hex = begin_hex(), endh = end_hex();
14480 for (; hex != endh; ++hex, ++i)
14481 *i = get_user_flag(hex);
14482
14483 Assert(i == v.end(), ExcInternalError());
14484 }
14485}
14486
14487
14488
14489template <int dim, int spacedim>
14491void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
14492{
14493 std::vector<bool> v;
14494 save_user_flags_hex(v);
14495 write_bool_vector(mn_tria_hex_user_flags_begin,
14496 v,
14498 out);
14499}
14500
14501
14502
14503template <int dim, int spacedim>
14506{
14507 std::vector<bool> v;
14508 read_bool_vector(mn_tria_hex_user_flags_begin,
14509 v,
14511 in);
14512 load_user_flags_hex(v);
14513}
14514
14515
14516
14517template <int dim, int spacedim>
14520 const std::vector<bool> &v)
14521{
14522 Assert(v.size() == n_hexs(), ExcGridReadError());
14523
14524 if (dim >= 3)
14525 {
14526 hex_iterator hex = begin_hex(), endh = end_hex();
14527 std::vector<bool>::const_iterator i = v.begin();
14528 for (; hex != endh; ++hex, ++i)
14529 if (*i == true)
14530 set_user_flag(hex);
14531 else
14532 clear_user_flag(hex);
14533
14534 Assert(i == v.end(), ExcInternalError());
14535 }
14536}
14537
14538
14539
14540template <int dim, int spacedim>
14543 std::vector<unsigned int> &v) const
14544{
14545 // clear vector and append all the
14546 // stuff later on
14547 v.clear();
14548
14549 std::vector<unsigned int> tmp;
14550
14551 save_user_indices_line(tmp);
14552 v.insert(v.end(), tmp.begin(), tmp.end());
14553
14554 if (dim >= 2)
14555 {
14556 save_user_indices_quad(tmp);
14557 v.insert(v.end(), tmp.begin(), tmp.end());
14558 }
14559
14560 if (dim >= 3)
14561 {
14562 save_user_indices_hex(tmp);
14563 v.insert(v.end(), tmp.begin(), tmp.end());
14564 }
14565
14566 if (dim >= 4)
14568}
14569
14570
14571
14572template <int dim, int spacedim>
14575 const std::vector<unsigned int> &v)
14576{
14577 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14578 std::vector<unsigned int> tmp;
14579
14580 // first extract the indices
14581 // belonging to lines
14582 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14583 // and set the lines
14584 load_user_indices_line(tmp);
14585
14586 if (dim >= 2)
14587 {
14588 tmp.clear();
14589 tmp.insert(tmp.end(),
14590 v.begin() + n_lines(),
14591 v.begin() + n_lines() + n_quads());
14592 load_user_indices_quad(tmp);
14593 }
14594
14595 if (dim >= 3)
14596 {
14597 tmp.clear();
14598 tmp.insert(tmp.end(),
14599 v.begin() + n_lines() + n_quads(),
14600 v.begin() + n_lines() + n_quads() + n_hexs());
14601 load_user_indices_hex(tmp);
14602 }
14603
14604 if (dim >= 4)
14606}
14607
14608
14609
14610template <int dim, int spacedim>
14612void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
14613{
14614 // Save triangulation information.
14615 {
14616 std::ofstream ofs_tria(file_basename + "_triangulation.data");
14617 AssertThrow(ofs_tria.fail() == false, ExcIO());
14618
14619 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
14620 save(oa,
14622 }
14623
14624 // Save attached data.
14625 {
14626 std::ofstream ofs_info(file_basename + ".info");
14627 ofs_info
14628 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
14629 << std::endl
14631 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
14632 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
14633 << this->n_global_active_cells() << std::endl;
14634 }
14635
14636 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
14637}
14638
14639
14640
14641template <int dim, int spacedim>
14643void Triangulation<dim, spacedim>::load(const std::string &file_basename)
14644{
14645 // It's probably prudent to first get rid of any all content of the
14646 // triangulation, rather than hope that the deserialization below
14647 // overwrites everything:
14648 clear();
14649
14650 // Load triangulation information.
14651 {
14652 std::ifstream ifs_tria(file_basename + "_triangulation.data");
14653 AssertThrow(ifs_tria.fail() == false, ExcIO());
14654
14655 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
14656 load(ia,
14658 }
14659
14660 // Load attached data.
14661 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
14662 n_global_active_cells;
14663 {
14664 std::ifstream ifs_info(std::string(file_basename) + ".info");
14665 AssertThrow(ifs_info.fail() == false, ExcIO());
14666 std::string firstline;
14667 std::getline(ifs_info, firstline);
14668 ifs_info >> version >> numcpus >> attached_count_fixed >>
14669 attached_count_variable >> n_global_active_cells;
14670 }
14671
14672 AssertThrow(numcpus == 1,
14673 ExcMessage("Incompatible number of CPUs found in .info file."));
14674
14675 const auto expected_version =
14677 spacedim>::version_number;
14678 AssertThrow(version == expected_version,
14679 ExcMessage(
14680 "The information saved in the file you are trying "
14681 "to read the triangulation from was written with an "
14682 "incompatible file format version and cannot be read."));
14683 Assert(this->n_global_active_cells() == n_global_active_cells,
14684 ExcMessage("The number of cells of the triangulation differs "
14685 "from the number of cells written into the .info file."));
14686
14687 // Clear all of the callback data, as explained in the documentation of
14688 // register_data_attach().
14689 this->cell_attached_data.n_attached_data_sets = 0;
14690 this->cell_attached_data.n_attached_deserialize =
14691 attached_count_fixed + attached_count_variable;
14692
14693 this->load_attached_data(0,
14694 this->n_global_active_cells(),
14695 this->n_active_cells(),
14696 file_basename,
14697 attached_count_fixed,
14698 attached_count_variable);
14699
14700 this->update_cell_relations();
14701}
14702
14703#endif
14704namespace
14705{
14706 template <typename Iterator>
14707 unsigned int
14708 get_user_index(const Iterator &i)
14709 {
14710 return i->user_index();
14711 }
14712
14713
14714
14715 template <int structdim, int dim, int spacedim>
14716 unsigned int
14717 get_user_index(
14719 {
14722 }
14723
14724
14725
14726 template <typename Iterator>
14727 void
14728 set_user_index(const Iterator &i, const unsigned int x)
14729 {
14730 i->set_user_index(x);
14731 }
14732
14733
14734
14735 template <int structdim, int dim, int spacedim>
14736 void
14737 set_user_index(
14739 const unsigned int)
14740 {
14742 }
14743} // namespace
14744
14745#ifndef DOXYGEN
14746
14747template <int dim, int spacedim>
14750 std::vector<unsigned int> &v) const
14751{
14752 v.resize(n_lines(), 0);
14753 std::vector<unsigned int>::iterator i = v.begin();
14754 line_iterator line = begin_line(), endl = end_line();
14755 for (; line != endl; ++line, ++i)
14756 *i = line->user_index();
14757}
14758
14759
14760
14761template <int dim, int spacedim>
14764 const std::vector<unsigned int> &v)
14765{
14766 Assert(v.size() == n_lines(), ExcGridReadError());
14767
14768 line_iterator line = begin_line(), endl = end_line();
14769 std::vector<unsigned int>::const_iterator i = v.begin();
14770 for (; line != endl; ++line, ++i)
14771 line->set_user_index(*i);
14772}
14773
14774
14775template <int dim, int spacedim>
14778 std::vector<unsigned int> &v) const
14779{
14780 v.resize(n_quads(), 0);
14781
14782 if (dim >= 2)
14783 {
14784 std::vector<unsigned int>::iterator i = v.begin();
14785 quad_iterator quad = begin_quad(), endq = end_quad();
14786 for (; quad != endq; ++quad, ++i)
14787 *i = get_user_index(quad);
14788 }
14789}
14790
14791
14792
14793template <int dim, int spacedim>
14796 const std::vector<unsigned int> &v)
14797{
14798 Assert(v.size() == n_quads(), ExcGridReadError());
14799
14800 if (dim >= 2)
14801 {
14802 quad_iterator quad = begin_quad(), endq = end_quad();
14803 std::vector<unsigned int>::const_iterator i = v.begin();
14804 for (; quad != endq; ++quad, ++i)
14805 set_user_index(quad, *i);
14806 }
14807}
14808
14809
14810template <int dim, int spacedim>
14813 std::vector<unsigned int> &v) const
14814{
14815 v.resize(n_hexs(), 0);
14816
14817 if (dim >= 3)
14818 {
14819 std::vector<unsigned int>::iterator i = v.begin();
14820 hex_iterator hex = begin_hex(), endh = end_hex();
14821 for (; hex != endh; ++hex, ++i)
14822 *i = get_user_index(hex);
14823 }
14824}
14825
14826
14827
14828template <int dim, int spacedim>
14831 const std::vector<unsigned int> &v)
14832{
14833 Assert(v.size() == n_hexs(), ExcGridReadError());
14834
14835 if (dim >= 3)
14836 {
14837 hex_iterator hex = begin_hex(), endh = end_hex();
14838 std::vector<unsigned int>::const_iterator i = v.begin();
14839 for (; hex != endh; ++hex, ++i)
14840 set_user_index(hex, *i);
14841 }
14842}
14843
14844#endif
14845
14846
14847//---------------- user pointers ----------------------------------------//
14848
14849
14850namespace
14851{
14852 template <typename Iterator>
14853 void *
14854 get_user_pointer(const Iterator &i)
14855 {
14856 return i->user_pointer();
14857 }
14858
14859
14860
14861 template <int structdim, int dim, int spacedim>
14862 void *
14863 get_user_pointer(
14865 {
14867 return nullptr;
14868 }
14869
14870
14871
14872 template <typename Iterator>
14873 void
14874 set_user_pointer(const Iterator &i, void *x)
14875 {
14876 i->set_user_pointer(x);
14877 }
14878
14879
14880
14881 template <int structdim, int dim, int spacedim>
14882 void
14883 set_user_pointer(
14885 void *)
14886 {
14888 }
14889} // namespace
14890
14891#ifndef DOXYGEN
14892
14893template <int dim, int spacedim>
14896 std::vector<void *> &v) const
14897{
14898 // clear vector and append all the
14899 // stuff later on
14900 v.clear();
14901
14902 std::vector<void *> tmp;
14903
14904 save_user_pointers_line(tmp);
14905 v.insert(v.end(), tmp.begin(), tmp.end());
14906
14907 if (dim >= 2)
14908 {
14909 save_user_pointers_quad(tmp);
14910 v.insert(v.end(), tmp.begin(), tmp.end());
14911 }
14912
14913 if (dim >= 3)
14914 {
14915 save_user_pointers_hex(tmp);
14916 v.insert(v.end(), tmp.begin(), tmp.end());
14917 }
14918
14919 if (dim >= 4)
14921}
14922
14923
14924
14925template <int dim, int spacedim>
14928 const std::vector<void *> &v)
14929{
14930 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14931 std::vector<void *> tmp;
14932
14933 // first extract the pointers
14934 // belonging to lines
14935 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14936 // and set the lines
14937 load_user_pointers_line(tmp);
14938
14939 if (dim >= 2)
14940 {
14941 tmp.clear();
14942 tmp.insert(tmp.end(),
14943 v.begin() + n_lines(),
14944 v.begin() + n_lines() + n_quads());
14945 load_user_pointers_quad(tmp);
14946 }
14947
14948 if (dim >= 3)
14949 {
14950 tmp.clear();
14951 tmp.insert(tmp.end(),
14952 v.begin() + n_lines() + n_quads(),
14953 v.begin() + n_lines() + n_quads() + n_hexs());
14954 load_user_pointers_hex(tmp);
14955 }
14956
14957 if (dim >= 4)
14959}
14960
14961
14962
14963template <int dim, int spacedim>
14966 std::vector<void *> &v) const
14967{
14968 v.resize(n_lines(), nullptr);
14969 std::vector<void *>::iterator i = v.begin();
14970 line_iterator line = begin_line(), endl = end_line();
14971 for (; line != endl; ++line, ++i)
14972 *i = line->user_pointer();
14973}
14974
14975
14976
14977template <int dim, int spacedim>
14980 const std::vector<void *> &v)
14981{
14982 Assert(v.size() == n_lines(), ExcGridReadError());
14983
14984 line_iterator line = begin_line(), endl = end_line();
14985 std::vector<void *>::const_iterator i = v.begin();
14986 for (; line != endl; ++line, ++i)
14987 line->set_user_pointer(*i);
14988}
14989
14990
14991
14992template <int dim, int spacedim>
14995 std::vector<void *> &v) const
14996{
14997 v.resize(n_quads(), nullptr);
14998
14999 if (dim >= 2)
15000 {
15001 std::vector<void *>::iterator i = v.begin();
15002 quad_iterator quad = begin_quad(), endq = end_quad();
15003 for (; quad != endq; ++quad, ++i)
15004 *i = get_user_pointer(quad);
15005 }
15006}
15007
15008
15009
15010template <int dim, int spacedim>
15013 const std::vector<void *> &v)
15014{
15015 Assert(v.size() == n_quads(), ExcGridReadError());
15016
15017 if (dim >= 2)
15018 {
15019 quad_iterator quad = begin_quad(), endq = end_quad();
15020 std::vector<void *>::const_iterator i = v.begin();
15021 for (; quad != endq; ++quad, ++i)
15022 set_user_pointer(quad, *i);
15023 }
15024}
15025
15026
15027template <int dim, int spacedim>
15030 std::vector<void *> &v) const
15031{
15032 v.resize(n_hexs(), nullptr);
15033
15034 if (dim >= 3)
15035 {
15036 std::vector<void *>::iterator i = v.begin();
15037 hex_iterator hex = begin_hex(), endh = end_hex();
15038 for (; hex != endh; ++hex, ++i)
15039 *i = get_user_pointer(hex);
15040 }
15041}
15042
15043
15044
15045template <int dim, int spacedim>
15048 const std::vector<void *> &v)
15049{
15050 Assert(v.size() == n_hexs(), ExcGridReadError());
15051
15052 if (dim >= 3)
15053 {
15054 hex_iterator hex = begin_hex(), endh = end_hex();
15055 std::vector<void *>::const_iterator i = v.begin();
15056 for (; hex != endh; ++hex, ++i)
15057 set_user_pointer(hex, *i);
15058 }
15059}
15060
15061#endif
15062
15063/*------------------------ Cell iterator functions ------------------------*/
15064
15065#ifndef DOXYGEN
15066
15067template <int dim, int spacedim>
15070 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
15071{
15072 switch (dim)
15073 {
15074 case 1:
15075 return begin_raw_line(level);
15076 case 2:
15077 return begin_raw_quad(level);
15078 case 3:
15079 return begin_raw_hex(level);
15080 default:
15082 return raw_cell_iterator();
15083 }
15084}
15085
15086
15087
15088template <int dim, int spacedim>
15091 Triangulation<dim, spacedim>::begin(const unsigned int level) const
15092{
15093 switch (dim)
15094 {
15095 case 1:
15096 return begin_line(level);
15097 case 2:
15098 return begin_quad(level);
15099 case 3:
15100 return begin_hex(level);
15101 default:
15102 Assert(false, ExcImpossibleInDim(dim));
15103 return cell_iterator();
15104 }
15105}
15106
15107
15108
15109template <int dim, int spacedim>
15112 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
15113{
15114 switch (dim)
15115 {
15116 case 1:
15117 return begin_active_line(level);
15118 case 2:
15119 return begin_active_quad(level);
15120 case 3:
15121 return begin_active_hex(level);
15122 default:
15124 return active_cell_iterator();
15125 }
15126}
15127
15128
15129
15130template <int dim, int spacedim>
15134{
15135 const unsigned int level = levels.size() - 1;
15136 if (levels[level]->cells.n_objects() == 0)
15137 return end(level);
15138
15139 // find the last raw iterator on
15140 // this level
15141 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
15142 level,
15143 levels[level]->cells.n_objects() - 1);
15144
15145 // then move to the last used one
15146 if (ri->used() == true)
15147 return ri;
15148 while ((--ri).state() == IteratorState::valid)
15149 if (ri->used() == true)
15150 return ri;
15151 return ri;
15152}
15153
15154
15155
15156template <int dim, int spacedim>
15160{
15161 // get the last used cell
15162 cell_iterator cell = last();
15163
15164 if (cell != end())
15165 {
15166 // then move to the last active one
15167 if (cell->is_active() == true)
15168 return cell;
15169 while ((--cell).state() == IteratorState::valid)
15170 if (cell->is_active() == true)
15171 return cell;
15172 }
15173 return cell;
15174}
15175
15176
15177
15178template <int dim, int spacedim>
15182 const CellId &cell_id) const
15183{
15184 Assert(
15185 this->contains_cell(cell_id),
15186 ExcMessage(
15187 "CellId is invalid for this triangulation.\n"
15188 "Either the provided CellId does not correspond to a cell in this "
15189 "triangulation object, or, in case you are using a parallel "
15190 "triangulation, may correspond to an artificial cell that is less "
15191 "refined on this processor. In the case of "
15192 "parallel::fullydistributed::Triangulation, the corresponding coarse "
15193 "cell might not be accessible by the current process."));
15194
15195 cell_iterator cell(
15196 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
15197
15198 for (const auto &child_index : cell_id.get_child_indices())
15199 cell = cell->child(static_cast<unsigned int>(child_index));
15200
15201 return cell;
15202}
15203
15204
15205
15206template <int dim, int spacedim>
15208bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
15209{
15210 const auto coarse_cell_index =
15211 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
15212
15213 if (coarse_cell_index == numbers::invalid_unsigned_int)
15214 return false;
15215
15216 cell_iterator cell(this, 0, coarse_cell_index);
15217
15218 for (const auto &child_index : cell_id.get_child_indices())
15219 {
15220 if (cell->has_children() == false)
15221 return false;
15222 cell = cell->child(static_cast<unsigned int>(child_index));
15223 }
15224
15225 return true;
15226}
15227
15228
15229
15230template <int dim, int spacedim>
15234{
15235 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15236 -1,
15237 -1);
15238}
15239
15240
15241
15242template <int dim, int spacedim>
15245 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
15246{
15247 // This function may be called on parallel triangulations on levels
15248 // that exist globally, but not on the local portion of the
15249 // triangulation. In that case, just return the end iterator.
15250 //
15251 // We need to use levels.size() instead of n_levels() because the
15252 // latter function uses the cache, but we need to be able to call
15253 // this function at a time when the cache is not currently up to
15254 // date.
15255 if (level >= levels.size())
15256 {
15257 Assert(level < n_global_levels(),
15258 ExcInvalidLevel(level, n_global_levels()));
15259 return end();
15260 }
15261
15262 // Query whether the given level is valid for the local portion of the
15263 // triangulation.
15264 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15265 if (level < levels.size() - 1)
15266 return begin_raw(level + 1);
15267 else
15268 return end();
15269}
15270
15271
15272template <int dim, int spacedim>
15275 Triangulation<dim, spacedim>::end(const unsigned int level) const
15276{
15277 // This function may be called on parallel triangulations on levels
15278 // that exist globally, but not on the local portion of the
15279 // triangulation. In that case, just return the end iterator.
15280 //
15281 // We need to use levels.size() instead of n_levels() because the
15282 // latter function uses the cache, but we need to be able to call
15283 // this function at a time when the cache is not currently up to
15284 // date.
15285 if (level >= levels.size())
15286 {
15287 Assert(level < n_global_levels(),
15288 ExcInvalidLevel(level, n_global_levels()));
15289 return end();
15290 }
15291
15292 // Query whether the given level is valid for the local portion of the
15293 // triangulation.
15294 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15295 if (level < levels.size() - 1)
15296 return begin(level + 1);
15297 else
15298 return end();
15299}
15300
15301
15302template <int dim, int spacedim>
15305 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
15306{
15307 // This function may be called on parallel triangulations on levels
15308 // that exist globally, but not on the local portion of the
15309 // triangulation. In that case, just return the end iterator.
15310 //
15311 // We need to use levels.size() instead of n_levels() because the
15312 // latter function uses the cache, but we need to be able to call
15313 // this function at a time when the cache is not currently up to
15314 // date.
15315 if (level >= levels.size())
15316 {
15317 Assert(level < n_global_levels(),
15318 ExcInvalidLevel(level, n_global_levels()));
15319 return end();
15320 }
15321
15322 // Query whether the given level is valid for the local portion of the
15323 // triangulation.
15324 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15325 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
15326 begin_active(level + 1));
15327}
15328
15329
15330
15331template <int dim, int spacedim>
15335 const
15336{
15338 begin(), end());
15339}
15340
15341
15342template <int dim, int spacedim>
15345 active_cell_iterator> Triangulation<dim, spacedim>::
15347{
15348 return IteratorRange<
15350 end());
15351}
15352
15353
15354
15355template <int dim, int spacedim>
15358 cell_iterator> Triangulation<dim, spacedim>::
15359 cell_iterators_on_level(const unsigned int level) const
15360{
15362 begin(level), end(level));
15363}
15364
15365
15366
15367template <int dim, int spacedim>
15370 active_cell_iterator> Triangulation<dim, spacedim>::
15371 active_cell_iterators_on_level(const unsigned int level) const
15372{
15373 return IteratorRange<
15375 begin_active(level), end_active(level));
15376}
15377#endif
15378
15379/*------------------------ Face iterator functions ------------------------*/
15380
15381#ifndef DOXYGEN
15382
15383template <int dim, int spacedim>
15387{
15388 switch (dim)
15389 {
15390 case 1:
15391 Assert(false, ExcImpossibleInDim(1));
15392 return raw_face_iterator();
15393 case 2:
15394 return begin_line();
15395 case 3:
15396 return begin_quad();
15397 default:
15399 return face_iterator();
15400 }
15401}
15402
15403
15404
15405template <int dim, int spacedim>
15409{
15410 switch (dim)
15411 {
15412 case 1:
15413 Assert(false, ExcImpossibleInDim(1));
15414 return raw_face_iterator();
15415 case 2:
15416 return begin_active_line();
15417 case 3:
15418 return begin_active_quad();
15419 default:
15421 return active_face_iterator();
15422 }
15423}
15424
15425
15426
15427template <int dim, int spacedim>
15431{
15432 switch (dim)
15433 {
15434 case 1:
15435 Assert(false, ExcImpossibleInDim(1));
15436 return raw_face_iterator();
15437 case 2:
15438 return end_line();
15439 case 3:
15440 return end_quad();
15441 default:
15443 return raw_face_iterator();
15444 }
15445}
15446
15447
15448
15449template <int dim, int spacedim>
15452 active_face_iterator> Triangulation<dim, spacedim>::
15454{
15455 return IteratorRange<
15457 begin_active_face(), end_face());
15458}
15459
15460/*------------------------ Vertex iterator functions ------------------------*/
15461
15462
15463template <int dim, int spacedim>
15467{
15468 vertex_iterator i =
15469 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15470 if (i.state() != IteratorState::valid)
15471 return i;
15472 // This loop will end because every triangulation has used vertices.
15473 while (i->used() == false)
15474 if ((++i).state() != IteratorState::valid)
15475 return i;
15476 return i;
15477}
15478
15479
15480
15481template <int dim, int spacedim>
15485{
15486 // every vertex is active
15487 return begin_vertex();
15488}
15489
15490
15491
15492template <int dim, int spacedim>
15496{
15497 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15498 -1,
15500}
15501
15502#endif
15503
15504
15505/*------------------------ Line iterator functions ------------------------*/
15506
15507#ifndef DOXYGEN
15508
15509template <int dim, int spacedim>
15512 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
15513{
15514 // This function may be called on parallel triangulations on levels
15515 // that exist globally, but not on the local portion of the
15516 // triangulation. In that case, just return the end iterator.
15517 //
15518 // We need to use levels.size() instead of n_levels() because the
15519 // latter function uses the cache, but we need to be able to call
15520 // this function at a time when the cache is not currently up to
15521 // date.
15522 if (level >= levels.size())
15523 {
15524 Assert(level < n_global_levels(),
15525 ExcInvalidLevel(level, n_global_levels()));
15526 return end_line();
15527 }
15528
15529 switch (dim)
15530 {
15531 case 1:
15532 // Query whether the given level is valid for the local portion of the
15533 // triangulation.
15534 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15535
15536 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15537 return end_line();
15538
15539 return raw_line_iterator(
15540 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15541
15542 default:
15543 Assert(level == 0, ExcFacesHaveNoLevel());
15544 return raw_line_iterator(
15545 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15546 }
15547}
15548
15549
15550template <int dim, int spacedim>
15553 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
15554{
15555 // level is checked in begin_raw
15556 raw_line_iterator ri = begin_raw_line(level);
15557 if (ri.state() != IteratorState::valid)
15558 return ri;
15559 while (ri->used() == false)
15560 if ((++ri).state() != IteratorState::valid)
15561 return ri;
15562 return ri;
15563}
15564
15565
15566
15567template <int dim, int spacedim>
15571 const unsigned int level) const
15572{
15573 // level is checked in begin_raw
15574 line_iterator i = begin_line(level);
15575 if (i.state() != IteratorState::valid)
15576 return i;
15577 while (i->has_children())
15578 if ((++i).state() != IteratorState::valid)
15579 return i;
15580 return i;
15581}
15582
15583
15584
15585template <int dim, int spacedim>
15589{
15590 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15591 -1,
15592 -1);
15593}
15594
15595#endif
15596
15597/*------------------------ Quad iterator functions ------------------------*/
15598
15599#ifndef DOXYGEN
15600
15601template <int dim, int spacedim>
15604 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
15605{
15606 // This function may be called on parallel triangulations on levels
15607 // that exist globally, but not on the local portion of the
15608 // triangulation. In that case, just return the end iterator.
15609 //
15610 // We need to use levels.size() instead of n_levels() because the
15611 // latter function uses the cache, but we need to be able to call
15612 // this function at a time when the cache is not currently up to
15613 // date.
15614 if (level >= levels.size())
15615 {
15616 Assert(level < n_global_levels(),
15617 ExcInvalidLevel(level, n_global_levels()));
15618 return end_quad();
15619 }
15620
15621 switch (dim)
15622 {
15623 case 1:
15624 Assert(false, ExcImpossibleInDim(1));
15625 return raw_hex_iterator();
15626 case 2:
15627 {
15628 // Query whether the given level is valid for the local portion of the
15629 // triangulation.
15630 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15631
15632 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15633 return end_quad();
15634
15635 return raw_quad_iterator(
15636 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15637 }
15638
15639 case 3:
15640 {
15641 Assert(level == 0, ExcFacesHaveNoLevel());
15642
15643 return raw_quad_iterator(
15644 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15645 }
15646
15647
15648 default:
15650 return raw_hex_iterator();
15651 }
15652}
15653
15654
15655
15656template <int dim, int spacedim>
15659 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
15660{
15661 // level is checked in begin_raw
15662 raw_quad_iterator ri = begin_raw_quad(level);
15663 if (ri.state() != IteratorState::valid)
15664 return ri;
15665 while (ri->used() == false)
15666 if ((++ri).state() != IteratorState::valid)
15667 return ri;
15668 return ri;
15669}
15670
15671
15672
15673template <int dim, int spacedim>
15677 const unsigned int level) const
15678{
15679 // level is checked in begin_raw
15680 quad_iterator i = begin_quad(level);
15681 if (i.state() != IteratorState::valid)
15682 return i;
15683 while (i->has_children())
15684 if ((++i).state() != IteratorState::valid)
15685 return i;
15686 return i;
15687}
15688
15689
15690
15691template <int dim, int spacedim>
15695{
15696 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15697 -1,
15698 -1);
15699}
15700
15701#endif
15702
15703/*------------------------ Hex iterator functions ------------------------*/
15704
15705#ifndef DOXYGEN
15706
15707template <int dim, int spacedim>
15710 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
15711{
15712 // This function may be called on parallel triangulations on levels
15713 // that exist globally, but not on the local portion of the
15714 // triangulation. In that case, just return the end iterator.
15715 //
15716 // We need to use levels.size() instead of n_levels() because the
15717 // latter function uses the cache, but we need to be able to call
15718 // this function at a time when the cache is not currently up to
15719 // date.
15720 if (level >= levels.size())
15721 {
15722 Assert(level < n_global_levels(),
15723 ExcInvalidLevel(level, n_global_levels()));
15724 return end_hex();
15725 }
15726
15727 switch (dim)
15728 {
15729 case 1:
15730 case 2:
15731 Assert(false, ExcImpossibleInDim(1));
15732 return raw_hex_iterator();
15733 case 3:
15734 {
15735 // Query whether the given level is valid for the local portion of the
15736 // triangulation.
15737 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15738
15739 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15740 return end_hex();
15741
15742 return raw_hex_iterator(
15743 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15744 }
15745
15746 default:
15748 return raw_hex_iterator();
15749 }
15750}
15751
15752
15753
15754template <int dim, int spacedim>
15757 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
15758{
15759 // level is checked in begin_raw
15760 raw_hex_iterator ri = begin_raw_hex(level);
15761 if (ri.state() != IteratorState::valid)
15762 return ri;
15763 while (ri->used() == false)
15764 if ((++ri).state() != IteratorState::valid)
15765 return ri;
15766 return ri;
15767}
15768
15769
15770
15771template <int dim, int spacedim>
15775{
15776 // level is checked in begin_raw
15777 hex_iterator i = begin_hex(level);
15778 if (i.state() != IteratorState::valid)
15779 return i;
15780 while (i->has_children())
15781 if ((++i).state() != IteratorState::valid)
15782 return i;
15783 return i;
15784}
15785
15786
15787
15788template <int dim, int spacedim>
15792{
15793 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15794 -1,
15795 -1);
15796}
15797
15798#endif
15799
15800// -------------------------------- number of cells etc ---------------
15801
15802
15803namespace internal
15804{
15805 namespace TriangulationImplementation
15806 {
15807 unsigned int
15809 {
15810 return c.n_lines;
15811 }
15812
15813
15814 unsigned int
15817 {
15818 return c.n_active_lines;
15819 }
15820
15821
15822 unsigned int
15824 {
15825 return c.n_quads;
15826 }
15827
15828
15829 unsigned int
15832 {
15833 return c.n_active_quads;
15834 }
15835
15836
15837 unsigned int
15839 {
15840 return c.n_hexes;
15841 }
15842
15843
15844 unsigned int
15847 {
15848 return c.n_active_hexes;
15849 }
15850 } // namespace TriangulationImplementation
15851} // namespace internal
15852
15853#ifndef DOXYGEN
15854
15855template <int dim, int spacedim>
15857unsigned int Triangulation<dim, spacedim>::n_cells() const
15858{
15860}
15861
15862
15863template <int dim, int spacedim>
15866{
15868}
15869
15870template <int dim, int spacedim>
15874{
15875 return n_active_cells();
15876}
15877
15878template <int dim, int spacedim>
15882{
15883 return n_cells(0);
15884}
15885
15886template <int dim, int spacedim>
15888unsigned int Triangulation<dim, spacedim>::n_faces() const
15889{
15890 switch (dim)
15891 {
15892 case 1:
15893 return n_used_vertices();
15894 case 2:
15895 return n_lines();
15896 case 3:
15897 return n_quads();
15898 default:
15900 }
15901 return 0;
15902}
15903
15904
15905template <int dim, int spacedim>
15908{
15909 switch (dim)
15910 {
15911 case 1:
15912 return n_vertices();
15913 case 2:
15914 return n_raw_lines();
15915 case 3:
15916 return n_raw_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_used_vertices();
15932 case 2:
15933 return n_active_lines();
15934 case 3:
15935 return n_active_quads();
15936 default:
15938 }
15939 return 0;
15940}
15941
15942
15943template <int dim, int spacedim>
15946 const unsigned int level) const
15947{
15948 switch (dim)
15949 {
15950 case 1:
15951 return n_raw_lines(level);
15952 case 2:
15953 return n_raw_quads(level);
15954 case 3:
15955 return n_raw_hexs(level);
15956 default:
15958 }
15959 return 0;
15960}
15961
15962
15963
15964template <int dim, int spacedim>
15967 const unsigned int level) const
15968{
15969 switch (dim)
15970 {
15971 case 1:
15972 return n_lines(level);
15973 case 2:
15974 return n_quads(level);
15975 case 3:
15976 return n_hexs(level);
15977 default:
15979 }
15980 return 0;
15981}
15982
15983
15984
15985template <int dim, int spacedim>
15988 const unsigned int level) const
15989{
15990 switch (dim)
15991 {
15992 case 1:
15993 return n_active_lines(level);
15994 case 2:
15995 return n_active_quads(level);
15996 case 3:
15997 return n_active_hexs(level);
15998 default:
16000 }
16001 return 0;
16002}
16003
16004
16005template <int dim, int spacedim>
16008{
16009 if (anisotropic_refinement == false)
16010 {
16011 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
16012 if (n_active_cells(lvl) != 0)
16013 return true;
16014 }
16015 else
16016 {
16017 for (const auto &cell : active_cell_iterators())
16018 for (const auto &i : cell->face_indices())
16019 if (cell->face(i)->has_children())
16020 return true;
16021 }
16022 return false;
16023}
16024
16025
16026template <int dim, int spacedim>
16028unsigned int Triangulation<dim, spacedim>::n_lines() const
16029{
16030 return number_cache.n_lines;
16031}
16032
16033
16034
16035template <int dim, int spacedim>
16038 const unsigned int level) const
16039{
16040 if (dim == 1)
16041 {
16042 AssertIndexRange(level, n_levels());
16043 return levels[level]->cells.n_objects();
16044 }
16045
16046 Assert(false, ExcFacesHaveNoLevel());
16047 return 0;
16048}
16049
16050
16051template <int dim, int spacedim>
16054{
16055 if (dim == 1)
16056 {
16058 return 0;
16059 }
16060
16061 return faces->lines.n_objects();
16062}
16063
16064
16065template <int dim, int spacedim>
16068 const unsigned int level) const
16069{
16070 AssertIndexRange(level, number_cache.n_lines_level.size());
16071 Assert(dim == 1, ExcFacesHaveNoLevel());
16072 return number_cache.n_lines_level[level];
16073}
16074
16075
16076template <int dim, int spacedim>
16079{
16080 return number_cache.n_active_lines;
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
16092 return number_cache.n_active_lines_level[level];
16093}
16094
16095
16096
16097template <int dim, int spacedim>
16099unsigned int Triangulation<dim, spacedim>::n_quads() const
16100{
16101 if constexpr (dim == 1)
16102 return 0;
16103 else
16104 return number_cache.n_quads;
16105}
16106
16107
16108
16109template <int dim, int spacedim>
16112 const unsigned int level) const
16113{
16114 (void)level;
16115 if constexpr (dim == 1)
16116 return 0;
16117 else if constexpr (dim == 2)
16118 {
16119 AssertIndexRange(level, number_cache.n_quads_level.size());
16120 return number_cache.n_quads_level[level];
16121 }
16122 else if constexpr (dim == 3)
16123 Assert(dim < 3, ExcFacesHaveNoLevel());
16124 else
16126
16128}
16129
16130
16131
16132template <int dim, int spacedim>
16135{
16136 if constexpr (dim == 1)
16137 return 0;
16138 else if constexpr (dim == 2)
16140 else if constexpr (dim == 3)
16141 return faces->quads.n_objects();
16142 else
16144
16146}
16147
16148
16149
16150template <int dim, int spacedim>
16153 const unsigned int level) const
16154{
16155 (void)level;
16156 if constexpr (dim == 1)
16157 return 0;
16158 else if constexpr (dim == 2)
16159 {
16160 AssertIndexRange(level, n_levels());
16161 return levels[level]->cells.n_objects();
16162 }
16163 else if constexpr (dim == 3)
16164 Assert(dim < 3, ExcFacesHaveNoLevel());
16165 else
16167
16169}
16170
16171
16172
16173template <int dim, int spacedim>
16176{
16177 if constexpr (dim == 1)
16178 return 0;
16179 else
16180 return number_cache.n_active_quads;
16181}
16182
16183
16184
16185template <int dim, int spacedim>
16188 const unsigned int level) const
16189{
16190 (void)level;
16191 if constexpr (dim == 1)
16192 return 0;
16193 else if constexpr (dim == 2)
16194 {
16195 AssertIndexRange(level, number_cache.n_quads_level.size());
16196 return number_cache.n_active_quads_level[level];
16197 }
16198 else if constexpr (dim == 3)
16199 Assert(dim < 3, ExcFacesHaveNoLevel());
16200 else
16202
16204}
16205
16206
16207
16208template <int dim, int spacedim>
16210unsigned int Triangulation<dim, spacedim>::n_hexs() const
16211{
16212 if constexpr (dim == 3)
16213 return number_cache.n_hexes;
16214 else
16215 return 0;
16216}
16217
16218
16219
16220template <int dim, int spacedim>
16223 const unsigned int level) const
16224{
16225 (void)level;
16226 if constexpr (dim == 3)
16227 {
16228 AssertIndexRange(level, number_cache.n_hexes_level.size());
16229 return number_cache.n_hexes_level[level];
16230 }
16231 else
16232 return 0;
16233}
16234
16235
16236
16237template <int dim, int spacedim>
16240 const unsigned int level) const
16241{
16242 (void)level;
16243 if constexpr (dim == 3)
16244 {
16245 AssertIndexRange(level, n_levels());
16246 return levels[level]->cells.n_objects();
16247 }
16248 else
16249 return 0;
16250}
16251
16252
16253template <int dim, int spacedim>
16256{
16257 if constexpr (dim == 3)
16258 return number_cache.n_active_hexes;
16259 else
16260 return 0;
16261}
16262
16263
16264
16265template <int dim, int spacedim>
16268 const unsigned int level) const
16269{
16270 (void)level;
16271 if constexpr (dim == 3)
16272 {
16273 AssertIndexRange(level, number_cache.n_hexes_level.size());
16274 return number_cache.n_active_hexes_level[level];
16275 }
16276 else
16277 return 0;
16278}
16279
16280
16281
16282template <int dim, int spacedim>
16285{
16286 return std::count(vertices_used.begin(), vertices_used.end(), true);
16287}
16288
16289
16290
16291template <int dim, int spacedim>
16293const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
16294{
16295 return vertices_used;
16296}
16297
16298#endif
16299
16300template <>
16301unsigned int
16303{
16304 return 2;
16305}
16306
16307
16308
16309template <>
16310unsigned int
16312{
16313 return 2;
16314}
16315
16316
16317template <>
16318unsigned int
16320{
16321 return 2;
16322}
16323
16324#ifndef DOXYGEN
16325
16326template <int dim, int spacedim>
16329{
16330 cell_iterator cell = begin(0),
16331 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
16332 // store the largest index of the
16333 // vertices used on level 0
16334 unsigned int max_vertex_index = 0;
16335 for (; cell != endc; ++cell)
16336 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16337 if (cell->vertex_index(vertex) > max_vertex_index)
16338 max_vertex_index = cell->vertex_index(vertex);
16339
16340 // store the number of times a cell
16341 // touches a vertex. An unsigned
16342 // int should suffice, even for
16343 // larger dimensions
16344 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
16345 // touch a vertex's usage count
16346 // every time we find an adjacent
16347 // element
16348 for (cell = begin(); cell != endc; ++cell)
16349 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16350 ++usage_count[cell->vertex_index(vertex)];
16351
16353 static_cast<unsigned int>(
16354 *std::max_element(usage_count.begin(), usage_count.end())));
16355}
16356
16357
16358
16359template <int dim, int spacedim>
16363{
16365}
16366
16367
16368
16369template <int dim, int spacedim>
16372{
16373 return *this;
16374}
16375
16376
16377
16378template <int dim, int spacedim>
16382{
16383 return *this;
16384}
16385
16386
16387
16388template <int dim, int spacedim>
16392 &periodicity_vector)
16393{
16394 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
16395 periodicity_vector.begin(),
16396 periodicity_vector.end());
16397
16398 // Now initialize periodic_face_map
16399 update_periodic_face_map();
16400}
16401
16402
16403
16404template <int dim, int spacedim>
16406const typename std::map<
16407 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
16408 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
16409 unsigned int>,
16412{
16413 return periodic_face_map;
16414}
16415
16416
16417template <int dim, int spacedim>
16420{
16421 // We only update the cell relations here for serial triangulations.
16422 // For other triangulations, this is done at other stages of
16423 // mesh creation and mesh refinement.
16425 this))
16426 return;
16427
16428 this->local_cell_relations.clear();
16429 this->local_cell_relations.reserve(this->n_active_cells());
16430
16431 for (const auto &cell : this->active_cell_iterators())
16432 this->local_cell_relations.emplace_back(
16433 cell, ::CellStatus::cell_will_persist);
16434}
16435
16436
16437
16438template <int dim, int spacedim>
16441{
16443 this))
16444 return;
16445
16446 // pack data before triangulation gets updated
16447 if (this->cell_attached_data.n_attached_data_sets > 0)
16448 {
16449 this->local_cell_relations.clear();
16450
16451 for (const auto &cell : this->active_cell_iterators())
16452 {
16453 const bool children_will_be_coarsened =
16454 (cell->level() > 0) && (cell->coarsen_flag_set());
16455
16456 if (children_will_be_coarsened == false)
16457 {
16458 ::CellStatus status =
16459 cell->refine_flag_set() ?
16462
16463 local_cell_relations.emplace_back(cell, status);
16464 }
16465 else if (cell->parent()->child_iterator_to_index(cell) == 0)
16466 {
16467 local_cell_relations.emplace_back(
16468 cell->parent(),
16470
16471 for (unsigned int i = 1; i < cell->parent()->n_children(); ++i)
16472 local_cell_relations.emplace_back(
16473 cell->parent(), ::CellStatus::cell_invalid);
16474 }
16475 }
16476
16477 // pack data
16478 this->data_serializer.pack_data(
16479 this->local_cell_relations,
16480 this->cell_attached_data.pack_callbacks_fixed,
16481 this->cell_attached_data.pack_callbacks_variable,
16482 this->get_mpi_communicator());
16483
16484 // dummy copy of data
16485 this->data_serializer.dest_data_fixed =
16486 this->data_serializer.src_data_fixed;
16487 this->data_serializer.dest_data_variable =
16488 this->data_serializer.src_data_variable;
16489 this->data_serializer.dest_sizes_variable =
16490 this->data_serializer.src_sizes_variable;
16491 }
16492}
16493
16494
16495
16496template <int dim, int spacedim>
16499{
16501 this))
16502 return;
16503
16504 // transfer data after triangulation got updated
16505 if (this->cell_attached_data.n_attached_data_sets > 0)
16506 {
16507 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
16508 cell_relation_t>
16509 temp;
16510
16511 for (const auto &cell : local_cell_relations)
16512 {
16513 if (cell.first->has_children())
16514 {
16517
16518 temp.emplace_back(cell.first->child(0),
16520 }
16521 else
16522 temp.push_back(cell);
16523 }
16524
16525 this->local_cell_relations = std::move(temp);
16526 }
16527}
16528
16529
16530
16531template <int dim, int spacedim>
16534{
16535 // Call our version of prepare_coarsening_and_refinement() even if a derived
16536 // class like parallel::distributed::Triangulation overrides it. Their
16537 // function will be called in their execute_coarsening_and_refinement()
16538 // function. Even in a distributed computation our job here is to reconstruct
16539 // the local part of the mesh and as such checking our flags is enough.
16541
16542 // verify a case with which we have had
16543 // some difficulty in the past (see the
16544 // deal.II/coarsening_* tests)
16545 if (smooth_grid & limit_level_difference_at_vertices)
16546 Assert(satisfies_level1_at_vertex_rule(*this), ExcInternalError());
16547
16548 // Inform all listeners about beginning of refinement.
16549 signals.pre_refinement();
16550
16551 this->pack_data_serial();
16552
16553 execute_coarsening();
16554
16555 const DistortedCellList cells_with_distorted_children = execute_refinement();
16556
16557 // We need to update the cell relations in order to be able to
16558 // deserialize data. Later on, update_cell_relations is called to mark all
16559 // active cells with the cell_will_persist status.
16560 this->unpack_data_serial();
16561
16562 reset_cell_vertex_indices_cache();
16563
16564 // If the line_to_adjacent_cell_map is populated, clear it, as it must
16565 // be recomputed every time the mesh changes.
16566 line_to_adjacent_cells_map.reset();
16567
16568 // verify a case with which we have had
16569 // some difficulty in the past (see the
16570 // deal.II/coarsening_* tests)
16571 if (smooth_grid & limit_level_difference_at_vertices)
16572 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
16573
16574 // finally build up neighbor connectivity information, and set
16575 // active cell indices
16576 this->policy->update_neighbors(*this);
16577 reset_active_cell_indices();
16578
16579 reset_global_cell_indices(); // TODO: better place?
16580
16581 // Inform all listeners about end of refinement.
16582 signals.post_refinement();
16583
16584 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
16585 cells_with_distorted_children);
16586
16587 update_periodic_face_map();
16588
16589 if (this->cell_attached_data.n_attached_data_sets == 0)
16590 this->update_cell_relations();
16591
16592 if constexpr (running_in_debug_mode())
16593 {
16594 // In debug mode, we want to check for some consistency of the
16595 // result of this function. Because there are multiple exit
16596 // paths, put this check into a ScopeExit object that is
16597 // executed on each of the exit paths.
16598 //
16599 // Specifically, check on exit of this function that if a quad
16600 // cell has been refined, all of its children have neighbors
16601 // in all directions in which the parent cell has neighbors as
16602 // well. The children's neighbors are either the parent
16603 // neighbor or the parent neighbor's children, or simply one of
16604 // the other children of the current cell. This check is
16605 // useful because if one creates a triangulation with an
16606 // inconsistently ordered set of cells (e.g., because one has
16607 // forgotten to call GridTools::consistently_order_cells()),
16608 // then this relatively simple invariant is violated -- so the
16609 // check here can be used to catch that case, at least
16610 // sometimes.
16611 //
16612 // In 1d, this situation cannot happen. In 3d, we have explicit
16613 // orientation flags to ensure that it is not necessary to re-orient
16614 // cells at the beginning. But in both cases, the invariant should
16615 // still hold as long as the cell is a hypercube.
16616 for (const auto &cell : cell_iterators())
16617 {
16618 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
16619 for (const unsigned int f : cell->face_indices())
16620 if (cell->at_boundary(f) == false)
16621 {
16622 for (const auto &child : cell->child_iterators())
16623 {
16624 Assert(
16625 child->at_boundary(f) == false,
16626 ExcMessage(
16627 "We ended up with a triangulation whose child cells "
16628 "are not connected to their neighbors as expected. "
16629 "When you created the triangulation, did you forget "
16630 "to call GridTools::consistently_order_cells() "
16631 "before calling Triangulation::create_triangulation()?"));
16632 }
16633 }
16634 }
16635 }
16636}
16637
16638
16639
16640template <int dim, int spacedim>
16643{
16644 unsigned int active_cell_index = 0;
16645 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
16646 if ((cell->used() == false) || cell->has_children())
16647 cell->set_active_cell_index(numbers::invalid_unsigned_int);
16648 else
16649 {
16650 cell->set_active_cell_index(active_cell_index);
16651 ++active_cell_index;
16652 }
16653
16654 Assert(active_cell_index == n_active_cells(), ExcInternalError());
16655}
16656
16657
16658
16659template <int dim, int spacedim>
16662{
16663 types::global_cell_index active_cell_index = 0;
16664 for (unsigned int l = 0; l < levels.size(); ++l)
16665 {
16666 types::global_cell_index level_cell_index = 0;
16667 for (const auto &cell : cell_iterators_on_level(l))
16668 {
16669 cell->set_global_level_cell_index(level_cell_index++);
16670 if (cell->is_active())
16671 cell->set_global_active_cell_index(active_cell_index++);
16672 }
16673 }
16674 AssertDimension(active_cell_index, this->n_active_cells());
16675}
16676
16677
16678
16679template <int dim, int spacedim>
16682{
16683 for (unsigned int l = 0; l < levels.size(); ++l)
16684 for (const auto &cell : cell_iterators_on_level(l))
16685 {
16686 const unsigned int n_vertices = cell->n_vertices();
16687
16689 ReferenceCells::max_n_vertices<dim>()>
16690 cell_vertices(n_vertices);
16691 if constexpr (running_in_debug_mode())
16692 std::fill(cell_vertices.begin(),
16693 cell_vertices.end(),
16695
16696 GridTools::internal::extract_vertices_without_cache<dim, spacedim>(
16697 cell, cell_vertices);
16698 for (unsigned int vertex_no = 0; vertex_no < n_vertices; ++vertex_no)
16699 levels[l]->set_cached_vertex_index(cell->index(),
16700 vertex_no,
16701 cell_vertices[vertex_no]);
16702 }
16703}
16704
16705
16706
16707template <int dim, int spacedim>
16710{
16711 // first empty the currently stored objects
16712 periodic_face_map.clear();
16713
16714 typename std::vector<
16716 for (it = periodic_face_pairs_level_0.begin();
16717 it != periodic_face_pairs_level_0.end();
16718 ++it)
16719 {
16720 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16721 it->cell[1],
16722 it->face_idx[0],
16723 it->face_idx[1],
16724 it->orientation,
16725 periodic_face_map);
16726
16727 const auto face_reference_cell =
16728 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16729 // for the other way, we need to invert the orientation
16730 update_periodic_face_map_recursively<dim, spacedim>(
16731 it->cell[1],
16732 it->cell[0],
16733 it->face_idx[1],
16734 it->face_idx[0],
16735 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16736 periodic_face_map);
16737 }
16738
16739 // check consistency
16740 typename std::map<std::pair<cell_iterator, unsigned int>,
16741 std::pair<std::pair<cell_iterator, unsigned int>,
16742 types::geometric_orientation>>::const_iterator
16743 it_test;
16744 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16745 ++it_test)
16746 {
16748 it_test->first.first;
16750 it_test->second.first.first;
16751 if (cell_1->level() == cell_2->level())
16752 {
16753 // if both cells have the same neighbor, then the same pair
16754 // order swapped has to be in the map
16755 Assert(periodic_face_map[it_test->second.first].first ==
16756 it_test->first,
16758 }
16759 }
16760}
16761
16762
16763
16764template <int dim, int spacedim>
16766const std::vector<ReferenceCell<dim>>
16768{
16769 return this->reference_cells;
16770}
16771
16772
16773
16774template <int dim, int spacedim>
16777{
16778 Assert(this->reference_cells.size() > 0,
16779 ExcMessage("You can't ask about the kinds of reference "
16780 "cells used by this triangulation if the "
16781 "triangulation doesn't yet have any cells in it."));
16782 return (this->reference_cells.size() == 1 &&
16783 this->reference_cells[0].is_hyper_cube());
16784}
16785
16786
16787
16788template <int dim, int spacedim>
16791{
16792 Assert(this->reference_cells.size() > 0,
16793 ExcMessage("You can't ask about the kinds of reference "
16794 "cells used by this triangulation if the "
16795 "triangulation doesn't yet have any cells in it."));
16796 return (this->reference_cells.size() == 1 &&
16797 this->reference_cells[0].is_simplex());
16798}
16799
16800
16801
16802template <int dim, int spacedim>
16805{
16806 Assert(this->reference_cells.size() > 0,
16807 ExcMessage("You can't ask about the kinds of reference "
16808 "cells used by this triangulation if the "
16809 "triangulation doesn't yet have any cells in it."));
16810 return reference_cells.size() > 1 ||
16811 ((reference_cells[0].is_hyper_cube() == false) &&
16812 (reference_cells[0].is_simplex() == false));
16813}
16814
16815
16816
16817template <int dim, int spacedim>
16820 const std::function<std::vector<char>(const cell_iterator &,
16821 const ::CellStatus)>
16822 &pack_callback,
16823 const bool returns_variable_size_data)
16824{
16825 unsigned int handle = numbers::invalid_unsigned_int;
16826
16827 // Add new callback function to the corresponding register.
16828 // Encode handles according to returns_variable_size_data.
16829 if (returns_variable_size_data)
16830 {
16831 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16832 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16833 }
16834 else
16835 {
16836 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16837 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16838 }
16839
16840 // Increase overall counter.
16841 ++this->cell_attached_data.n_attached_data_sets;
16842
16843 return handle;
16844}
16845
16846
16847
16848template <int dim, int spacedim>
16851 const unsigned int handle,
16852 const std::function<
16853 void(const cell_iterator &,
16854 const ::CellStatus,
16855 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16856 &unpack_callback)
16857{
16858 // perform unpacking
16859 this->data_serializer.unpack_data(this->local_cell_relations,
16860 handle,
16861 unpack_callback);
16862
16863 // decrease counters
16864 --this->cell_attached_data.n_attached_data_sets;
16865 if (this->cell_attached_data.n_attached_deserialize > 0)
16866 --this->cell_attached_data.n_attached_deserialize;
16867
16868 // important: only remove data if we are not in the deserialization
16869 // process. There, each SolutionTransfer registers and unpacks before
16870 // the next one does this, so n_attached_data_sets is only 1 here. This
16871 // would destroy the saved data before the second SolutionTransfer can
16872 // get it. This created a bug that is documented in
16873 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16874
16875 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16876 this->cell_attached_data.n_attached_deserialize == 0)
16877 {
16878 // everybody got their data, time for cleanup!
16879 this->cell_attached_data.pack_callbacks_fixed.clear();
16880 this->cell_attached_data.pack_callbacks_variable.clear();
16881 this->data_serializer.clear();
16882
16883 // reset all cell_status entries after coarsening/refinement
16884 for (auto &cell_rel : this->local_cell_relations)
16885 cell_rel.second = ::CellStatus::cell_will_persist;
16886 }
16887}
16888
16889
16890
16891template <int dim, int spacedim>
16894 const unsigned int global_first_cell,
16895 const unsigned int global_num_cells,
16896 const std::string &file_basename) const
16897{
16898 // cast away constness
16899 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16900
16901 // each cell should have been flagged `CellStatus::cell_will_persist`
16902 for (const auto &cell_rel : this->local_cell_relations)
16903 {
16904 (void)cell_rel;
16905 Assert((cell_rel.second == // cell_status
16908 }
16909
16910 if (this->cell_attached_data.n_attached_data_sets > 0)
16911 {
16912 // pack attached data first
16913 tria->data_serializer.pack_data(
16914 tria->local_cell_relations,
16915 tria->cell_attached_data.pack_callbacks_fixed,
16916 tria->cell_attached_data.pack_callbacks_variable,
16917 this->get_mpi_communicator());
16918
16919 // then store buffers in file
16920 tria->data_serializer.save(global_first_cell,
16921 global_num_cells,
16922 file_basename,
16923 this->get_mpi_communicator());
16924
16925 // and release the memory afterwards
16926 tria->data_serializer.clear();
16927 }
16928
16929 // clear all of the callback data, as explained in the documentation of
16930 // register_data_attach()
16931 {
16932 tria->cell_attached_data.n_attached_data_sets = 0;
16933 tria->cell_attached_data.pack_callbacks_fixed.clear();
16934 tria->cell_attached_data.pack_callbacks_variable.clear();
16935 }
16936}
16937
16938
16939template <int dim, int spacedim>
16942 const unsigned int global_first_cell,
16943 const unsigned int global_num_cells,
16944 const unsigned int local_num_cells,
16945 const std::string &file_basename,
16946 const unsigned int n_attached_deserialize_fixed,
16947 const unsigned int n_attached_deserialize_variable)
16948{
16949 // load saved data, if any was stored
16950 if (this->cell_attached_data.n_attached_deserialize > 0)
16951 {
16952 this->data_serializer.load(global_first_cell,
16953 global_num_cells,
16954 local_num_cells,
16955 file_basename,
16956 n_attached_deserialize_fixed,
16957 n_attached_deserialize_variable,
16958 this->get_mpi_communicator());
16959
16960 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16961
16962 if constexpr (running_in_debug_mode())
16963 {
16964 // the CellStatus of all stored cells should always be
16965 // CellStatus::cell_will_persist.
16966 for (const auto &cell_rel : this->local_cell_relations)
16967 {
16968 Assert((cell_rel.second == // cell_status
16971 }
16972 }
16973 }
16974}
16975
16976
16977template <int dim, int spacedim>
16980{
16981 levels.clear();
16982 faces.reset();
16983
16984 vertices.clear();
16985 vertices_used.clear();
16986
16987 manifolds.clear();
16988
16989 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16990 if (dim == 1)
16991 {
16992 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16993 vertex_to_boundary_id_map_1d->clear();
16994
16995 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
16996 vertex_to_manifold_id_map_1d->clear();
16997 }
16998 else
16999 {
17000 // For dim>1, these maps should simply not exist.
17001 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
17002 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
17003 }
17004
17005
17007}
17008
17009
17010
17011template <int dim, int spacedim>
17015{
17016 const DistortedCellList cells_with_distorted_children =
17017 this->policy->execute_refinement(*this, check_for_distorted_cells);
17018
17019
17020
17021 // re-compute number of lines
17023 *this, levels.size(), number_cache);
17024
17025 if constexpr (running_in_debug_mode())
17026 {
17027 for (const auto &level : levels)
17028 monitor_memory(level->cells, dim);
17029
17030 // check whether really all refinement flags are reset (also of
17031 // previously non-active cells which we may not have touched. If the
17032 // refinement flag of a non-active cell is set, something went wrong
17033 // since the cell-accessors should have caught this)
17034 for (const auto &cell : this->cell_iterators())
17035 Assert(!cell->refine_flag_set(), ExcInternalError());
17036 }
17037
17038 return cells_with_distorted_children;
17039}
17040
17041
17042
17043template <int dim, int spacedim>
17046{
17047 // first find out if there are any cells at all to be coarsened in the
17048 // loop below
17049 const cell_iterator endc = end();
17050 bool do_coarsen = false;
17051 if (levels.size() >= 2)
17052 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17053 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17054 {
17055 do_coarsen = true;
17056 break;
17057 }
17058
17059 if (!do_coarsen)
17060 return;
17061
17062 // create a vector counting for each line and quads how many cells contain
17063 // the respective object. this is used later to decide which lines can be
17064 // deleted after coarsening a cell.
17065 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
17066 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
17067 if (dim > 1)
17068 for (const auto &cell : this->cell_iterators())
17069 {
17070 if (dim > 2)
17071 {
17072 const auto line_indices = internal::TriaAccessorImplementation::
17073 Implementation::get_line_indices_of_cell(*cell);
17074 // avoid a compiler warning by fixing the max number of
17075 // loop iterations to 12
17076 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
17077 for (unsigned int l = 0; l < n_lines; ++l)
17078 ++line_cell_count[line_indices[l]];
17079 for (const unsigned int q : cell->face_indices())
17080 ++quad_cell_count[cell->face_index(q)];
17081 }
17082 else
17083 for (unsigned int l = 0; l < cell->n_lines(); ++l)
17084 ++line_cell_count[cell->line(l)->index()];
17085 }
17086
17087 // Since the loop goes over used cells we only need not worry about
17088 // deleting some cells since the ++operator will then just hop over them
17089 // if we should hit one. Do the loop in the reverse way since we may
17090 // only delete some cells if their neighbors have already been deleted
17091 // (if the latter are on a higher level for example). In effect, only
17092 // those cells are deleted of which originally all children were flagged
17093 // and for which all children are on the same refinement level. Note
17094 // that because of the effects of
17095 // @p{fix_coarsen_flags}, of a cell either all or no children must be
17096 // flagged for coarsening, so it is ok to only check the first child
17097 //
17098 // since we delete the *children* of cells, we can ignore cells on the
17099 // highest level, i.e., level must be less than or equal to
17100 // n_levels()-2.
17101 if (levels.size() >= 2)
17102 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17103 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17104 {
17105 for (unsigned int child = 0; child < cell->n_children(); ++child)
17106 {
17107 Assert(cell->child(child)->coarsen_flag_set(),
17109 cell->child(child)->clear_coarsen_flag();
17110 }
17111 // inform all listeners that cell coarsening is going to happen
17112 signals.pre_coarsening_on_cell(cell);
17113 // use a separate function, since this is dimension specific
17114 this->policy->delete_children(*this,
17115 cell,
17116 line_cell_count,
17117 quad_cell_count);
17118 }
17119
17120 // re-compute number of lines and quads
17122 *this, levels.size(), number_cache);
17123}
17124
17125
17126
17127template <int dim, int spacedim>
17130{
17131 // copy a piece of code from prepare_coarsening_and_refinement that
17132 // ensures that the level difference at vertices is limited if so
17133 // desired. we need this code here since at least in 1d we don't
17134 // call the dimension-independent version of
17135 // prepare_coarsening_and_refinement function. in 2d and 3d, having
17136 // this hunk here makes our lives a bit easier as well as it takes
17137 // care of these cases earlier than it would otherwise happen.
17138 //
17139 // the main difference to the code in p_c_and_r is that here we
17140 // absolutely have to make sure that we get things right, i.e. that
17141 // in particular we set flags right if
17142 // limit_level_difference_at_vertices is set. to do so we iterate
17143 // until the flags don't change any more
17144 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17145
17146 bool continue_iterating = true;
17147
17148 do
17149 {
17150 if (smooth_grid & limit_level_difference_at_vertices)
17151 {
17152 Assert(!anisotropic_refinement,
17153 ExcMessage("In case of anisotropic refinement the "
17154 "limit_level_difference_at_vertices flag for "
17155 "mesh smoothing must not be set!"));
17156
17157 // store highest level one of the cells adjacent to a vertex
17158 // belongs to
17159 std::vector<int> vertex_level(vertices.size(), 0);
17160 for (const auto &cell : this->active_cell_iterators())
17161 {
17162 if (cell->refine_flag_set())
17163 for (const unsigned int vertex : cell->vertex_indices())
17164 vertex_level[cell->vertex_index(vertex)] =
17165 std::max(vertex_level[cell->vertex_index(vertex)],
17166 cell->level() + 1);
17167 else if (!cell->coarsen_flag_set())
17168 for (const unsigned int vertex : cell->vertex_indices())
17169 vertex_level[cell->vertex_index(vertex)] =
17170 std::max(vertex_level[cell->vertex_index(vertex)],
17171 cell->level());
17172 else
17173 {
17174 // if coarsen flag is set then tentatively assume
17175 // that the cell will be coarsened. this isn't
17176 // always true (the coarsen flag could be removed
17177 // again) and so we may make an error here. we try
17178 // to correct this by iterating over the entire
17179 // process until we are converged
17180 Assert(cell->coarsen_flag_set(), ExcInternalError());
17181 for (const unsigned int vertex : cell->vertex_indices())
17182 vertex_level[cell->vertex_index(vertex)] =
17183 std::max(vertex_level[cell->vertex_index(vertex)],
17184 cell->level() - 1);
17185 }
17186 }
17187
17188
17189 // loop over all cells in reverse order. do so because we
17190 // can then update the vertex levels on the adjacent
17191 // vertices and maybe already flag additional cells in this
17192 // loop
17193 //
17194 // note that not only may we have to add additional
17195 // refinement flags, but we will also have to remove
17196 // coarsening flags on cells adjacent to vertices that will
17197 // see refinement
17198 active_cell_iterator endc = end();
17199 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
17200 if (cell->refine_flag_set() == false)
17201 {
17202 for (const unsigned int vertex : cell->vertex_indices())
17203 if (vertex_level[cell->vertex_index(vertex)] >=
17204 cell->level() + 1)
17205 {
17206 // remove coarsen flag...
17207 cell->clear_coarsen_flag();
17208
17209 // ...and if necessary also refine the current
17210 // cell, at the same time updating the level
17211 // information about vertices
17212 if (vertex_level[cell->vertex_index(vertex)] >
17213 cell->level() + 1)
17214 {
17215 cell->set_refine_flag();
17216
17217 for (const unsigned int v : cell->vertex_indices())
17218 vertex_level[cell->vertex_index(v)] =
17219 std::max(vertex_level[cell->vertex_index(v)],
17220 cell->level() + 1);
17221 }
17222
17223 // continue and see whether we may, for example,
17224 // go into the inner 'if' above based on a
17225 // different vertex
17226 }
17227 }
17228 }
17229
17230 // loop over all cells and remove the coarsen flags for those cells that
17231 // have sister cells not marked for coarsening, or where some neighbors
17232 // are more refined.
17233
17234 // Coarsen flags of cells with no mother cell, i.e. on the
17235 // coarsest level, are deleted explicitly.
17236 for (const auto &acell : this->active_cell_iterators_on_level(0))
17237 acell->clear_coarsen_flag();
17238
17239 const cell_iterator endc = end();
17240 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17241 {
17242 // nothing to do if we are already on the finest level
17243 if (cell->is_active())
17244 continue;
17245
17246 const unsigned int n_children = cell->n_children();
17247 unsigned int flagged_children = 0;
17248 for (unsigned int child = 0; child < n_children; ++child)
17249 {
17250 const auto child_cell = cell->child(child);
17251 if (child_cell->is_active() && child_cell->coarsen_flag_set())
17252 {
17253 ++flagged_children;
17254 // clear flag since we don't need it anymore
17255 child_cell->clear_coarsen_flag();
17256 }
17257 }
17258
17259 // flag the children for coarsening again if all children were
17260 // flagged and if the policy allows it
17261 if (flagged_children == n_children &&
17262 this->policy->coarsening_allowed(cell))
17263 for (unsigned int c = 0; c < n_children; ++c)
17264 {
17265 Assert(cell->child(c)->refine_flag_set() == false,
17267
17268 cell->child(c)->set_coarsen_flag();
17269 }
17270 }
17271
17272 // now see if anything has changed in the last iteration of this
17273 // function
17274 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17275
17276 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
17277 previous_coarsen_flags.swap(current_coarsen_flags);
17278 }
17279 while (continue_iterating == true);
17280}
17281
17282#endif
17283
17284// TODO: merge the following 3 functions since they are the same
17285template <>
17286bool
17288{
17289 // save the flags to determine whether something was changed in the
17290 // course of this function
17291 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17292
17293 // do nothing in 1d, except setting the coarsening flags correctly
17294 fix_coarsen_flags();
17295
17296 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17297
17298 return (flags_before != flags_after);
17299}
17300
17301
17302
17303template <>
17304bool
17306{
17307 // save the flags to determine whether something was changed in the
17308 // course of this function
17309 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17310
17311 // do nothing in 1d, except setting the coarsening flags correctly
17312 fix_coarsen_flags();
17313
17314 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17315
17316 return (flags_before != flags_after);
17317}
17318
17319
17320
17321template <>
17322bool
17324{
17325 // save the flags to determine whether something was changed in the
17326 // course of this function
17327 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17328
17329 // do nothing in 1d, except setting the coarsening flags correctly
17330 fix_coarsen_flags();
17331
17332 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17333
17334 return (flags_before != flags_after);
17335}
17336
17337
17338
17339namespace
17340{
17341 // check if the given @param cell marked for coarsening would
17342 // produce an unrefined island. To break up long chains of these
17343 // cells we recursively check our neighbors in case we change this
17344 // cell. This reduces the number of outer iterations dramatically.
17345 template <int dim, int spacedim>
17346 void
17347 possibly_do_not_produce_unrefined_islands(
17349 {
17350 Assert(cell->has_children(), ExcInternalError());
17351
17352 unsigned int n_neighbors = 0;
17353 // count all neighbors that will be refined along the face of our
17354 // cell after the next step
17355 unsigned int count = 0;
17356 for (const unsigned int n : GeometryInfo<dim>::face_indices())
17357 {
17358 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
17359 cell->neighbor(n);
17360 if (neighbor.state() == IteratorState::valid)
17361 {
17362 ++n_neighbors;
17363 if (face_will_be_refined_by_neighbor(cell, n))
17364 ++count;
17365 }
17366 }
17367 // clear coarsen flags if either all existing neighbors will be
17368 // refined or all but one will be and the cell is in the interior
17369 // of the domain
17370 if (count == n_neighbors ||
17371 (count >= n_neighbors - 1 &&
17372 n_neighbors == GeometryInfo<dim>::faces_per_cell))
17373 {
17374 for (unsigned int c = 0; c < cell->n_children(); ++c)
17375 cell->child(c)->clear_coarsen_flag();
17376
17377 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17378 if (!cell->at_boundary(face) &&
17379 (!cell->neighbor(face)->is_active()) &&
17380 (cell_will_be_coarsened(cell->neighbor(face))))
17381 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
17382 cell->neighbor(face));
17383 }
17384 }
17385
17386
17387 // see if the current cell needs to be refined to avoid unrefined
17388 // islands.
17389 //
17390 // there are sometimes chains of cells that induce refinement of
17391 // each other. to avoid running the loop in
17392 // prepare_coarsening_and_refinement over and over again for each
17393 // one of them, at least for the isotropic refinement case we seek
17394 // to flag neighboring elements as well as necessary. this takes
17395 // care of (slightly pathological) cases like
17396 // deal.II/mesh_smoothing_03
17397 template <int dim, int spacedim>
17398 void
17399 possibly_refine_unrefined_island(
17401 const bool allow_anisotropic_smoothing)
17402 {
17403 Assert(cell->is_active(), ExcInternalError());
17404
17405 if constexpr (running_in_debug_mode())
17406 {
17407 // If this is not a parallel::distributed::Triangulation, then we really
17408 // should only get here if the cell is marked for refinement:
17409 if (dynamic_cast<
17411 &cell->get_triangulation()) == nullptr)
17412 Assert(cell->refine_flag_set() == false, ExcInternalError());
17413 else
17414 // But if this is a p::d::Triangulation, then we don't have that
17415 // much control and we can get here because mesh smoothing is
17416 // requested but can not be honored because p4est controls
17417 // what gets refined. In that case, we can at least provide
17418 // a better error message.
17419 Assert(
17420 cell->refine_flag_set() == false,
17421 ExcMessage(
17422 "The triangulation is trying to avoid unrefined islands "
17423 "during mesh refinement/coarsening, as you had requested "
17424 " by passing the appropriate 'smoothing flags' to the "
17425 "constructor of the triangulation. However, for objects "
17426 "of type parallel::distributed::Triangulation, control "
17427 "over which cells get refined rests with p4est, not the "
17428 "deal.II triangulation, and consequently it is not "
17429 "always possible to avoid unrefined islands in the mesh. "
17430 "Please remove the constructor argument to the triangulation "
17431 "object that requests mesh smoothing."));
17432 }
17433
17434 // now we provide two algorithms. the first one is the standard
17435 // one, coming from the time, where only isotropic refinement was
17436 // possible. it simply counts the neighbors that are or will be
17437 // refined and compares to the number of other ones. the second
17438 // one does this check independently for each direction: if all
17439 // neighbors in one direction (normally two, at the boundary only
17440 // one) are refined, the current cell is flagged to be refined in
17441 // an according direction.
17442
17443 if (allow_anisotropic_smoothing == false)
17444 {
17445 // use first algorithm
17446 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
17447 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17448 if (!cell->at_boundary(face))
17449 {
17450 if (face_will_be_refined_by_neighbor(cell, face))
17451 ++refined_neighbors;
17452 else
17453 ++unrefined_neighbors;
17454 }
17455
17456 if (unrefined_neighbors < refined_neighbors)
17457 {
17458 cell->clear_coarsen_flag();
17459 cell->set_refine_flag();
17460
17461 // ok, so now we have flagged this cell. if we know that
17462 // there were any unrefined neighbors at all, see if any
17463 // of those will have to be refined as well
17464 if (unrefined_neighbors > 0)
17465 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17466 if (!cell->at_boundary(face) &&
17467 (face_will_be_refined_by_neighbor(cell, face) == false) &&
17468 (cell->neighbor(face)->has_children() == false) &&
17469 (cell->neighbor(face)->refine_flag_set() == false))
17470 possibly_refine_unrefined_island<dim, spacedim>(
17471 cell->neighbor(face), allow_anisotropic_smoothing);
17472 }
17473 }
17474 else
17475 {
17476 // variable to store the cell refine case needed to fulfill
17477 // all smoothing requirements
17478 RefinementCase<dim> smoothing_cell_refinement_case =
17480
17481 // use second algorithm, do the check individually for each
17482 // direction
17483 for (unsigned int face_pair = 0;
17484 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
17485 ++face_pair)
17486 {
17487 // variable to store the cell refine case needed to refine
17488 // at the current face pair in the same way as the
17489 // neighbors do...
17490 RefinementCase<dim> directional_cell_refinement_case =
17492
17493 for (unsigned int face_index = 0; face_index < 2; ++face_index)
17494 {
17495 unsigned int face = 2 * face_pair + face_index;
17496 // variable to store the refine case (to come) of the
17497 // face under consideration
17498 RefinementCase<dim - 1> expected_face_ref_case =
17499 RefinementCase<dim - 1>::no_refinement;
17500
17501 if (cell->neighbor(face).state() == IteratorState::valid)
17502 face_will_be_refined_by_neighbor<dim, spacedim>(
17503 cell, face, expected_face_ref_case);
17504 // now extract which refine case would be necessary to
17505 // achieve the same face refinement. set the
17506 // intersection with other requirements for the same
17507 // direction.
17508
17509 // note: using the intersection is not an obvious
17510 // decision, we could also argue that it is more
17511 // natural to use the union. however, intersection is
17512 // the less aggressive tactic and favours a smaller
17513 // number of refined cells over an intensive
17514 // smoothing. this way we try not to lose too much of
17515 // the effort we put in anisotropic refinement
17516 // indicators due to overly aggressive smoothing...
17517 directional_cell_refinement_case =
17518 (directional_cell_refinement_case &
17521 expected_face_ref_case,
17522 face,
17523 cell->face_orientation(face),
17524 cell->face_flip(face),
17525 cell->face_rotation(face)));
17526 } // for both face indices
17527 // if both requirements sum up to something useful, add
17528 // this to the refine case for smoothing. note: if
17529 // directional_cell_refinement_case is isotropic still,
17530 // then something went wrong...
17531 Assert(directional_cell_refinement_case <
17534 smoothing_cell_refinement_case =
17535 smoothing_cell_refinement_case | directional_cell_refinement_case;
17536 } // for all face_pairs
17537 // no we collected contributions from all directions. combine
17538 // the new flags with the existing refine case, but only if
17539 // smoothing is required
17540 if (smoothing_cell_refinement_case)
17541 {
17542 cell->clear_coarsen_flag();
17543 cell->set_refine_flag(cell->refine_flag_set() |
17544 smoothing_cell_refinement_case);
17545 }
17546 }
17547 }
17548} // namespace
17549
17550#ifndef DOXYGEN
17551template <int dim, int spacedim>
17554{
17555 // save the flags to determine whether something was changed in the
17556 // course of this function
17557 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
17558 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
17559
17560 // save the flags at the outset of each loop. we do so in order to
17561 // find out whether something was changed in the present loop, in
17562 // which case we would have to re-run the loop. the other
17563 // possibility to find this out would be to set a flag
17564 // @p{something_changed} to true each time we change something.
17565 // however, sometimes one change in one of the parts of the loop is
17566 // undone by another one, so we might end up in an endless loop. we
17567 // could be tempted to break this loop at an arbitrary number of
17568 // runs, but that would not be a clean solution, since we would
17569 // either have to 1/ break the loop too early, in which case the
17570 // promise that a second call to this function immediately after the
17571 // first one does not change anything, would be broken, or 2/ we do
17572 // as many loops as there are levels. we know that information is
17573 // transported over one level in each run of the loop, so this is
17574 // enough. Unfortunately, each loop is rather expensive, so we chose
17575 // the way presented here
17576 auto coarsen_flags_before_loop = coarsen_flags_before;
17577 auto refine_flags_before_loop = refine_flags_before;
17578
17579 // now for what is done in each loop: we have to fulfill several
17580 // tasks at the same time, namely several mesh smoothing algorithms
17581 // and mesh regularization, by which we mean that the next mesh
17582 // fulfills several requirements such as no double refinement at
17583 // each face or line, etc.
17584 //
17585 // since doing these things at once seems almost impossible (in the
17586 // first year of this library, they were done in two functions, one
17587 // for refinement and one for coarsening, and most things within
17588 // these were done at once, so the code was rather impossible to
17589 // join into this, only, function), we do them one after each
17590 // other. the order in which we do them is such that the important
17591 // tasks, namely regularization, are done last and the least
17592 // important things are done the first. the following order is
17593 // chosen:
17594 //
17595 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
17596 // coarsen flags on level 1 to avoid level 0 cells being created
17597 // by coarsening. As coarsen flags will never be added, this can
17598 // be done once and for all before the actual loop starts.
17599 //
17600 // 1/ do not coarsen a cell if 'most of the neighbors' will be
17601 // refined after the step. This is to prevent occurrence of
17602 // unrefined islands.
17603 //
17604 // 2/ eliminate refined islands in the interior and at the
17605 // boundary. since they don't do much harm besides increasing the
17606 // number of degrees of freedom, doing this has a rather low
17607 // priority.
17608 //
17609 // 3/ limit the level difference of neighboring cells at each
17610 // vertex.
17611 //
17612 // 4/ eliminate unrefined islands. this has higher priority since
17613 // this diminishes the approximation properties not only of the
17614 // unrefined island, but also of the surrounding patch.
17615 //
17616 // 5/ ensure patch level 1. Then the triangulation consists of
17617 // patches, i.e. of cells that are refined once. It follows that
17618 // if at least one of the children of a cell is or will be
17619 // refined than all children need to be refined. This step only
17620 // sets refinement flags and does not set coarsening flags. If
17621 // the patch_level_1 flag is set, then
17622 // eliminate_unrefined_islands, eliminate_refined_inner_islands
17623 // and eliminate_refined_boundary_islands will be fulfilled
17624 // automatically and do not need to be enforced separately.
17625 //
17626 // 6/ take care of the requirement that no double refinement is done
17627 // at each face
17628 //
17629 // 7/ take care that no double refinement is done at each line in 3d
17630 // or higher dimensions.
17631 //
17632 // 8/ make sure that all children of each cell are either flagged
17633 // for coarsening or none of the children is
17634 //
17635 // For some of these steps, it is known that they interact. Namely,
17636 // it is not possible to guarantee that after step 6 another step 5
17637 // would have no effect; the same holds for the opposite order and
17638 // also when taking into account step 7. however, it is important to
17639 // guarantee that step five or six do not undo something that step 5
17640 // did, and step 7 not something of step 6, otherwise the
17641 // requirements will not be satisfied even if the loop
17642 // terminates. this is accomplished by the fact that steps 5 and 6
17643 // only *add* refinement flags and delete coarsening flags
17644 // (therefore, step 6 can't undo something that step 4 already did),
17645 // and step 7 only deletes coarsening flags, never adds some. step 7
17646 // needs also take care that it won't tag cells for refinement for
17647 // which some neighbors are more refined or will be refined.
17648
17649 //------------------------------------
17650 // STEP 0:
17651 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17652 // coarsen flags on level 1 to avoid level 0 cells being created
17653 // by coarsening.
17654 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17655 n_levels() >= 2)
17656 {
17657 for (const auto &cell : active_cell_iterators_on_level(1))
17658 cell->clear_coarsen_flag();
17659 }
17660
17661 bool mesh_changed_in_this_loop = false;
17662 do
17663 {
17664 //------------------------------------
17665 // STEP 1:
17666 // do not coarsen a cell if 'most of the neighbors' will be
17667 // refined after the step. This is to prevent the occurrence
17668 // of unrefined islands. If patch_level_1 is set, this will
17669 // be automatically fulfilled.
17670 if (smooth_grid & do_not_produce_unrefined_islands &&
17671 !(smooth_grid & patch_level_1))
17672 {
17673 for (const auto &cell : cell_iterators())
17674 {
17675 // only do something if this
17676 // cell will be coarsened
17677 if (!cell->is_active() && cell_will_be_coarsened(cell))
17678 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17679 }
17680 }
17681
17682
17683 //------------------------------------
17684 // STEP 2:
17685 // eliminate refined islands in the interior and at the
17686 // boundary. since they don't do much harm besides increasing
17687 // the number of degrees of freedom, doing this has a rather
17688 // low priority. If patch_level_1 is set, this will be
17689 // automatically fulfilled.
17690 //
17691 // there is one corner case to consider: if this is a
17692 // distributed triangulation, there may be refined islands on
17693 // the boundary of which we own only part (e.g. a single cell
17694 // in the corner of a domain). the rest of the island is
17695 // ghost cells and it *looks* like the area around it
17696 // (artificial cells) are coarser but this is only because
17697 // they may actually be equally fine on other
17698 // processors. it's hard to detect this case but we can do
17699 // the following: only set coarsen flags to remove this
17700 // refined island if all cells we want to set flags on are
17701 // locally owned
17702 if (smooth_grid & (eliminate_refined_inner_islands |
17703 eliminate_refined_boundary_islands) &&
17704 !(smooth_grid & patch_level_1))
17705 {
17706 for (const auto &cell : cell_iterators())
17707 if (!cell->is_active() ||
17708 (cell->is_active() && cell->refine_flag_set() &&
17709 cell->is_locally_owned()))
17710 {
17711 // check whether all children are active, i.e. not
17712 // refined themselves. This is a precondition that the
17713 // children may be coarsened away. If the cell is only
17714 // flagged for refinement, then all future children
17715 // will be active
17716 bool all_children_active = true;
17717 if (!cell->is_active())
17718 for (unsigned int c = 0; c < cell->n_children(); ++c)
17719 if (!cell->child(c)->is_active() ||
17720 cell->child(c)->is_ghost() ||
17721 cell->child(c)->is_artificial())
17722 {
17723 all_children_active = false;
17724 break;
17725 }
17726
17727 if (all_children_active)
17728 {
17729 // count number of refined and unrefined neighbors
17730 // of cell. neighbors on lower levels are counted
17731 // as unrefined since they can only get to the
17732 // same level as this cell by the next refinement
17733 // cycle
17734 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17735
17736 // Keep track if this cell is at a periodic
17737 // boundary or not. TODO: We do not currently run
17738 // the algorithm for inner islands at a periodic
17739 // boundary (remains to be implemented), but we
17740 // also don't want to consider them
17741 // boundary_island cells as this can interfere
17742 // with 2:1 refinement across periodic faces.
17743 // Instead: just ignore those cells for this
17744 // smoothing operation below.
17745 bool at_periodic_boundary = false;
17746
17747 for (const unsigned int n : cell->face_indices())
17748 {
17749 const cell_iterator neighbor = cell->neighbor(n);
17750 if (neighbor.state() == IteratorState::valid)
17751 {
17752 ++total_neighbors;
17753
17754 if (!face_will_be_refined_by_neighbor(cell, n))
17755 ++unrefined_neighbors;
17756 }
17757 else if (cell->has_periodic_neighbor(n))
17758 {
17759 ++total_neighbors;
17760 at_periodic_boundary = true;
17761 }
17762 }
17763
17764 // if all neighbors unrefined: mark this cell for
17765 // coarsening or don't refine if marked for that
17766 //
17767 // also do the distinction between the two
17768 // versions of the eliminate_refined_*_islands
17769 // flag
17770 //
17771 // the last check is whether there are any
17772 // neighbors at all. if not so, then we are (e.g.)
17773 // on the coarsest grid with one cell, for which,
17774 // of course, we do not remove the refine flag.
17775 if ((unrefined_neighbors == total_neighbors) &&
17776 ((!cell->at_boundary() &&
17777 (smooth_grid & eliminate_refined_inner_islands)) ||
17778 (cell->at_boundary() && !at_periodic_boundary &&
17779 (smooth_grid &
17780 eliminate_refined_boundary_islands))) &&
17781 (total_neighbors != 0))
17782 {
17783 if (!cell->is_active())
17784 for (unsigned int c = 0; c < cell->n_children(); ++c)
17785 {
17786 cell->child(c)->clear_refine_flag();
17787 cell->child(c)->set_coarsen_flag();
17788 }
17789 else
17790 cell->clear_refine_flag();
17791 }
17792 }
17793 }
17794 }
17795
17796 //------------------------------------
17797 // STEP 3:
17798 // limit the level difference of neighboring cells at each
17799 // vertex.
17800 //
17801 // in case of anisotropic refinement this does not make
17802 // sense. as soon as one cell is anisotropically refined, an
17803 // Assertion is thrown. therefore we can ignore this problem
17804 // later on
17805 if (smooth_grid & limit_level_difference_at_vertices)
17806 {
17807 Assert(!anisotropic_refinement,
17808 ExcMessage("In case of anisotropic refinement the "
17809 "limit_level_difference_at_vertices flag for "
17810 "mesh smoothing must not be set!"));
17811
17812 // store highest level one of the cells adjacent to a vertex
17813 // belongs to
17814 std::vector<int> vertex_level(vertices.size(), 0);
17815 for (const auto &cell : active_cell_iterators())
17816 {
17817 if (cell->refine_flag_set())
17818 for (const unsigned int vertex : cell->vertex_indices())
17819 vertex_level[cell->vertex_index(vertex)] =
17820 std::max(vertex_level[cell->vertex_index(vertex)],
17821 cell->level() + 1);
17822 else if (!cell->coarsen_flag_set())
17823 for (const unsigned int vertex : cell->vertex_indices())
17824 vertex_level[cell->vertex_index(vertex)] =
17825 std::max(vertex_level[cell->vertex_index(vertex)],
17826 cell->level());
17827 else
17828 {
17829 // if coarsen flag is set then tentatively assume
17830 // that the cell will be coarsened. this isn't
17831 // always true (the coarsen flag could be removed
17832 // again) and so we may make an error here
17833 Assert(cell->coarsen_flag_set(), ExcInternalError());
17834 for (const unsigned int vertex : cell->vertex_indices())
17835 vertex_level[cell->vertex_index(vertex)] =
17836 std::max(vertex_level[cell->vertex_index(vertex)],
17837 cell->level() - 1);
17838 }
17839 }
17840
17841
17842 // loop over all cells in reverse order. do so because we
17843 // can then update the vertex levels on the adjacent
17844 // vertices and maybe already flag additional cells in this
17845 // loop
17846 //
17847 // note that not only may we have to add additional
17848 // refinement flags, but we will also have to remove
17849 // coarsening flags on cells adjacent to vertices that will
17850 // see refinement
17851 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17852 if (cell->refine_flag_set() == false)
17853 {
17854 for (const unsigned int vertex : cell->vertex_indices())
17855 if (vertex_level[cell->vertex_index(vertex)] >=
17856 cell->level() + 1)
17857 {
17858 // remove coarsen flag...
17859 cell->clear_coarsen_flag();
17860
17861 // ...and if necessary also refine the current
17862 // cell, at the same time updating the level
17863 // information about vertices
17864 if (vertex_level[cell->vertex_index(vertex)] >
17865 cell->level() + 1)
17866 {
17867 cell->set_refine_flag();
17868
17869 for (const unsigned int v : cell->vertex_indices())
17870 vertex_level[cell->vertex_index(v)] =
17871 std::max(vertex_level[cell->vertex_index(v)],
17872 cell->level() + 1);
17873 }
17874
17875 // continue and see whether we may, for example,
17876 // go into the inner'if'
17877 // above based on a
17878 // different vertex
17879 }
17880 }
17881 }
17882
17883 //-----------------------------------
17884 // STEP 4:
17885 // eliminate unrefined islands. this has higher priority
17886 // since this diminishes the approximation properties not
17887 // only of the unrefined island, but also of the surrounding
17888 // patch.
17889 //
17890 // do the loop from finest to coarsest cells since we may
17891 // trigger a cascade by marking cells for refinement which
17892 // may trigger more cells further down below
17893 if (smooth_grid & eliminate_unrefined_islands)
17894 {
17895 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17896 // only do something if cell is not already flagged for
17897 // (isotropic) refinement
17898 if (cell->refine_flag_set() !=
17900 possibly_refine_unrefined_island<dim, spacedim>(
17901 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17902 }
17903
17904 //-------------------------------
17905 // STEP 5:
17906 // ensure patch level 1.
17907 //
17908 // Introduce some terminology:
17909 // - a cell that is refined
17910 // once is a patch of
17911 // level 1 simply called patch.
17912 // - a cell that is globally
17913 // refined twice is called
17914 // a patch of level 2.
17915 // - patch level n says that
17916 // the triangulation consists
17917 // of patches of level n.
17918 // This makes sense only
17919 // if the grid is already at
17920 // least n times globally
17921 // refined.
17922 //
17923 // E.g. from patch level 1 follows: if at least one of the
17924 // children of a cell is or will be refined than enforce all
17925 // children to be refined.
17926
17927 // This step 4 only sets refinement flags and does not set
17928 // coarsening flags.
17929 if (smooth_grid & patch_level_1)
17930 {
17931 // An important assumption (A) is that before calling this
17932 // function the grid was already of patch level 1.
17933
17934 // loop over all cells whose children are all active. (By
17935 // assumption (A) either all or none of the children are
17936 // active). If the refine flag of at least one of the
17937 // children is set then set_refine_flag and
17938 // clear_coarsen_flag of all children.
17939 for (const auto &cell : cell_iterators())
17940 if (!cell->is_active())
17941 {
17942 // ensure the invariant. we can then check whether all
17943 // of its children are further refined or not by
17944 // simply looking at the first child
17945 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17946 if (cell->child(0)->has_children() == true)
17947 continue;
17948
17949 // cell is found to be a patch. combine the refine
17950 // cases of all children
17951 RefinementCase<dim> combined_ref_case =
17953 for (unsigned int i = 0; i < cell->n_children(); ++i)
17954 combined_ref_case =
17955 combined_ref_case | cell->child(i)->refine_flag_set();
17956 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17957 for (unsigned int i = 0; i < cell->n_children(); ++i)
17958 {
17959 cell_iterator child = cell->child(i);
17960
17961 child->clear_coarsen_flag();
17962 child->set_refine_flag(combined_ref_case);
17963 }
17964 }
17965
17966 // The code above dealt with the case where we may get a
17967 // non-patch_level_1 mesh from refinement. Now also deal
17968 // with the case where we could get such a mesh by
17969 // coarsening. Coarsen the children (and remove the
17970 // grandchildren) only if all cell->grandchild(i)
17971 // ->coarsen_flag_set() are set.
17972 //
17973 // for a case where this is a bit tricky, take a look at the
17974 // mesh_smoothing_0[12] testcases
17975 for (const auto &cell : cell_iterators())
17976 {
17977 // check if this cell has active grandchildren. note
17978 // that we know that it is patch_level_1, i.e. if one of
17979 // its children is active then so are all, and it isn't
17980 // going to have any grandchildren at all:
17981 if (cell->is_active() || cell->child(0)->is_active())
17982 continue;
17983
17984 // cell is not active, and so are none of its
17985 // children. check the grandchildren. note that the
17986 // children are also patch_level_1, and so we only ever
17987 // need to check their first child
17988 const unsigned int n_children = cell->n_children();
17989 bool has_active_grandchildren = false;
17990
17991 for (unsigned int i = 0; i < n_children; ++i)
17992 if (cell->child(i)->child(0)->is_active())
17993 {
17994 has_active_grandchildren = true;
17995 break;
17996 }
17997
17998 if (has_active_grandchildren == false)
17999 continue;
18000
18001
18002 // ok, there are active grandchildren. see if either all
18003 // or none of them are flagged for coarsening
18004 unsigned int n_grandchildren = 0;
18005
18006 // count all coarsen flags of the grandchildren.
18007 unsigned int n_coarsen_flags = 0;
18008
18009 // cell is not a patch (of level 1) as it has a
18010 // grandchild. Is cell a patch of level 2?? Therefore:
18011 // find out whether all cell->child(i) are patches
18012 for (unsigned int c = 0; c < n_children; ++c)
18013 {
18014 // get at the child. by assumption (A), and the
18015 // check by which we got here, the child is not
18016 // active
18017 cell_iterator child = cell->child(c);
18018
18019 const unsigned int nn_children = child->n_children();
18020 n_grandchildren += nn_children;
18021
18022 // if child is found to be a patch of active cells
18023 // itself, then add up how many of its children are
18024 // supposed to be coarsened
18025 if (child->child(0)->is_active())
18026 for (unsigned int cc = 0; cc < nn_children; ++cc)
18027 if (child->child(cc)->coarsen_flag_set())
18028 ++n_coarsen_flags;
18029 }
18030
18031 // if not all grandchildren are supposed to be coarsened
18032 // (e.g. because some simply don't have the flag set, or
18033 // because they are not active and therefore cannot
18034 // carry the flag), then remove the coarsen flag from
18035 // all of the active grandchildren. note that there may
18036 // be coarsen flags on the grandgrandchildren -- we
18037 // don't clear them here, but we'll get to them in later
18038 // iterations if necessary
18039 //
18040 // there is nothing we have to do if no coarsen flags
18041 // have been set at all
18042 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
18043 for (unsigned int c = 0; c < n_children; ++c)
18044 {
18045 const cell_iterator child = cell->child(c);
18046 if (child->child(0)->is_active())
18047 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
18048 child->child(cc)->clear_coarsen_flag();
18049 }
18050 }
18051 }
18052
18053 //--------------------------------
18054 //
18055 // at the boundary we could end up with cells with negative
18056 // volume or at least with a part, that is negative, if the
18057 // cell is refined anisotropically. we have to check, whether
18058 // that can happen
18059 this->policy->prevent_distorted_boundary_cells(*this);
18060
18061 //-------------------------------
18062 // STEP 6:
18063 // take care of the requirement that no
18064 // double refinement is done at each face
18065 //
18066 // in case of anisotropic refinement it is only likely, but
18067 // not sure, that the cells, which are more refined along a
18068 // certain face common to two cells are on a higher
18069 // level. therefore we cannot be sure, that the requirement
18070 // of no double refinement is fulfilled after a single pass
18071 // of the following actions. We could just wait for the next
18072 // global loop. when this function terminates, the
18073 // requirement will be fulfilled. However, it might be faster
18074 // to insert an inner loop here.
18075 bool changed = true;
18076 while (changed)
18077 {
18078 changed = false;
18079 active_cell_iterator cell = last_active(), endc = end();
18080
18081 for (; cell != endc; --cell)
18082 if (cell->refine_flag_set())
18083 {
18084 // loop over neighbors of cell
18085 for (const auto i : cell->face_indices())
18086 {
18087 // only do something if the face is not at the
18088 // boundary and if the face will be refined with
18089 // the RefineCase currently flagged for
18090 const bool has_periodic_neighbor =
18091 cell->has_periodic_neighbor(i);
18092 const bool has_neighbor_or_periodic_neighbor =
18093 !cell->at_boundary(i) || has_periodic_neighbor;
18094 if (has_neighbor_or_periodic_neighbor &&
18096 cell->refine_flag_set(), i) !=
18098 {
18099 // 1) if the neighbor has children: nothing to
18100 // worry about. 2) if the neighbor is active
18101 // and a coarser one, ensure, that its
18102 // refine_flag is set 3) if the neighbor is
18103 // active and as refined along the face as our
18104 // current cell, make sure, that no
18105 // coarsen_flag is set. if we remove the
18106 // coarsen flag of our neighbor,
18107 // fix_coarsen_flags() makes sure, that the
18108 // mother cell will not be coarsened
18109 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
18110 {
18111 if ((!has_periodic_neighbor &&
18112 cell->neighbor_is_coarser(i)) ||
18113 (has_periodic_neighbor &&
18114 cell->periodic_neighbor_is_coarser(i)))
18115 {
18116 if (cell->neighbor_or_periodic_neighbor(i)
18117 ->coarsen_flag_set())
18118 cell->neighbor_or_periodic_neighbor(i)
18119 ->clear_coarsen_flag();
18120 // we'll set the refine flag for this
18121 // neighbor below. we note, that we
18122 // have changed something by setting
18123 // the changed flag to true. We do not
18124 // need to do so, if we just removed
18125 // the coarsen flag, as the changed
18126 // flag only indicates the need to
18127 // re-run the inner loop. however, we
18128 // only loop over cells flagged for
18129 // refinement here, so nothing to
18130 // worry about if we remove coarsen
18131 // flags
18132
18133 if (dim == 2)
18134 {
18135 if (smooth_grid &
18136 allow_anisotropic_smoothing)
18137 changed =
18138 has_periodic_neighbor ?
18139 cell->periodic_neighbor(i)
18140 ->flag_for_face_refinement(
18141 cell
18142 ->periodic_neighbor_of_coarser_periodic_neighbor(
18143 i)
18144 .first,
18146 cell->neighbor(i)
18147 ->flag_for_face_refinement(
18148 cell
18149 ->neighbor_of_coarser_neighbor(
18150 i)
18151 .first,
18153 else
18154 {
18155 if (!cell
18156 ->neighbor_or_periodic_neighbor(
18157 i)
18158 ->refine_flag_set())
18159 changed = true;
18160 cell->neighbor_or_periodic_neighbor(i)
18161 ->set_refine_flag();
18162 }
18163 }
18164 else // i.e. if (dim==3)
18165 {
18166 // ugly situations might arise here,
18167 // consider the following situation, which
18168 // shows neighboring cells at the common
18169 // face, where the upper right element is
18170 // coarser at the given face. Now the upper
18171 // child element of the lower left wants to
18172 // refine according to cut_z, such that
18173 // there is a 'horizontal' refinement of the
18174 // face marked with #####
18175 //
18176 // / /
18177 // / /
18178 // *---------------*
18179 // | |
18180 // | |
18181 // | |
18182 // | |
18183 // | |
18184 // | | /
18185 // | |/
18186 // *---------------*
18187 //
18188 //
18189 // *---------------*
18190 // /| /|
18191 // / | ##### / |
18192 // | |
18193 // *---------------*
18194 // /| /|
18195 // / | / |
18196 // | |
18197 // *---------------*
18198 // / /
18199 // / /
18200 //
18201 // this introduces too many hanging nodes
18202 // and the neighboring (coarser) cell (upper
18203 // right) has to be refined. If it is only
18204 // refined according to cut_z, then
18205 // everything is ok:
18206 //
18207 // / /
18208 // / /
18209 // *---------------*
18210 // | |
18211 // | | /
18212 // | |/
18213 // *---------------*
18214 // | |
18215 // | | /
18216 // | |/
18217 // *---------------*
18218 //
18219 //
18220 // *---------------*
18221 // /| /|
18222 // / *---------------*
18223 // /| /|
18224 // *---------------*
18225 // /| /|
18226 // / | / |
18227 // | |
18228 // *---------------*
18229 // / /
18230 // / /
18231 //
18232 // if however the cell wants to refine
18233 // itself in an other way, or if we disallow
18234 // anisotropic smoothing, then simply
18235 // refining the neighbor isotropically is
18236 // not going to work, since this introduces
18237 // a refinement of face ##### with both
18238 // cut_x and cut_y, which is not possible:
18239 //
18240 // / / /
18241 // / / /
18242 // *-------*-------*
18243 // | | |
18244 // | | | /
18245 // | | |/
18246 // *-------*-------*
18247 // | | |
18248 // | | | /
18249 // | | |/
18250 // *-------*-------*
18251 //
18252 //
18253 // *---------------*
18254 // /| /|
18255 // / *---------------*
18256 // /| /|
18257 // *---------------*
18258 // /| /|
18259 // / | / |
18260 // | |
18261 // *---------------*
18262 // / /
18263 // / /
18264 //
18265 // thus, in this case we also need to refine
18266 // our current cell in the new direction:
18267 //
18268 // / / /
18269 // / / /
18270 // *-------*-------*
18271 // | | |
18272 // | | | /
18273 // | | |/
18274 // *-------*-------*
18275 // | | |
18276 // | | | /
18277 // | | |/
18278 // *-------*-------*
18279 //
18280 //
18281 // *-------*-------*
18282 // /| /| /|
18283 // / *-------*-------*
18284 // /| /| /|
18285 // *-------*-------*
18286 // /| / /|
18287 // / | / |
18288 // | |
18289 // *---------------*
18290 // / /
18291 // / /
18292
18293 std::pair<unsigned int, unsigned int>
18294 nb_indices =
18295 has_periodic_neighbor ?
18296 cell
18297 ->periodic_neighbor_of_coarser_periodic_neighbor(
18298 i) :
18299 cell->neighbor_of_coarser_neighbor(i);
18300 unsigned int refined_along_x = 0,
18301 refined_along_y = 0,
18302 to_be_refined_along_x = 0,
18303 to_be_refined_along_y = 0;
18304
18305 const int this_face_index =
18306 cell->face_index(i);
18307
18308 // step 1: detect, along which axis the face
18309 // is currently refined
18310
18311 // first, we need an iterator pointing to
18312 // the parent face. This requires a slight
18313 // detour in case the neighbor is behind a
18314 // periodic face.
18315 const auto parent_face = [&]() {
18316 if (has_periodic_neighbor)
18317 {
18318 const auto neighbor =
18319 cell->periodic_neighbor(i);
18320 const auto parent_face_no =
18321 neighbor
18322 ->periodic_neighbor_of_periodic_neighbor(
18323 nb_indices.first);
18324 auto parent =
18325 neighbor->periodic_neighbor(
18326 nb_indices.first);
18327 return parent->face(parent_face_no);
18328 }
18329 else
18330 return cell->neighbor(i)->face(
18331 nb_indices.first);
18332 }();
18333
18334 if ((this_face_index ==
18335 parent_face->child_index(0)) ||
18336 (this_face_index ==
18337 parent_face->child_index(1)))
18338 {
18339 // this might be an
18340 // anisotropic child. get the
18341 // face refine case of the
18342 // neighbors face and count
18343 // refinements in x and y
18344 // direction.
18345 RefinementCase<dim - 1> frc =
18346 parent_face->refinement_case();
18348 ++refined_along_x;
18350 ++refined_along_y;
18351 }
18352 else
18353 // this has to be an isotropic
18354 // child
18355 {
18356 ++refined_along_x;
18357 ++refined_along_y;
18358 }
18359 // step 2: detect, along which axis the face
18360 // has to be refined given the current
18361 // refine flag
18362 RefinementCase<dim - 1> flagged_frc =
18364 cell->refine_flag_set(),
18365 i,
18366 cell->face_orientation(i),
18367 cell->face_flip(i),
18368 cell->face_rotation(i));
18369 if (flagged_frc &
18371 ++to_be_refined_along_x;
18372 if (flagged_frc &
18374 ++to_be_refined_along_y;
18375
18376 // step 3: set the refine flag of the
18377 // (coarser and active) neighbor.
18378 if ((smooth_grid &
18379 allow_anisotropic_smoothing) ||
18380 cell->neighbor_or_periodic_neighbor(i)
18381 ->refine_flag_set())
18382 {
18383 if (refined_along_x +
18384 to_be_refined_along_x >
18385 1)
18386 changed |=
18387 cell
18388 ->neighbor_or_periodic_neighbor(i)
18389 ->flag_for_face_refinement(
18390 nb_indices.first,
18391 RefinementCase<dim -
18392 1>::cut_axis(0));
18393 if (refined_along_y +
18394 to_be_refined_along_y >
18395 1)
18396 changed |=
18397 cell
18398 ->neighbor_or_periodic_neighbor(i)
18399 ->flag_for_face_refinement(
18400 nb_indices.first,
18401 RefinementCase<dim -
18402 1>::cut_axis(1));
18403 }
18404 else
18405 {
18406 if (cell
18407 ->neighbor_or_periodic_neighbor(i)
18408 ->refine_flag_set() !=
18411 changed = true;
18412 cell->neighbor_or_periodic_neighbor(i)
18413 ->set_refine_flag();
18414 }
18415
18416 // step 4: if necessary (see above) add to
18417 // the refine flag of the current cell
18418 cell_iterator nb =
18419 cell->neighbor_or_periodic_neighbor(i);
18420 RefinementCase<dim - 1> nb_frc =
18422 nb->refine_flag_set(),
18423 nb_indices.first,
18424 nb->face_orientation(nb_indices.first),
18425 nb->face_flip(nb_indices.first),
18426 nb->face_rotation(nb_indices.first));
18427 if ((nb_frc & RefinementCase<dim>::cut_x) &&
18428 !((refined_along_x != 0u) ||
18429 (to_be_refined_along_x != 0u)))
18430 changed |= cell->flag_for_face_refinement(
18431 i,
18433 if ((nb_frc & RefinementCase<dim>::cut_y) &&
18434 !((refined_along_y != 0u) ||
18435 (to_be_refined_along_y != 0u)))
18436 changed |= cell->flag_for_face_refinement(
18437 i,
18439 }
18440 } // if neighbor is coarser
18441 else // -> now the neighbor is not coarser
18442 {
18443 cell->neighbor_or_periodic_neighbor(i)
18444 ->clear_coarsen_flag();
18445 const unsigned int nb_nb =
18446 has_periodic_neighbor ?
18447 cell
18448 ->periodic_neighbor_of_periodic_neighbor(
18449 i) :
18450 cell->neighbor_of_neighbor(i);
18451 const cell_iterator neighbor =
18452 cell->neighbor_or_periodic_neighbor(i);
18453 RefinementCase<dim - 1> face_ref_case =
18455 neighbor->refine_flag_set(),
18456 nb_nb,
18457 neighbor->face_orientation(nb_nb),
18458 neighbor->face_flip(nb_nb),
18459 neighbor->face_rotation(nb_nb));
18460 RefinementCase<dim - 1> needed_face_ref_case =
18462 cell->refine_flag_set(),
18463 i,
18464 cell->face_orientation(i),
18465 cell->face_flip(i),
18466 cell->face_rotation(i));
18467 // if the neighbor wants to refine the
18468 // face with cut_x and we want cut_y
18469 // or vice versa, we have to refine
18470 // isotropically at the given face
18471 if ((face_ref_case ==
18473 needed_face_ref_case ==
18475 (face_ref_case ==
18477 needed_face_ref_case ==
18479 {
18480 changed = cell->flag_for_face_refinement(
18481 i, face_ref_case);
18482 neighbor->flag_for_face_refinement(
18483 nb_nb, needed_face_ref_case);
18484 }
18485 }
18486 }
18487 else //-> the neighbor is not active
18488 {
18489 RefinementCase<dim - 1>
18490 face_ref_case = cell->face(i)->refinement_case(),
18491 needed_face_ref_case =
18493 cell->refine_flag_set(),
18494 i,
18495 cell->face_orientation(i),
18496 cell->face_flip(i),
18497 cell->face_rotation(i));
18498 // if the face is refined with cut_x and
18499 // we want cut_y or vice versa, we have to
18500 // refine isotropically at the given face
18501 if ((face_ref_case == RefinementCase<dim>::cut_x &&
18502 needed_face_ref_case ==
18504 (face_ref_case == RefinementCase<dim>::cut_y &&
18505 needed_face_ref_case ==
18507 changed =
18508 cell->flag_for_face_refinement(i,
18509 face_ref_case);
18510 }
18511 }
18512 }
18513 }
18514 }
18515
18516 //------------------------------------
18517 // STEP 7:
18518 // take care that no double refinement is done at each line in 3d or
18519 // higher dimensions.
18520 this->policy->prepare_refinement_dim_dependent(*this);
18521
18522 //------------------------------------
18523 // STEP 8:
18524 // make sure that all children of each cell are either flagged for
18525 // coarsening or none of the children is
18526 fix_coarsen_flags();
18527
18528 // get the refinement and coarsening flags
18529 auto coarsen_flags_after_loop =
18530 internal::extract_raw_coarsen_flags(levels);
18531 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
18532
18533 // find out whether something was changed in this loop
18534 mesh_changed_in_this_loop =
18535 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
18536 (refine_flags_before_loop != refine_flags_after_loop));
18537
18538 // set the flags for the next loop already
18539 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
18540 refine_flags_before_loop.swap(refine_flags_after_loop);
18541 }
18542 while (mesh_changed_in_this_loop);
18543
18544
18545 // find out whether something was really changed in this
18546 // function. Note that @p{..._flags_before_loop} represents the state
18547 // after the last loop, i.e., the present state
18548 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
18549 (refine_flags_before != refine_flags_before_loop));
18550}
18551
18552
18553
18554template <int dim, int spacedim>
18557 const unsigned int magic_number1,
18558 const std::vector<bool> &v,
18559 const unsigned int magic_number2,
18560 std::ostream &out)
18561{
18562 const unsigned int N = v.size();
18563 unsigned char *flags = new unsigned char[N / 8 + 1];
18564 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18565 flags[i] = 0;
18566
18567 for (unsigned int position = 0; position < N; ++position)
18568 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
18569
18570 AssertThrow(out.fail() == false, ExcIO());
18571
18572 // format:
18573 // 0. magic number
18574 // 1. number of flags
18575 // 2. the flags
18576 // 3. magic number
18577 out << magic_number1 << ' ' << N << std::endl;
18578 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18579 out << static_cast<unsigned int>(flags[i]) << ' ';
18580
18581 out << std::endl << magic_number2 << std::endl;
18582
18583 delete[] flags;
18584
18585 AssertThrow(out.fail() == false, ExcIO());
18586}
18587
18588
18589template <int dim, int spacedim>
18592 const unsigned int magic_number1,
18593 std::vector<bool> &v,
18594 const unsigned int magic_number2,
18595 std::istream &in)
18596{
18597 AssertThrow(in.fail() == false, ExcIO());
18598
18599 unsigned int magic_number;
18600 in >> magic_number;
18601 AssertThrow(magic_number == magic_number1, ExcGridReadError());
18602
18603 unsigned int N;
18604 in >> N;
18605 v.resize(N);
18606
18607 unsigned char *flags = new unsigned char[N / 8 + 1];
18608 unsigned short int tmp;
18609 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18610 {
18611 in >> tmp;
18612 flags[i] = tmp;
18613 }
18614
18615 for (unsigned int position = 0; position != N; ++position)
18616 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
18617
18618 in >> magic_number;
18619 AssertThrow(magic_number == magic_number2, ExcGridReadError());
18620
18621 delete[] flags;
18622
18623 AssertThrow(in.fail() == false, ExcIO());
18624}
18625
18626
18627
18628template <int dim, int spacedim>
18631{
18632 std::size_t mem = 0;
18633 mem += sizeof(MeshSmoothing);
18634 mem += MemoryConsumption::memory_consumption(reference_cells);
18635 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
18637 for (const auto &level : levels)
18640 mem += MemoryConsumption::memory_consumption(vertices_used);
18641 mem += sizeof(default_flat_manifold) + sizeof(*default_flat_manifold);
18642 mem += sizeof(manifolds);
18643 mem += sizeof(smooth_grid);
18644 mem += MemoryConsumption::memory_consumption(number_cache);
18645 mem += sizeof(faces);
18646 if (faces)
18648
18649 return mem;
18650}
18651
18652
18653
18654template <int dim, int spacedim>
18657 default;
18658
18659#endif
18660
18661// explicit instantiations
18662#include "grid/tria.inst"
18663
*  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:4238
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:4614
virtual void clear()
bool anisotropic_refinement
Definition tria.h:4633
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:4691
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:4603
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:4609
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:4640
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:4668
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:4145
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:4595
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:4239
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:4651
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:4214
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:4240
MeshSmoothing smooth_grid
Definition tria.h:4139
void save_refine_flags(std::ostream &out) const
Triangulation< dim, spacedim > & get_triangulation()
std::unique_ptr< Policy > policy
Definition tria.h:4205
void save_user_flags_quad(std::ostream &out) const
void compute_line_to_adjacent_cells_map()
Signals signals
Definition tria.h:2588
virtual ~Triangulation() override
internal::TriangulationImplementation::Strides< dim > strides
Definition tria.h:4150
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:1756
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1747
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1767
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1732
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1708
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1723
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:15815
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:15808
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:1802
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2434
boost::signals2::signal< void(const typename Triangulation< dim, spacedim >::cell_iterator &cell)> post_refinement_on_cell
Definition tria.h:2424
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:12737
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:12817
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:12808
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:12833
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12742
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12825
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:12797
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:12345
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:12432
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:7964
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:12352
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:12665
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:12442
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