deal.II version 9.8.0
\(\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>
23
26
31#include <deal.II/grid/tria.h>
38
39#include <boost/archive/text_iarchive.hpp>
40#include <boost/archive/text_oarchive.hpp>
41
42#include <algorithm>
43#include <array>
44#include <cmath>
45#include <cstdint>
46#include <fstream>
47#include <functional>
48#include <limits>
49#include <list>
50#include <map>
51#include <memory>
52#include <numeric>
53#include <vector>
54
55
57
58
59namespace internal
60{
62 {
64 : n_levels(0)
65 , n_lines(0)
67 // all other fields are
68 // default constructed
69 {}
70
71
72
73 std::size_t
75 {
76 std::size_t mem =
82
84 mem += active_cell_index_partitioner->memory_consumption();
85
86 for (const auto &partitioner : level_cell_index_partitioners)
87 if (partitioner)
88 mem += partitioner->memory_consumption();
89
90 return mem;
91 }
92
93
95 : n_quads(0)
97 // all other fields are
98 // default constructed
99 {}
100
101
102
103 std::size_t
112
113
114
116 : n_hexes(0)
117 , n_active_hexes(0)
118 // all other fields are
119 // default constructed
120 {}
121
122
123
124 std::size_t
133
134
135
136 template <int dim>
138 : max_children_per_cell(numbers::invalid_unsigned_int)
139 , max_faces_per_cell(numbers::invalid_unsigned_int)
140 , max_lines_per_cell(numbers::invalid_unsigned_int)
141 , max_vertices_per_cell(numbers::invalid_unsigned_int)
142 , max_children_per_face(numbers::invalid_unsigned_int)
143 , max_lines_per_face(numbers::invalid_unsigned_int)
144 {}
145
146
147
148 template <int dim>
150 const std::vector<ReferenceCell<dim>> &reference_cells)
157 {
158 for (const ReferenceCell<dim> &reference_cell : reference_cells)
159 {
162 reference_cell.n_isotropic_children());
164 std::max(max_faces_per_cell, reference_cell.n_faces());
166 std::max(max_lines_per_cell, reference_cell.n_lines());
168 std::max(max_vertices_per_cell, reference_cell.n_vertices());
169
170 for (unsigned int face_no : reference_cell.face_indices())
171 {
172 const auto face_reference_cell =
173 reference_cell.face_reference_cell(face_no);
176 face_reference_cell.n_isotropic_children());
178 std::max(max_lines_per_face, face_reference_cell.n_lines());
179 }
180 }
181 }
182 } // namespace TriangulationImplementation
183
184
185 template <int dim, int spacedim>
190
191
192 template <int dim, int spacedim>
195 const std::vector<cell_relation_t> &cell_relations,
196 const std::vector<
197 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
198 &pack_callbacks_fixed,
199 const std::vector<
200 typename internal::CellAttachedData<dim, spacedim>::pack_callback_t>
201 &pack_callbacks_variable,
202 const MPI_Comm &mpi_communicator)
203 {
204 Assert(src_data_fixed.empty(),
205 ExcMessage("Previously packed data has not been released yet!"));
207
208 const unsigned int n_callbacks_fixed = pack_callbacks_fixed.size();
209 const unsigned int n_callbacks_variable = pack_callbacks_variable.size();
210
211 // Store information that we packed variable size data in
212 // a member variable for later.
213 variable_size_data_stored = (n_callbacks_variable > 0);
214
215 // If variable transfer is scheduled, we will store the data size that
216 // each variable size callback function writes in this auxiliary
217 // container. The information will be stored by each cell in this vector
218 // temporarily.
219 std::vector<unsigned int> cell_sizes_variable_cumulative(
220 n_callbacks_variable);
221
222 // Prepare the buffer structure, in which each callback function will
223 // store its data for each active cell.
224 // The outmost shell in this container construct corresponds to the
225 // data packed per cell. The next layer resembles the data that
226 // each callback function packs on the corresponding cell. These
227 // buffers are chains of chars stored in an std::vector<char>.
228 // A visualisation of the data structure:
229 /* clang-format off */
230 // | cell_1 | | cell_2 | ...
231 // || callback_1 || callback_2 |...| || callback_1 || callback_2 |...| ...
232 // |||char|char|...|||char|char|...|...| |||char|char|...|||char|char|...|...| ...
233 /* clang-format on */
234 std::vector<std::vector<std::vector<char>>> packed_fixed_size_data(
235 cell_relations.size());
236 std::vector<std::vector<std::vector<char>>> packed_variable_size_data(
237 variable_size_data_stored ? cell_relations.size() : 0);
238
239 //
240 // --------- Pack data for fixed and variable size transfer ---------
241 //
242 // Iterate over all cells, call all callback functions on each cell,
243 // and store their data in the corresponding buffer scope.
244 {
245 auto cell_rel_it = cell_relations.cbegin();
246 auto data_cell_fixed_it = packed_fixed_size_data.begin();
247 auto data_cell_variable_it = packed_variable_size_data.begin();
248 for (; cell_rel_it != cell_relations.cend(); ++cell_rel_it)
249 {
250 const auto &dealii_cell = cell_rel_it->first;
251 const auto &cell_status = cell_rel_it->second;
252
253 // Assertions about the tree structure.
254 switch (cell_status)
255 {
258 // double check the condition that we will only ever attach
259 // data to active cells when we get here
260 Assert(dealii_cell->is_active(), ExcInternalError());
261 break;
262
264 // double check the condition that we will only ever attach
265 // data to cells with children when we get here. however, we
266 // can only tolerate one level of coarsening at a time, so
267 // check that the children are all active
268 Assert(dealii_cell->is_active() == false, ExcInternalError());
269 for (unsigned int c = 0; c < dealii_cell->n_children(); ++c)
270 Assert(dealii_cell->child(c)->is_active(),
272 break;
273
275 // do nothing on invalid cells
276 break;
277
278 default:
280 break;
281 }
282
283 // Reserve memory corresponding to the number of callback
284 // functions that will be called.
285 // If variable size transfer is scheduled, we need to leave
286 // room for an array that holds information about how many
287 // bytes each of the variable size callback functions will
288 // write.
289 // On cells flagged with CellStatus::cell_invalid, only its CellStatus
290 // will be stored.
291 const unsigned int n_fixed_size_data_sets_on_cell =
292 1 + ((cell_status == CellStatus::cell_invalid) ?
293 0 :
294 ((variable_size_data_stored ? 1 : 0) + n_callbacks_fixed));
295 data_cell_fixed_it->resize(n_fixed_size_data_sets_on_cell);
296
297 // We continue with packing all data on this specific cell.
298 auto data_fixed_it = data_cell_fixed_it->begin();
299
300 // First, we pack the CellStatus information.
301 // to get consistent data sizes on each cell for the fixed size
302 // transfer, we won't allow compression
303 *data_fixed_it =
304 Utilities::pack(cell_status, /*allow_compression=*/false);
305 ++data_fixed_it;
306
307 // Proceed with all registered callback functions.
308 // Skip cells with the CellStatus::cell_invalid flag.
309 if (cell_status != CellStatus::cell_invalid)
310 {
311 // Pack fixed size data.
312 for (auto callback_it = pack_callbacks_fixed.cbegin();
313 callback_it != pack_callbacks_fixed.cend();
314 ++callback_it, ++data_fixed_it)
315 {
316 *data_fixed_it = (*callback_it)(dealii_cell, cell_status);
317 }
318
319 // Pack variable size data.
320 // If we store variable size data, we need to transfer
321 // the sizes of each corresponding callback function
322 // via fixed size transfer as well.
324 {
325 const unsigned int n_variable_size_data_sets_on_cell =
326 ((cell_status == CellStatus::cell_invalid) ?
327 0 :
328 n_callbacks_variable);
329 data_cell_variable_it->resize(
330 n_variable_size_data_sets_on_cell);
331
332 auto callback_it = pack_callbacks_variable.cbegin();
333 auto data_variable_it = data_cell_variable_it->begin();
334 auto sizes_variable_it =
335 cell_sizes_variable_cumulative.begin();
336 for (; callback_it != pack_callbacks_variable.cend();
337 ++callback_it, ++data_variable_it, ++sizes_variable_it)
338 {
339 *data_variable_it =
340 (*callback_it)(dealii_cell, cell_status);
341
342 // Store data sizes for each callback function first.
343 // Make it cumulative below.
344 *sizes_variable_it = data_variable_it->size();
345 }
346
347 // Turn size vector into its cumulative representation.
348 std::partial_sum(cell_sizes_variable_cumulative.begin(),
349 cell_sizes_variable_cumulative.end(),
350 cell_sizes_variable_cumulative.begin());
351
352 // Serialize cumulative variable size vector
353 // value-by-value. This way we can circumvent the overhead
354 // of storing the container object as a whole, since we
355 // know its size by the number of registered callback
356 // functions.
357 data_fixed_it->resize(n_callbacks_variable *
358 sizeof(unsigned int));
359 for (unsigned int i = 0; i < n_callbacks_variable; ++i)
360 std::memcpy(&(data_fixed_it->at(i * sizeof(unsigned int))),
361 &(cell_sizes_variable_cumulative.at(i)),
362 sizeof(unsigned int));
363
364 ++data_fixed_it;
365 }
366
367 // Double check that we packed everything we wanted
368 // in the fixed size buffers.
369 Assert(data_fixed_it == data_cell_fixed_it->end(),
371 }
372
373 ++data_cell_fixed_it;
374
375 // Increment the variable size data iterator
376 // only if we actually pack this kind of data
377 // to avoid getting out of bounds.
379 ++data_cell_variable_it;
380 } // loop over cell_relations
381 }
382
383 //
384 // ----------- Gather data sizes for fixed size transfer ------------
385 //
386 // Generate a vector which stores the sizes of each callback function,
387 // including the packed CellStatus transfer.
388 // Find the very first cell that we wrote to with all callback
389 // functions (i.e. a cell that was not flagged with
390 // CellStatus::cell_invalid) and store the sizes of each buffer.
391 //
392 // To deal with the case that at least one of the processors does not
393 // own any cell at all, we will exchange the information about the data
394 // sizes among them later. The code in between is still well-defined,
395 // since the following loops will be skipped.
396 std::vector<unsigned int> local_sizes_fixed(
397 1 + n_callbacks_fixed + (variable_size_data_stored ? 1 : 0));
398 for (const auto &data_cell : packed_fixed_size_data)
399 {
400 if (data_cell.size() == local_sizes_fixed.size())
401 {
402 auto sizes_fixed_it = local_sizes_fixed.begin();
403 auto data_fixed_it = data_cell.cbegin();
404 for (; data_fixed_it != data_cell.cend();
405 ++data_fixed_it, ++sizes_fixed_it)
406 {
407 *sizes_fixed_it = data_fixed_it->size();
408 }
409
410 break;
411 }
412 }
413
414 // Check if all cells have valid sizes.
415 for (auto data_cell_fixed_it = packed_fixed_size_data.cbegin();
416 data_cell_fixed_it != packed_fixed_size_data.cend();
417 ++data_cell_fixed_it)
418 {
419 Assert((data_cell_fixed_it->size() == 1) ||
420 (data_cell_fixed_it->size() == local_sizes_fixed.size()),
422 }
423
424 // Share information about the packed data sizes
425 // of all callback functions across all processors, in case one
426 // of them does not own any cells at all.
427 std::vector<unsigned int> global_sizes_fixed(local_sizes_fixed.size());
428 Utilities::MPI::max(local_sizes_fixed,
429 mpi_communicator,
430 global_sizes_fixed);
431
432 // Construct cumulative sizes, since this is the only information
433 // we need from now on.
434 sizes_fixed_cumulative.resize(global_sizes_fixed.size());
435 std::partial_sum(global_sizes_fixed.begin(),
436 global_sizes_fixed.end(),
437 sizes_fixed_cumulative.begin());
438
439 //
440 // ---------- Gather data sizes for variable size transfer ----------
441 //
443 {
444 src_sizes_variable.reserve(packed_variable_size_data.size());
445 for (const auto &data_cell : packed_variable_size_data)
446 {
447 int variable_data_size_on_cell = 0;
448
449 for (const auto &data : data_cell)
450 variable_data_size_on_cell += data.size();
451
452 src_sizes_variable.push_back(variable_data_size_on_cell);
453 }
454 }
455
456 //
457 // ------------------------ Build buffers ---------------------------
458 //
459 const unsigned int expected_size_fixed =
460 cell_relations.size() * sizes_fixed_cumulative.back();
461 const unsigned int expected_size_variable =
462 std::accumulate(src_sizes_variable.begin(),
464 std::vector<int>::size_type(0));
465
466 // Move every piece of packed fixed size data into the consecutive
467 // buffer.
468 src_data_fixed.reserve(expected_size_fixed);
469 for (const auto &data_cell_fixed : packed_fixed_size_data)
470 {
471 // Move every fraction of packed data into the buffer
472 // reserved for this particular cell.
473 for (const auto &data_fixed : data_cell_fixed)
474 std::move(data_fixed.begin(),
475 data_fixed.end(),
476 std::back_inserter(src_data_fixed));
477
478 // If we only packed the CellStatus information
479 // (i.e. encountered a cell flagged CellStatus::cell_invalid),
480 // fill the remaining space with invalid entries.
481 // We can skip this if there is nothing else to pack.
482 if ((data_cell_fixed.size() == 1) &&
483 (sizes_fixed_cumulative.size() > 1))
484 {
485 const std::size_t bytes_skipped =
487
488 src_data_fixed.insert(src_data_fixed.end(),
489 bytes_skipped,
490 static_cast<char>(-1)); // invalid_char
491 }
493
494 // Move every piece of packed variable size data into the consecutive
495 // buffer.
496 if (variable_size_data_stored)
497 {
498 src_data_variable.reserve(expected_size_variable);
499 for (const auto &data_cell : packed_variable_size_data)
500 {
501 // Move every fraction of packed data into the buffer
502 // reserved for this particular cell.
503 for (const auto &data : data_cell)
504 std::move(data.begin(),
505 data.end(),
506 std::back_inserter(src_data_variable));
508 }
509
510 // Double check that we packed everything correctly.
511 Assert(src_data_fixed.size() == expected_size_fixed, ExcInternalError());
512 Assert(src_data_variable.size() == expected_size_variable,
514 }
515
516
517
518 template <int dim, int spacedim>
519 DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
521 std::vector<
522 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
523 &cell_relations) const
524 {
526 ExcMessage("No data has been packed!"));
527 if (cell_relations.size() > 0)
528 {
529 Assert(dest_data_fixed.size() > 0,
530 ExcMessage("No data has been received!"));
532
533 // Size of CellStatus object that will be unpacked on each cell.
534 const unsigned int size = sizes_fixed_cumulative.front();
535
536 // Iterate over all cells and overwrite the CellStatus
537 // information from the transferred data.
538 // Proceed buffer iterator position to next cell after
539 // each iteration.
540 auto cell_rel_it = cell_relations.begin();
541 auto dest_fixed_it = dest_data_fixed.cbegin();
542 for (; cell_rel_it != cell_relations.end();
543 ++cell_rel_it, dest_fixed_it += sizes_fixed_cumulative.back())
544 {
545 cell_rel_it->second = // cell_status
546 Utilities::unpack<CellStatus>(dest_fixed_it,
547 dest_fixed_it + size,
548 /*allow_compression=*/false);
549 }
550 }
551
552
553
554 template <int dim, int spacedim>
557 const std::vector<
558 typename CellAttachedDataSerializer<dim, spacedim>::cell_relation_t>
559 &cell_relations,
560 const unsigned int handle,
561 const std::function<
562 void(const cell_iterator &,
563 const CellStatus &,
564 const boost::iterator_range<std::vector<char>::const_iterator> &)>
565 &unpack_callback) const
566 {
567 // We decode the handle returned by register_data_attach() back into
568 // a format we can use. All even handles belong to those callback
569 // functions which write/read variable size data, all odd handles
570 // interact with fixed size buffers.
571 const bool callback_variable_transfer = (handle % 2 == 0);
572 const unsigned int callback_index = handle / 2;
573
574 // Cells will always receive fixed size data (i.e., CellStatus
575 // information), but not necessarily variable size data (e.g., with a
576 // ParticleHandler a cell might not contain any particle at all).
577 // Thus it is sufficient to check if fixed size data has been received.
579 ExcMessage("No data has been packed!"));
580 if (cell_relations.size() > 0)
581 {
582 Assert(dest_data_fixed.size() > 0,
583 ExcMessage("No data has been received!"));
584 }
585
586 std::vector<char>::const_iterator dest_data_it;
587 std::vector<char>::const_iterator dest_sizes_cell_it;
588
589 // Depending on whether our callback function unpacks fixed or
590 // variable size data, we have to pursue different approaches
591 // to localize the correct fraction of the buffer from which
592 // we are allowed to read.
593 unsigned int offset = numbers::invalid_unsigned_int;
594 unsigned int size = numbers::invalid_unsigned_int;
595 unsigned int data_increment = numbers::invalid_unsigned_int;
596
597 if (callback_variable_transfer)
598 {
599 // For the variable size data, we need to extract the
600 // data size from the fixed size buffer on each cell.
601 //
602 // We packed this information last, so the last packed
603 // object in the fixed size buffer corresponds to the
604 // variable data sizes.
605 //
606 // The last entry of sizes_fixed_cumulative corresponds
607 // to the size of all fixed size data packed on the cell.
608 // To get the offset for the last packed object, we need
609 // to get the next-to-last entry.
610 const unsigned int offset_variable_data_sizes =
611 sizes_fixed_cumulative[sizes_fixed_cumulative.size() - 2];
612
613 // This iterator points to the data size that the
614 // callback_function packed for each specific cell.
615 // Adjust buffer iterator to the offset of the callback
616 // function so that we only have to advance its position
617 // to the next cell after each iteration.
618 dest_sizes_cell_it = dest_data_fixed.cbegin() +
619 offset_variable_data_sizes +
620 callback_index * sizeof(unsigned int);
621
622 // Let the data iterator point to the correct buffer.
623 dest_data_it = dest_data_variable.cbegin();
624 }
625 else
626 {
627 // For the fixed size data, we can get the information about
628 // the buffer location on each cell directly from the
629 // sizes_fixed_cumulative vector.
630 offset = sizes_fixed_cumulative[callback_index];
631 size = sizes_fixed_cumulative[callback_index + 1] - offset;
632 data_increment = sizes_fixed_cumulative.back();
633
634 // Let the data iterator point to the correct buffer.
635 // Adjust buffer iterator to the offset of the callback
636 // function so that we only have to advance its position
637 // to the next cell after each iteration.
638 if (cell_relations.begin() != cell_relations.end())
639 dest_data_it = dest_data_fixed.cbegin() + offset;
640 }
641
642 // Iterate over all cells and unpack the transferred data.
643 auto cell_rel_it = cell_relations.begin();
644 auto dest_sizes_it = dest_sizes_variable.cbegin();
645 for (; cell_rel_it != cell_relations.end(); ++cell_rel_it)
646 {
647 const auto &dealii_cell = cell_rel_it->first;
648 const auto &cell_status = cell_rel_it->second;
649
650 if (callback_variable_transfer)
651 {
652 // Update the increment according to the whole data size
653 // of the current cell.
654 data_increment = *dest_sizes_it;
655
656 if (cell_status != CellStatus::cell_invalid)
657 {
658 // Extract the corresponding values for offset and size from
659 // the cumulative sizes array stored in the fixed size
660 // buffer.
661 if (callback_index == 0)
662 offset = 0;
663 else
664 std::memcpy(&offset,
665 &(*(dest_sizes_cell_it - sizeof(unsigned int))),
666 sizeof(unsigned int));
667
668 std::memcpy(&size,
669 &(*dest_sizes_cell_it),
670 sizeof(unsigned int));
671
672 size -= offset;
673
674 // Move the data iterator to the corresponding position
675 // of the callback function and adjust the increment
676 // accordingly.
677 dest_data_it += offset;
678 data_increment -= offset;
679 }
680
681 // Advance data size iterators to the next cell, avoid iterating
682 // past the end of dest_sizes_cell_it
683 if (cell_rel_it != cell_relations.end() - 1)
684 dest_sizes_cell_it += sizes_fixed_cumulative.back();
685 ++dest_sizes_it;
686 }
687
688 switch (cell_status)
689 {
692 unpack_callback(dealii_cell,
693 cell_status,
694 boost::make_iterator_range(dest_data_it,
695 dest_data_it + size));
696 break;
697
699 unpack_callback(dealii_cell->parent(),
700 cell_status,
701 boost::make_iterator_range(dest_data_it,
702 dest_data_it + size));
703 break;
704
706 // Skip this cell.
707 break;
708
709 default:
711 break;
712 }
713
714 if (cell_rel_it != cell_relations.end() - 1)
715 dest_data_it += data_increment;
716 }
717 }
718
719
720
721 template <int dim, int spacedim>
722 DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
723 void CellAttachedDataSerializer<dim, spacedim>::save(
724 const unsigned int global_first_cell,
725 const unsigned int global_num_cells,
726 const std::string &file_basename,
727 const MPI_Comm &mpi_communicator) const
728 {
730 ExcMessage("No data has been packed!"));
731
732#ifdef DEAL_II_WITH_MPI
733 // Large fractions of this function have been copied from
734 // DataOutInterface::write_vtu_in_parallel.
735 // TODO: Write general MPIIO interface.
736
737 const unsigned int myrank =
738 Utilities::MPI::this_mpi_process(mpi_communicator);
739 const unsigned int mpisize =
740 Utilities::MPI::n_mpi_processes(mpi_communicator);
741
742 if (mpisize > 1)
743 {
744 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
745
746 //
747 // ---------- Fixed size data ----------
748 //
749 {
750 const std::string fname_fixed =
751 std::string(file_basename) + "_fixed.data";
752
753 MPI_Info info;
754 int ierr = MPI_Info_create(&info);
755 AssertThrowMPI(ierr);
756
757 MPI_File fh;
758 ierr = MPI_File_open(mpi_communicator,
759 fname_fixed.c_str(),
760 MPI_MODE_CREATE | MPI_MODE_WRONLY,
761 info,
762 &fh);
763 AssertThrowMPI(ierr);
764
765 ierr = MPI_File_set_size(fh, 0); // delete the file contents
766 AssertThrowMPI(ierr);
767 // this barrier is necessary, because otherwise others might already
768 // write while one core is still setting the size to zero.
769 ierr = MPI_Barrier(mpi_communicator);
770 AssertThrowMPI(ierr);
771 ierr = MPI_Info_free(&info);
772 AssertThrowMPI(ierr);
773 // ------------------
774
775 // Write cumulative sizes to file.
776 // Since each processor owns the same information about the data
777 // sizes, it is sufficient to let only the first processor perform
778 // this task.
779 if (myrank == 0)
780 {
782 fh,
783 0,
786 MPI_UNSIGNED,
787 MPI_STATUS_IGNORE);
788 AssertThrowMPI(ierr);
789 }
790
791 // Write packed data to file simultaneously.
792 const MPI_Offset size_header =
793 sizes_fixed_cumulative.size() * sizeof(unsigned int);
794
795 // Make sure we do the following computation in 64bit integers to be
796 // able to handle 4GB+ files:
797 const MPI_Offset my_global_file_position =
798 size_header +
799 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
800
801 ierr =
803 my_global_file_position,
804 src_data_fixed.data(),
805 src_data_fixed.size(),
806 MPI_BYTE,
807 MPI_STATUS_IGNORE);
808 AssertThrowMPI(ierr);
809
810 ierr = MPI_File_close(&fh);
811 AssertThrowMPI(ierr);
812 }
813
814
815
816 //
817 // ---------- Variable size data ----------
818 //
820 {
821 const std::string fname_variable =
822 std::string(file_basename) + "_variable.data";
823
824 MPI_Info info;
825 int ierr = MPI_Info_create(&info);
826 AssertThrowMPI(ierr);
827
828 MPI_File fh;
829 ierr = MPI_File_open(mpi_communicator,
830 fname_variable.c_str(),
831 MPI_MODE_CREATE | MPI_MODE_WRONLY,
832 info,
833 &fh);
834 AssertThrowMPI(ierr);
835
836 ierr = MPI_File_set_size(fh, 0); // delete the file contents
837 AssertThrowMPI(ierr);
838 // this barrier is necessary, because otherwise others might already
839 // write while one core is still setting the size to zero.
840 ierr = MPI_Barrier(mpi_communicator);
841 AssertThrowMPI(ierr);
842 ierr = MPI_Info_free(&info);
843 AssertThrowMPI(ierr);
844
845 // Write sizes of each cell into file simultaneously.
846 {
847 const MPI_Offset my_global_file_position =
848 static_cast<MPI_Offset>(global_first_cell) *
849 sizeof(unsigned int);
850
851 // It is very unlikely that a single process has more than
852 // 2 billion cells, but we might as well check.
854 static_cast<std::size_t>(
855 std::numeric_limits<int>::max()),
857
859 fh,
860 my_global_file_position,
861 src_sizes_variable.data(),
862 src_sizes_variable.size(),
863 MPI_INT,
864 MPI_STATUS_IGNORE);
865 AssertThrowMPI(ierr);
866 }
867
868 // Gather size of data in bytes we want to store from this
869 // processor and compute the prefix sum. We do this in 64 bit
870 // to avoid overflow for files larger than 4GB:
871 const std::uint64_t size_on_proc = src_data_variable.size();
872 std::uint64_t prefix_sum = 0;
873 ierr = MPI_Exscan(&size_on_proc,
874 &prefix_sum,
875 1,
876 MPI_UINT64_T,
877 MPI_SUM,
878 mpi_communicator);
879 AssertThrowMPI(ierr);
880
881 const MPI_Offset my_global_file_position =
882 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
883 prefix_sum;
884
885 // Write data consecutively into file.
887 fh,
888 my_global_file_position,
889 src_data_variable.data(),
890 src_data_variable.size(),
891 MPI_BYTE,
892 MPI_STATUS_IGNORE);
893 AssertThrowMPI(ierr);
894
895
896 ierr = MPI_File_close(&fh);
897 AssertThrowMPI(ierr);
898 }
899 } // if (mpisize > 1)
900 else
901#endif
902 {
903 (void)global_first_cell;
904 (void)global_num_cells;
905 (void)mpi_communicator;
906
907 //
908 // ---------- Fixed size data ----------
909 //
910 {
911 const std::string fname_fixed =
912 std::string(file_basename) + "_fixed.data";
913
914 std::ofstream file(fname_fixed, std::ios::binary | std::ios::out);
915 AssertThrow(file.fail() == false, ExcIO());
916
917 // Write header data.
918 file.write(reinterpret_cast<const char *>(
920 sizes_fixed_cumulative.size() * sizeof(unsigned int));
921
922 // Write packed data.
923 file.write(reinterpret_cast<const char *>(src_data_fixed.data()),
924 src_data_fixed.size() * sizeof(char));
925 }
926
927 //
928 // ---------- Variable size data ----------
929 //
931 {
932 const std::string fname_variable =
933 std::string(file_basename) + "_variable.data";
934
935 std::ofstream file(fname_variable,
936 std::ios::binary | std::ios::out);
937 AssertThrow(file.fail() == false, ExcIO());
938
939 // Write header data.
940 file.write(reinterpret_cast<const char *>(
941 src_sizes_variable.data()),
942 src_sizes_variable.size() * sizeof(int));
943
944 // Write packed data.
945 file.write(reinterpret_cast<const char *>(src_data_variable.data()),
946 src_data_variable.size() * sizeof(char));
947 }
948 }
949 }
950
951
952 template <int dim, int spacedim>
954 void CellAttachedDataSerializer<dim, spacedim>::load(
955 const unsigned int global_first_cell,
956 const unsigned int global_num_cells,
957 const unsigned int local_num_cells,
958 const std::string &file_basename,
959 const unsigned int n_attached_deserialize_fixed,
960 const unsigned int n_attached_deserialize_variable,
961 const MPI_Comm &mpi_communicator)
962 {
963 Assert(dest_data_fixed.empty(),
964 ExcMessage("Previously loaded data has not been released yet!"));
965
966 variable_size_data_stored = (n_attached_deserialize_variable > 0);
967
968#ifdef DEAL_II_WITH_MPI
969 // Large fractions of this function have been copied from
970 // DataOutInterface::write_vtu_in_parallel.
971 // TODO: Write general MPIIO interface.
972
973 const unsigned int mpisize =
974 Utilities::MPI::n_mpi_processes(mpi_communicator);
975
976 if (mpisize > 1)
977 {
978 //
979 // ---------- Fixed size data ----------
980 //
981 {
982 const std::string fname_fixed =
983 std::string(file_basename) + "_fixed.data";
984
985 MPI_Info info;
986 int ierr = MPI_Info_create(&info);
987 AssertThrowMPI(ierr);
988
989 MPI_File fh;
990 ierr = MPI_File_open(
991 mpi_communicator, fname_fixed.c_str(), MPI_MODE_RDONLY, info, &fh);
992 AssertThrowMPI(ierr);
993
994 ierr = MPI_Info_free(&info);
995 AssertThrowMPI(ierr);
996
997 // Read cumulative sizes from file.
998 // Since all processors need the same information about the data
999 // sizes, let each of them retrieve it by reading from the same
1000 // location in the file.
1001 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1002 (variable_size_data_stored ? 1 : 0));
1004 fh,
1005 0,
1008 MPI_UNSIGNED,
1009 MPI_STATUS_IGNORE);
1010 AssertThrowMPI(ierr);
1011
1012 // Allocate sufficient memory.
1013 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1014 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
1015 bytes_per_cell);
1016
1017 // Read packed data from file simultaneously.
1018 const MPI_Offset size_header =
1019 sizes_fixed_cumulative.size() * sizeof(unsigned int);
1020
1021 // Make sure we do the following computation in 64bit integers to be
1022 // able to handle 4GB+ files:
1023 const MPI_Offset my_global_file_position =
1024 size_header +
1025 static_cast<MPI_Offset>(global_first_cell) * bytes_per_cell;
1026
1027 ierr =
1029 my_global_file_position,
1030 dest_data_fixed.data(),
1031 dest_data_fixed.size(),
1032 MPI_BYTE,
1033 MPI_STATUS_IGNORE);
1034 AssertThrowMPI(ierr);
1035
1036
1037 ierr = MPI_File_close(&fh);
1038 AssertThrowMPI(ierr);
1039 }
1040
1041 //
1042 // ---------- Variable size data ----------
1043 //
1045 {
1046 const std::string fname_variable =
1047 std::string(file_basename) + "_variable.data";
1048
1049 MPI_Info info;
1050 int ierr = MPI_Info_create(&info);
1051 AssertThrowMPI(ierr);
1052
1053 MPI_File fh;
1054 ierr = MPI_File_open(mpi_communicator,
1055 fname_variable.c_str(),
1056 MPI_MODE_RDONLY,
1057 info,
1058 &fh);
1059 AssertThrowMPI(ierr);
1060
1061 ierr = MPI_Info_free(&info);
1062 AssertThrowMPI(ierr);
1063
1064 // Read sizes of all locally owned cells.
1065 dest_sizes_variable.resize(local_num_cells);
1066
1067 const MPI_Offset my_global_file_position_sizes =
1068 static_cast<MPI_Offset>(global_first_cell) * sizeof(unsigned int);
1069
1071 fh,
1072 my_global_file_position_sizes,
1073 dest_sizes_variable.data(),
1074 dest_sizes_variable.size(),
1075 MPI_INT,
1076 MPI_STATUS_IGNORE);
1077 AssertThrowMPI(ierr);
1078
1079
1080 // Compute my data size in bytes and compute prefix sum. We do this
1081 // in 64 bit to avoid overflow for files larger than 4 GB:
1082 const std::uint64_t size_on_proc =
1083 std::accumulate(dest_sizes_variable.begin(),
1084 dest_sizes_variable.end(),
1085 0ULL);
1086
1087 std::uint64_t prefix_sum = 0;
1088 ierr = MPI_Exscan(&size_on_proc,
1089 &prefix_sum,
1090 1,
1091 MPI_UINT64_T,
1092 MPI_SUM,
1093 mpi_communicator);
1094 AssertThrowMPI(ierr);
1095
1096 const MPI_Offset my_global_file_position =
1097 static_cast<MPI_Offset>(global_num_cells) * sizeof(unsigned int) +
1098 prefix_sum;
1099
1100 dest_data_variable.resize(size_on_proc);
1101
1103 fh,
1104 my_global_file_position,
1105 dest_data_variable.data(),
1106 dest_data_variable.size(),
1107 MPI_BYTE,
1108 MPI_STATUS_IGNORE);
1109 AssertThrowMPI(ierr);
1110
1111 ierr = MPI_File_close(&fh);
1112 AssertThrowMPI(ierr);
1113 }
1114 }
1115 else // if (mpisize > 1)
1116#endif
1117 {
1118 (void)mpi_communicator;
1119 (void)global_first_cell;
1120 (void)global_num_cells;
1121
1122 //
1123 // ---------- Fixed size data ----------
1124 //
1125 {
1126 const std::string fname_fixed =
1127 std::string(file_basename) + "_fixed.data";
1128
1129 std::ifstream file(fname_fixed, std::ios::binary | std::ios::in);
1130 AssertThrow(file.fail() == false, ExcIO());
1131
1132 sizes_fixed_cumulative.resize(1 + n_attached_deserialize_fixed +
1133 (variable_size_data_stored ? 1 : 0));
1134 // Read header data.
1135 file.read(reinterpret_cast<char *>(sizes_fixed_cumulative.data()),
1136 sizes_fixed_cumulative.size() * sizeof(unsigned int));
1137
1138 const unsigned int bytes_per_cell = sizes_fixed_cumulative.back();
1139 dest_data_fixed.resize(static_cast<std::size_t>(local_num_cells) *
1140 bytes_per_cell);
1141
1142 // Read packed data.
1143 file.read(reinterpret_cast<char *>(dest_data_fixed.data()),
1144 dest_data_fixed.size() * sizeof(char));
1145 }
1146
1147 //
1148 // ---------- Variable size data ----------
1149 //
1151 {
1152 const std::string fname_variable =
1153 std::string(file_basename) + "_variable.data";
1154
1155 std::ifstream file(fname_variable, std::ios::binary | std::ios::in);
1156 AssertThrow(file.fail() == false, ExcIO());
1157
1158 // Read header data.
1159 dest_sizes_variable.resize(local_num_cells);
1160 file.read(reinterpret_cast<char *>(dest_sizes_variable.data()),
1161 dest_sizes_variable.size() * sizeof(int));
1162
1163 // Read packed data.
1164 const std::uint64_t size =
1165 std::accumulate(dest_sizes_variable.begin(),
1166 dest_sizes_variable.end(),
1167 0ULL);
1168 dest_data_variable.resize(size);
1169 file.read(reinterpret_cast<char *>(dest_data_variable.data()),
1170 dest_data_variable.size() * sizeof(char));
1171 }
1172 }
1173 }
1174
1175
1176 template <int dim, int spacedim>
1178 void CellAttachedDataSerializer<dim, spacedim>::clear()
1179 {
1181
1182 // free information about data sizes
1183 sizes_fixed_cumulative.clear();
1184 sizes_fixed_cumulative.shrink_to_fit();
1185
1186 // free fixed size transfer data
1187 src_data_fixed.clear();
1188 src_data_fixed.shrink_to_fit();
1189
1190 dest_data_fixed.clear();
1191 dest_data_fixed.shrink_to_fit();
1192
1193 // free variable size transfer data
1194 src_sizes_variable.clear();
1195 src_sizes_variable.shrink_to_fit();
1196
1197 src_data_variable.clear();
1198 src_data_variable.shrink_to_fit();
1199
1200 dest_sizes_variable.clear();
1201 dest_sizes_variable.shrink_to_fit();
1202
1203 dest_data_variable.clear();
1204 dest_data_variable.shrink_to_fit();
1205 }
1206
1207} // namespace internal
1208
1209// anonymous namespace for internal helper functions
1210namespace
1211{
1212 // return whether the given cell is
1213 // patch_level_1, i.e. determine
1214 // whether either all or none of
1215 // its children are further
1216 // refined. this function can only
1217 // be called for non-active cells.
1218 template <int dim, int spacedim>
1219 bool
1220 cell_is_patch_level_1(
1222 {
1223 Assert(cell->is_active() == false, ExcInternalError());
1224
1225 unsigned int n_active_children = 0;
1226 for (unsigned int i = 0; i < cell->n_children(); ++i)
1227 if (cell->child(i)->is_active())
1228 ++n_active_children;
1229
1230 return (n_active_children == 0) ||
1231 (n_active_children == cell->n_children());
1232 }
1233
1234
1235
1236 // return, whether a given @p cell will be
1237 // coarsened, which is the case if all
1238 // children are active and have their coarsen
1239 // flag set. In case only part of the coarsen
1240 // flags are set, remove them.
1241 template <int dim, int spacedim>
1242 bool
1243 cell_will_be_coarsened(
1245 {
1246 // only cells with children should be
1247 // considered for coarsening
1248
1249 if (cell->has_children())
1250 {
1251 unsigned int children_to_coarsen = 0;
1252 const unsigned int n_children = cell->n_children();
1253
1254 for (unsigned int c = 0; c < n_children; ++c)
1255 if (cell->child(c)->is_active() && cell->child(c)->coarsen_flag_set())
1256 ++children_to_coarsen;
1257 if (children_to_coarsen == n_children)
1258 return true;
1259 else
1260 for (unsigned int c = 0; c < n_children; ++c)
1261 if (cell->child(c)->is_active())
1262 cell->child(c)->clear_coarsen_flag();
1263 }
1264 // no children, so no coarsening
1265 // possible. however, no children also
1266 // means that this cell will be in the same
1267 // state as if it had children and was
1268 // coarsened. So, what should we return -
1269 // false or true?
1270 // make sure we do not have to do this at
1271 // all...
1272 Assert(cell->has_children(), ExcInternalError());
1273 // ... and then simply return false
1274 return false;
1275 }
1276
1277
1278 // return, whether the face @p face_no of the
1279 // given @p cell will be refined after the
1280 // current refinement step, considering
1281 // refine and coarsen flags and considering
1282 // only those refinemnts that will be caused
1283 // by the neighboring cell.
1284
1285 // this function is used on both active cells
1286 // and cells with children. on cells with
1287 // children it also of interest to know 'how'
1288 // the face will be refined. thus there is an
1289 // additional third argument @p
1290 // expected_face_ref_case returning just
1291 // that. be aware, that this variable will
1292 // only contain useful information if this
1293 // function is called for an active cell.
1294 //
1295 // thus, this is an internal function, users
1296 // should call one of the two alternatives
1297 // following below.
1298 template <int dim, int spacedim>
1299 bool
1300 face_will_be_refined_by_neighbor_internal(
1302 const unsigned int face_no,
1303 RefinementCase<dim - 1> &expected_face_ref_case)
1304 {
1305 // first of all: set the default value for
1306 // expected_face_ref_case, which is no
1307 // refinement at all
1308 expected_face_ref_case = RefinementCase<dim - 1>::no_refinement;
1309
1310 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
1311 cell->neighbor(face_no);
1312
1313 // If we are at the boundary, there is no
1314 // neighbor which could refine the face
1315 if (neighbor.state() != IteratorState::valid)
1316 return false;
1317
1318 if (neighbor->has_children())
1319 {
1320 // if the neighbor is refined, it may be
1321 // coarsened. if so, then it won't refine
1322 // the face, no matter what else happens
1323 if (cell_will_be_coarsened(neighbor))
1324 return false;
1325 else
1326 // if the neighbor is refined, then it
1327 // is also refined at our current
1328 // face. It will stay so without
1329 // coarsening, so return true in that
1330 // case.
1331 {
1332 expected_face_ref_case = cell->face(face_no)->refinement_case();
1333 return true;
1334 }
1335 }
1336
1337 // now, the neighbor is not refined, but
1338 // perhaps it will be
1339 const RefinementCase<dim> nb_ref_flag = neighbor->refine_flag_set();
1340 if (nb_ref_flag != RefinementCase<dim>::no_refinement)
1341 {
1342 // now we need to know, which of the
1343 // neighbors faces points towards us
1344 const unsigned int neighbor_neighbor = cell->neighbor_face_no(face_no);
1345 // check, whether the cell will be
1346 // refined in a way that refines our
1347 // face
1348 const RefinementCase<dim - 1> face_ref_case =
1350 nb_ref_flag,
1351 neighbor_neighbor,
1352 neighbor->face_orientation(neighbor_neighbor),
1353 neighbor->face_flip(neighbor_neighbor),
1354 neighbor->face_rotation(neighbor_neighbor));
1355 if (face_ref_case != RefinementCase<dim - 1>::no_refinement)
1356 {
1358 neighbor_face = neighbor->face(neighbor_neighbor);
1359 const int this_face_index = cell->face_index(face_no);
1360
1361 // there are still two basic
1362 // possibilities here: the neighbor
1363 // might be coarser or as coarse
1364 // as we are
1365 if (neighbor_face->index() == this_face_index)
1366 // the neighbor is as coarse as
1367 // we are and will be refined at
1368 // the face of consideration, so
1369 // return true
1370 {
1371 expected_face_ref_case = face_ref_case;
1372 return true;
1373 }
1374 else
1375 {
1376 // the neighbor is coarser.
1377 // this is the most complicated
1378 // case. It might be, that the
1379 // neighbor's face will be
1380 // refined, but that we will
1381 // not see this, as we are
1382 // refined in a similar way.
1383
1384 // so, the neighbor's face must
1385 // have children. check, if our
1386 // cell's face is one of these
1387 // (it could also be a
1388 // grand_child)
1389 for (unsigned int c = 0; c < neighbor_face->n_children(); ++c)
1390 if (neighbor_face->child_index(c) == this_face_index)
1391 {
1392 // if the flagged refine
1393 // case of the face is a
1394 // subset or the same as
1395 // the current refine case,
1396 // then the face, as seen
1397 // from our cell, won't be
1398 // refined by the neighbor
1399 if ((neighbor_face->refinement_case() | face_ref_case) ==
1400 neighbor_face->refinement_case())
1401 return false;
1402 else
1403 {
1404 // if we are active, we
1405 // must be an
1406 // anisotropic child
1407 // and the coming
1408 // face_ref_case is
1409 // isotropic. Thus,
1410 // from our cell we
1411 // will see exactly the
1412 // opposite refine case
1413 // that the face has
1414 // now...
1415 Assert(
1416 face_ref_case ==
1419 expected_face_ref_case =
1420 ~neighbor_face->refinement_case();
1421 return true;
1422 }
1423 }
1424
1425 // so, obviously we were not
1426 // one of the children, but a
1427 // grandchild. This is only
1428 // possible in 3d.
1429 Assert(dim == 3, ExcInternalError());
1430 // In that case, however, no
1431 // matter what the neighbor
1432 // does, it won't be finer
1433 // after the next refinement
1434 // step.
1435 return false;
1436 }
1437 } // if face will be refined
1438 } // if neighbor is flagged for refinement
1439
1440 // no cases left, so the neighbor will not
1441 // refine the face
1442 return false;
1443 }
1444
1445 // version of above function for both active
1446 // and non-active cells
1447 template <int dim, int spacedim>
1448 bool
1449 face_will_be_refined_by_neighbor(
1451 const unsigned int face_no)
1452 {
1453 RefinementCase<dim - 1> dummy = RefinementCase<dim - 1>::no_refinement;
1454 return face_will_be_refined_by_neighbor_internal(cell, face_no, dummy);
1455 }
1456
1457 // version of above function for active cells
1458 // only. Additionally returning the refine
1459 // case (to come) of the face under
1460 // consideration
1461 template <int dim, int spacedim>
1462 bool
1463 face_will_be_refined_by_neighbor(
1465 const unsigned int face_no,
1466 RefinementCase<dim - 1> &expected_face_ref_case)
1467 {
1468 return face_will_be_refined_by_neighbor_internal(cell,
1469 face_no,
1470 expected_face_ref_case);
1471 }
1472
1473
1474
1475 template <int dim, int spacedim>
1476 bool
1477 satisfies_level1_at_vertex_rule(
1478 const Triangulation<dim, spacedim> &triangulation)
1479 {
1480 std::vector<unsigned int> min_adjacent_cell_level(
1481 triangulation.n_vertices(), triangulation.n_levels());
1482 std::vector<unsigned int> max_adjacent_cell_level(
1483 triangulation.n_vertices(), 0);
1484
1485 for (const auto &cell : triangulation.active_cell_iterators())
1486 for (const unsigned int v : cell->vertex_indices())
1487 {
1488 min_adjacent_cell_level[cell->vertex_index(v)] =
1490 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1491 max_adjacent_cell_level[cell->vertex_index(v)] =
1493 min_adjacent_cell_level[cell->vertex_index(v)], cell->level());
1494 }
1495
1496 for (unsigned int k = 0; k < triangulation.n_vertices(); ++k)
1497 if (triangulation.vertex_used(k))
1498 if (max_adjacent_cell_level[k] - min_adjacent_cell_level[k] > 1)
1499 return false;
1500 return true;
1501 }
1502
1503
1504
1522 template <int dim, int spacedim>
1523 unsigned int
1524 middle_vertex_index(
1526 {
1527 if (line->has_children())
1528 return line->child(0)->vertex_index(1);
1530 }
1531
1532
1533 template <int dim, int spacedim>
1534 unsigned int
1535 middle_vertex_index(
1537 {
1538 switch (static_cast<unsigned char>(quad->refinement_case()))
1539 {
1541 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(1));
1542 break;
1544 return middle_vertex_index<dim, spacedim>(quad->child(0)->line(3));
1545 break;
1547 return quad->child(0)->vertex_index(3);
1548 break;
1549 default:
1550 break;
1551 }
1553 }
1554
1555
1556 template <int dim, int spacedim>
1557 unsigned int
1558 middle_vertex_index(
1560 {
1561 switch (static_cast<unsigned char>(hex->refinement_case()))
1562 {
1564 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(1));
1565 break;
1567 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(3));
1568 break;
1570 return middle_vertex_index<dim, spacedim>(hex->child(0)->quad(5));
1571 break;
1573 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(11));
1574 break;
1576 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(5));
1577 break;
1579 return middle_vertex_index<dim, spacedim>(hex->child(0)->line(7));
1580 break;
1582 return hex->child(0)->vertex_index(7);
1583 break;
1584 default:
1585 break;
1586 }
1588 }
1589
1590
1603 template <class TRIANGULATION>
1604 typename TRIANGULATION::DistortedCellList
1605 collect_distorted_coarse_cells(const TRIANGULATION &)
1606 {
1607 return typename TRIANGULATION::DistortedCellList();
1608 }
1609
1610
1611
1620 template <int dim>
1622 collect_distorted_coarse_cells(const Triangulation<dim, dim> &triangulation)
1623 {
1624 typename Triangulation<dim, dim>::DistortedCellList distorted_cells;
1625 for (const auto &cell : triangulation.cell_iterators_on_level(0))
1626 {
1628 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1629 vertices[i] = cell->vertex(i);
1630
1633
1634 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1635 if (determinants[i] <=
1636 1e-9 * Utilities::fixed_power<dim>(cell->diameter()))
1637 {
1638 distorted_cells.distorted_cells.push_back(cell);
1639 break;
1640 }
1641 }
1642
1643 return distorted_cells;
1644 }
1645
1646
1653 template <int dim>
1654 bool
1655 has_distorted_children(
1656 const typename Triangulation<dim, dim>::cell_iterator &cell)
1657 {
1659
1660 for (unsigned int c = 0; c < cell->n_children(); ++c)
1661 {
1663 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1664 vertices[i] = cell->child(c)->vertex(i);
1665
1668
1669 for (const unsigned int i : GeometryInfo<dim>::vertex_indices())
1670 if (determinants[i] <=
1671 1e-9 * Utilities::fixed_power<dim>(cell->child(c)->diameter()))
1672 return true;
1673 }
1674
1675 return false;
1676 }
1677
1678
1686 template <int dim, int spacedim>
1687 bool
1688 has_distorted_children(
1690 {
1691 return false;
1692 }
1693
1694
1695 template <int dim, int spacedim>
1696 void
1697 update_periodic_face_map_recursively(
1698 const typename Triangulation<dim, spacedim>::cell_iterator &cell_1,
1699 const typename Triangulation<dim, spacedim>::cell_iterator &cell_2,
1700 unsigned int n_face_1,
1701 unsigned int n_face_2,
1702 const types::geometric_orientation orientation,
1703 typename std::map<
1705 unsigned int>,
1706 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1707 unsigned int>,
1708 types::geometric_orientation>> &periodic_face_map)
1709 {
1710 using FaceIterator = typename Triangulation<dim, spacedim>::face_iterator;
1711 const FaceIterator face_1 = cell_1->face(n_face_1);
1712 const FaceIterator face_2 = cell_2->face(n_face_2);
1713
1714 const auto inverse_orientation =
1715 face_1->reference_cell().get_inverse_combined_orientation(orientation);
1716
1717 if constexpr (running_in_debug_mode())
1718 {
1719 const auto [face_orientation, face_rotation, face_flip] =
1721
1722 Assert((dim != 1) || (face_orientation == true && face_flip == false &&
1723 face_rotation == false),
1724 ExcMessage("The supplied orientation "
1725 "(face_orientation, face_flip, face_rotation) "
1726 "is invalid for 1d"));
1727
1728 Assert((dim != 2) || (face_flip == false && face_rotation == false),
1729 ExcMessage("The supplied orientation "
1730 "(face_orientation, face_flip, face_rotation) "
1731 "is invalid for 2d"));
1732 }
1733
1734 Assert(face_1 != face_2, ExcMessage("face_1 and face_2 are equal!"));
1735
1736 Assert(face_1->at_boundary() && face_2->at_boundary(),
1737 ExcMessage("Periodic faces must be on the boundary"));
1738
1739 // Check if the requirement that each edge can only have at most one hanging
1740 // node, and as a consequence neighboring cells can differ by at most
1741 // one refinement level is enforced. In 1d, there are no hanging nodes and
1742 // so neighboring cells can differ by more than one refinement level.
1743 Assert(dim == 1 || std::abs(cell_1->level() - cell_2->level()) < 2,
1745
1746 // insert periodic face pair for both cells
1747 using CellFace =
1748 std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
1749 unsigned int>;
1750 const CellFace cell_face_1(cell_1, n_face_1);
1751 const CellFace cell_face_2(cell_2, n_face_2);
1752 const std::pair<CellFace, types::geometric_orientation>
1753 cell_face_orientation_2(cell_face_2, orientation);
1754
1755 const std::pair<CellFace, std::pair<CellFace, types::geometric_orientation>>
1756 periodic_faces(cell_face_1, cell_face_orientation_2);
1757
1758 // Only one periodic neighbor is allowed
1759 Assert(periodic_face_map.count(cell_face_1) == 0, ExcInternalError());
1760 periodic_face_map.insert(periodic_faces);
1761
1762 if (dim == 1)
1763 {
1764 if (cell_1->has_children())
1765 {
1766 if (cell_2->has_children())
1767 {
1768 update_periodic_face_map_recursively<dim, spacedim>(
1769 cell_1->child(n_face_1),
1770 cell_2->child(n_face_2),
1771 n_face_1,
1772 n_face_2,
1773 orientation,
1774 periodic_face_map);
1775 }
1776 else // only face_1 has children
1777 {
1778 update_periodic_face_map_recursively<dim, spacedim>(
1779 cell_1->child(n_face_1),
1780 cell_2,
1781 n_face_1,
1782 n_face_2,
1783 orientation,
1784 periodic_face_map);
1785 }
1786 }
1787 }
1788 else // dim == 2 || dim == 3
1789 {
1790 if (cell_1->has_children())
1791 {
1792 if (cell_2->has_children())
1793 {
1794 // In the case that both faces have children, we loop over all
1795 // children and apply update_periodic_face_map_recursively
1796 // recursively:
1797
1798 Assert(face_1->n_children() ==
1800 face_2->n_children() ==
1803
1804 const auto reference_cell = cell_1->reference_cell();
1805
1806 for (unsigned int i = 0;
1807 i < GeometryInfo<dim>::max_children_per_face;
1808 ++i)
1809 {
1810 // Lookup the index for the second face
1811 const unsigned int j =
1812 reference_cell.standard_to_real_face_vertex(
1813 i, n_face_1, inverse_orientation);
1814
1815 // find subcell ids that belong to the subface indices
1816 unsigned int child_cell_1 =
1818 cell_1->refinement_case(),
1819 n_face_1,
1820 i,
1821 cell_1->face_orientation(n_face_1),
1822 cell_1->face_flip(n_face_1),
1823 cell_1->face_rotation(n_face_1),
1824 face_1->refinement_case());
1825 unsigned int child_cell_2 =
1827 cell_2->refinement_case(),
1828 n_face_2,
1829 j,
1830 cell_2->face_orientation(n_face_2),
1831 cell_2->face_flip(n_face_2),
1832 cell_2->face_rotation(n_face_2),
1833 face_2->refinement_case());
1834
1835 Assert(cell_1->child(child_cell_1)->face(n_face_1) ==
1836 face_1->child(i),
1838 Assert(cell_2->child(child_cell_2)->face(n_face_2) ==
1839 face_2->child(j),
1841
1842 // precondition: subcell has the same orientation as cell
1843 // (so that the face numbers coincide) recursive call
1844 update_periodic_face_map_recursively<dim, spacedim>(
1845 cell_1->child(child_cell_1),
1846 cell_2->child(child_cell_2),
1847 n_face_1,
1848 n_face_2,
1849 orientation,
1850 periodic_face_map);
1851 }
1852 }
1853 else // only face_1 has children
1854 {
1855 for (unsigned int i = 0;
1856 i < GeometryInfo<dim>::max_children_per_face;
1857 ++i)
1858 {
1859 // find subcell ids that belong to the subface indices
1860 unsigned int child_cell_1 =
1862 cell_1->refinement_case(),
1863 n_face_1,
1864 i,
1865 cell_1->face_orientation(n_face_1),
1866 cell_1->face_flip(n_face_1),
1867 cell_1->face_rotation(n_face_1),
1868 face_1->refinement_case());
1869
1870 // recursive call
1871 update_periodic_face_map_recursively<dim, spacedim>(
1872 cell_1->child(child_cell_1),
1873 cell_2,
1874 n_face_1,
1875 n_face_2,
1876 orientation,
1877 periodic_face_map);
1878 }
1879 }
1880 }
1881 }
1882 }
1883
1884 // Given the child number and parent's line orientation, return the child face
1885 // number.
1886 unsigned int
1887 child_line_index(const unsigned int child_no,
1888 const types::geometric_orientation line_orientation)
1889 {
1890 AssertIndexRange(child_no, ReferenceCells::Line.n_children());
1891 Assert(line_orientation == numbers::default_geometric_orientation ||
1892 line_orientation == numbers::reverse_line_orientation,
1894 constexpr auto D = numbers::default_geometric_orientation;
1895 if (child_no == 0)
1896 return line_orientation == D ? 0 : 1;
1897 else
1898 return line_orientation == D ? 1 : 0;
1899 }
1900} // end of anonymous namespace
1901
1902
1903namespace internal
1904{
1906 {
1907 // make sure that if in the following we
1908 // write Triangulation<dim,spacedim>
1909 // we mean the *class*
1910 // ::Triangulation, not the
1911 // enclosing namespace
1912 // internal::TriangulationImplementation
1913 using ::Triangulation;
1914
1920 int,
1921 << "Something went wrong upon construction of cell "
1922 << arg1);
1933 int,
1934 << "Cell " << arg1
1935 << " has negative measure. This typically "
1936 << "indicates some distortion in the cell, or a mistakenly "
1937 << "swapped pair of vertices in the input to "
1938 << "Triangulation::create_triangulation().");
1947 int,
1948 int,
1949 int,
1950 << "Error while creating cell " << arg1
1951 << ": the vertex index " << arg2 << " must be between 0 and "
1952 << arg3 << '.');
1959 int,
1960 int,
1962 << "The input data for creating a triangulation contained "
1963 << "information about a line with indices " << arg1 << " and " << arg2
1964 << " that is described to have boundary indicator "
1965 << static_cast<int>(arg3)
1966 << ". However, this is an internal line not located on the "
1967 << "boundary. You cannot assign a boundary indicator to it." << std::endl
1968 << std::endl
1969 << "If this happened at a place where you call "
1970 << "Triangulation::create_triangulation() yourself, you need "
1971 << "to check the SubCellData object you pass to this function."
1972 << std::endl
1973 << std::endl
1974 << "If this happened in a place where you are reading a mesh "
1975 << "from a file, then you need to investigate why such a line "
1976 << "ended up in the input file. A typical case is a geometry "
1977 << "that consisted of multiple parts and for which the mesh "
1978 << "generator program assumes that the interface between "
1979 << "two parts is a boundary when that isn't supposed to be "
1980 << "the case, or where the mesh generator simply assigns "
1981 << "'geometry indicators' to lines at the perimeter of "
1982 << "a part that are not supposed to be interpreted as "
1983 << "'boundary indicators'.");
1990 int,
1991 int,
1992 int,
1993 int,
1995 << "The input data for creating a triangulation contained "
1996 << "information about a quad with indices " << arg1 << ", " << arg2
1997 << ", " << arg3 << ", and " << arg4
1998 << " that is described to have boundary indicator "
1999 << static_cast<int>(arg5)
2000 << ". However, this is an internal quad not located on the "
2001 << "boundary. You cannot assign a boundary indicator to it." << std::endl
2002 << std::endl
2003 << "If this happened at a place where you call "
2004 << "Triangulation::create_triangulation() yourself, you need "
2005 << "to check the SubCellData object you pass to this function."
2006 << std::endl
2007 << std::endl
2008 << "If this happened in a place where you are reading a mesh "
2009 << "from a file, then you need to investigate why such a quad "
2010 << "ended up in the input file. A typical case is a geometry "
2011 << "that consisted of multiple parts and for which the mesh "
2012 << "generator program assumes that the interface between "
2013 << "two parts is a boundary when that isn't supposed to be "
2014 << "the case, or where the mesh generator simply assigns "
2015 << "'geometry indicators' to quads at the surface of "
2016 << "a part that are not supposed to be interpreted as "
2017 << "'boundary indicators'.");
2024 int,
2025 int,
2026 << "In SubCellData the line info of the line with vertex indices " << arg1
2027 << " and " << arg2 << " appears more than once. "
2028 << "This is not allowed.");
2035 int,
2036 int,
2037 std::string,
2038 << "In SubCellData the line info of the line with vertex indices " << arg1
2039 << " and " << arg2 << " appears multiple times with different (valid) "
2040 << arg3 << ". This is not allowed.");
2047 int,
2048 int,
2049 int,
2050 int,
2051 std::string,
2052 << "In SubCellData the quad info of the quad with line indices " << arg1
2053 << ", " << arg2 << ", " << arg3 << " and " << arg4
2054 << " appears multiple times with different (valid) " << arg5
2055 << ". This is not allowed.");
2056
2061 int,
2062 int,
2063 << "The containers have sizes " << arg1 << " and " << arg2
2064 << ", which is not as expected.");
2065
2071 template <int dim, int spacedim>
2072 void
2074 const unsigned int true_dimension)
2075 {
2076 Assert(2 * true_dimension * tria_level.refine_flags.size() ==
2077 tria_level.neighbors.size(),
2078 ExcMemoryInexact(tria_level.refine_flags.size(),
2079 tria_level.neighbors.size()));
2080 Assert(2 * true_dimension * tria_level.coarsen_flags.size() ==
2081 tria_level.neighbors.size(),
2082 ExcMemoryInexact(tria_level.coarsen_flags.size(),
2083 tria_level.neighbors.size()));
2084 }
2085
2086
2087
2093 void
2094 monitor_memory(const TriaObjects &tria_object, const unsigned int)
2095 {
2096 Assert(tria_object.n_objects() == tria_object.used.size(),
2097 ExcMemoryInexact(tria_object.n_objects(),
2098 tria_object.used.size()));
2099 Assert(tria_object.n_objects() == tria_object.user_flags.size(),
2100 ExcMemoryInexact(tria_object.n_objects(),
2101 tria_object.user_flags.size()));
2102 Assert(tria_object.n_objects() ==
2103 tria_object.boundary_or_material_id.size(),
2104 ExcMemoryInexact(tria_object.n_objects(),
2105 tria_object.boundary_or_material_id.size()));
2106 Assert(tria_object.n_objects() == tria_object.manifold_id.size(),
2107 ExcMemoryInexact(tria_object.n_objects(),
2108 tria_object.manifold_id.size()));
2109 Assert(tria_object.n_objects() == tria_object.user_data.size(),
2110 ExcMemoryInexact(tria_object.n_objects(),
2111 tria_object.user_data.size()));
2112
2113 if (tria_object.structdim > 0)
2114 {
2115 const unsigned int factor = tria_object.children_per_object / 2;
2116 Assert(factor * tria_object.n_objects() ==
2117 tria_object.children.size(),
2118 ExcMemoryInexact(tria_object.n_objects(),
2119 tria_object.children.size()));
2120 }
2121 }
2122
2123
2124
2129 template <int dim, int spacedim>
2131 {
2132 public:
2136 virtual ~Policy() = default;
2137
2141 virtual void
2143
2147 virtual void
2149 Triangulation<dim, spacedim> &triangulation,
2151 std::vector<unsigned int> &line_cell_count,
2152 std::vector<unsigned int> &quad_cell_count) = 0;
2153
2159 const bool check_for_distorted_cells) = 0;
2160
2164 virtual void
2166 Triangulation<dim, spacedim> &triangulation) = 0;
2167
2171 virtual void
2173 Triangulation<dim, spacedim> &triangulation) = 0;
2174
2178 virtual bool
2180 const typename Triangulation<dim, spacedim>::cell_iterator &cell) = 0;
2181
2188 virtual std::unique_ptr<Policy<dim, spacedim>>
2189 clone() = 0;
2190 };
2191
2192
2193
2199 template <int dim, int spacedim, typename T>
2200 class PolicyWrapper : public Policy<dim, spacedim>
2201 {
2202 public:
2203 void
2205 {
2206 T::update_neighbors(tria);
2207 }
2208
2209 void
2213 std::vector<unsigned int> &line_cell_count,
2214 std::vector<unsigned int> &quad_cell_count) override
2215 {
2216 T::delete_children(tria, cell, line_cell_count, quad_cell_count);
2217 }
2218
2221 const bool check_for_distorted_cells) override
2222 {
2223 return T::execute_refinement(triangulation, check_for_distorted_cells);
2224 }
2225
2226 void
2228 Triangulation<dim, spacedim> &triangulation) override
2229 {
2230 T::prevent_distorted_boundary_cells(triangulation);
2231 }
2232
2233 void
2235 Triangulation<dim, spacedim> &triangulation) override
2236 {
2237 T::prepare_refinement_dim_dependent(triangulation);
2238 }
2239
2240 bool
2243 override
2244 {
2245 return T::template coarsening_allowed<dim, spacedim>(cell);
2246 }
2247
2248 std::unique_ptr<Policy<dim, spacedim>>
2249 clone() override
2250 {
2251 return std::make_unique<PolicyWrapper<dim, spacedim, T>>();
2252 }
2253 };
2254
2255
2261 {
2266 : offsets{0} {};
2267
2271 ArrayOfArrays(const ArrayOfArrays &) = default;
2272
2277
2281 ArrayOfArrays(const std::vector<std::size_t> &offsets,
2282 const std::vector<unsigned int> &columns)
2283 : offsets(offsets)
2284 , columns(columns)
2285 {}
2286
2291 ArrayOfArrays(std::vector<std::size_t> &&offsets,
2292 std::vector<unsigned int> &&columns)
2293 : offsets(std::move(offsets))
2294 , columns(std::move(columns))
2295 {}
2296
2301 operator=(const ArrayOfArrays &) = default;
2302
2308
2312 unsigned int
2313 size() const
2314 {
2315 return offsets.size() - 1;
2316 }
2317
2322 operator[](const unsigned int i) const
2323 {
2324 AssertIndexRange(i, offsets.size() - 1);
2326 offsets[i + 1] - offsets[i]);
2327 }
2328
2329 private:
2334 std::vector<std::size_t> offsets;
2335
2339 std::vector<unsigned int> columns;
2340 };
2341
2342
2343
2372 template <int dim>
2374 {
2376 const std::set<ReferenceCell<dim>> &all_reference_cells)
2379 {
2380 if constexpr (running_in_debug_mode())
2381 for (const auto &reference_cell : cell_types)
2382 Assert(all_reference_cells_.count(reference_cell) == 1u,
2384 }
2385
2386 const std::set<ReferenceCell<dim>> &
2388 {
2389 return all_reference_cells_;
2390 }
2391
2392 std::vector<types::geometric_orientation> &
2393 entity_orientations(const unsigned int structdim)
2394 {
2395 if (structdim == 1)
2396 return line_orientation;
2397
2398 AssertDimension(structdim, 2);
2399
2400 return quad_orientation;
2401 }
2402
2403 const std::vector<types::geometric_orientation> &
2404 entity_orientations(const unsigned int structdim) const
2405 {
2406 if (structdim == 1)
2407 return line_orientation;
2408
2409 AssertDimension(structdim, 2);
2410
2411 return quad_orientation;
2412 }
2413
2414 template <int structdim>
2415 std::vector<ReferenceCell<structdim>> &
2417 {
2418 if constexpr (structdim == dim)
2419 return cell_types;
2420 else if constexpr ((structdim == 2) && (dim == 3))
2421 {
2422 return quad_types;
2423 }
2424 else
2425 // for vertices/lines the entity types are clear
2426 // and we shouldn't need this function
2428 }
2429
2430 template <int structdim>
2431 const std::vector<ReferenceCell<structdim>> &
2433 {
2434 if constexpr (structdim == dim)
2435 return cell_types;
2436 else if constexpr ((structdim == 2) && (dim == 3))
2437 {
2438 return quad_types;
2439 }
2440 else
2441 // for vertices/lines the entity types are clear
2442 // and we shouldn't need this function
2444 }
2445
2447 entity_to_entities(const unsigned int from, const unsigned int to)
2448 {
2449 if (from == dim && to == dim)
2450 return neighbors;
2451 else if (from == dim && to == dim - 1)
2452 return cell_entities;
2453 else if (dim == 3 && from == 2 && to == 0)
2454 return quad_vertices;
2455 else if (dim == 3 && from == 2 && to == 1)
2456 return quad_lines;
2457 else if (from == 1 && to == 0)
2458 return line_vertices;
2459
2461
2462 return cell_entities;
2463 }
2464
2465 const ArrayOfArrays &
2466 entity_to_entities(const unsigned int from, const unsigned int to) const
2467 {
2468 if (from == dim && to == dim)
2469 return neighbors;
2470 else if (from == dim && to == dim - 1)
2471 return cell_entities;
2472 else if (dim == 3 && from == 2 && to == 0)
2473 return quad_vertices;
2474 else if (dim == 3 && from == 2 && to == 1)
2475 return quad_lines;
2476 else if (from == 1 && to == 0)
2477 return line_vertices;
2478
2480
2481 return cell_entities;
2482 }
2483
2484 private:
2485 std::vector<ReferenceCell<dim>> cell_types;
2486
2487 std::set<ReferenceCell<dim>> all_reference_cells_;
2488
2490
2491 std::vector<types::geometric_orientation> line_orientation;
2492
2495
2496 std::vector<types::geometric_orientation> quad_orientation;
2497
2500
2501 std::vector<ReferenceCell<2>> quad_types;
2502 };
2503
2504
2505
2514 determine_neighbors(const ArrayOfArrays &cells_to_faces)
2515 {
2516 // First determine the maximal face number used. The number of faces
2517 // is then one more (faces are counted starting at zero):
2518 unsigned int n_faces = 0;
2519 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2520 {
2521 const ArrayView<const unsigned int> face_indices =
2522 cells_to_faces[cell];
2523 n_faces = std::max(n_faces,
2524 *std::max_element(face_indices.begin(),
2525 face_indices.end()) +
2526 1);
2527 }
2528
2529 std::vector<std::size_t> cells_to_cells_offsets(cells_to_faces.size() + 1,
2530 0u);
2531 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2532 {
2533 const ArrayView<const unsigned int> face_indices =
2534 cells_to_faces[cell];
2535 cells_to_cells_offsets[cell + 1] =
2536 cells_to_cells_offsets[cell] + face_indices.size();
2537 }
2538 std::vector<unsigned int> cells_to_cells_columns(
2539 cells_to_cells_offsets.back(),
2540 /* default: cells is at the boundary in this direction */ -1);
2541
2542 std::vector<std::pair<unsigned int, unsigned int>> neighbors(
2543 n_faces,
2544 std::make_pair(numbers::invalid_unsigned_int,
2546
2547 // loop over all cells
2548 unsigned int global_face_index = 0;
2549 for (unsigned int cell = 0; cell < cells_to_faces.size(); ++cell)
2550 {
2551 // ... and all its faces
2552 const auto faces = cells_to_faces[cell];
2553 for (unsigned int f = 0; f < faces.size(); ++f, ++global_face_index)
2554 {
2555 if (neighbors[faces[f]].first == numbers::invalid_unsigned_int)
2556 {
2557 // face is visited the first time -> save the visiting cell
2558 // and the face pointer
2559 neighbors[faces[f]] = std::make_pair(cell, global_face_index);
2560 }
2561 else
2562 {
2563 // face is visited the second time -> now we know the cells
2564 // on both sides of the face and we can determine for both
2565 // cells the neighbor
2566 cells_to_cells_columns[global_face_index] =
2567 neighbors[faces[f]].first;
2568 cells_to_cells_columns[neighbors[faces[f]].second] = cell;
2569 }
2570 }
2571 }
2572
2573 return ArrayOfArrays(std::move(cells_to_cells_offsets),
2574 std::move(cells_to_cells_columns));
2575 }
2576
2577
2578
2587 template <int max_n_vertices, int face_dim, int dim, typename FU>
2588 void
2590 const std::vector<ReferenceCell<dim>> &cell_types,
2591 const ArrayOfArrays &cells_to_vertices,
2592 ArrayOfArrays &cells_to_faces, // result
2593 ArrayOfArrays &crs_0, // result
2594 std::vector<types::geometric_orientation> &orientations, // result
2595 const FU &second_key_function)
2596 {
2597 const bool compatibility_mode = true;
2598
2599 // note: we do not pre-allocate memory for these arrays because it turned
2600 // out that counting unique entities is more expensive than push_back().
2601 std::vector<std::size_t> offsets_0;
2602 std::vector<unsigned int> columns_0;
2603
2604 unsigned int n_entities = 0;
2605
2606 for (const auto &c : cell_types)
2607 {
2608 // Make sure that there are only two possibilities for
2609 // face_dim that we can cover with the ?: statement below:
2610 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2612 n_entities += (face_dim == dim - 1 ? c.n_faces() : c.n_lines());
2613 }
2614
2615 // step 1: store each d-dimensional entity of a cell (described by their
2616 // vertices) into a vector and create a key for them
2617 //
2618 // note: it turned out to be more efficient to have a vector of tuples
2619 // than to have two vectors (sorting becomes inefficient)
2620 std::vector<
2621 std::tuple<std::array<unsigned int, max_n_vertices>, unsigned int>>
2622 keys; // key (sorted vertices), cell-entity index
2623
2624 std::vector<std::array<unsigned int, max_n_vertices>> ad_entity_vertices;
2625 std::vector<ReferenceCell<face_dim>> ad_entity_types;
2626 std::vector<std::array<unsigned int, max_n_vertices>> ad_compatibility;
2627
2628 keys.reserve(n_entities);
2629 ad_entity_vertices.reserve(n_entities);
2630 ad_entity_types.reserve(n_entities);
2631 ad_compatibility.reserve(n_entities);
2632
2633 std::vector<std::size_t> cells_to_faces_offsets(cell_types.size() + 1);
2634 cells_to_faces_offsets[0] = 0;
2635
2636 constexpr unsigned int offset = 1;
2637
2638 // loop over all cells
2639 for (unsigned int c = 0, counter = 0; c < cell_types.size(); ++c)
2640 {
2641 const auto &cell_type = cell_types[c];
2642
2643 // Make sure that there are only two possibilities for
2644 // face_dimensionality that we can cover with the ?: statement below:
2645 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2647 const unsigned int n_face_entities =
2648 (face_dim == dim - 1 ? cell_type.n_faces() : cell_type.n_lines());
2649 cells_to_faces_offsets[c + 1] =
2650 cells_to_faces_offsets[c] + n_face_entities;
2651
2652 // ... loop over all its entities
2653 const ArrayView<const unsigned int> local_vertices =
2654 cells_to_vertices[c];
2655 for (unsigned int e = 0; e < n_face_entities; ++e)
2656 {
2657 // ... determine global entity vertices
2658 std::array<unsigned int, max_n_vertices> entity_vertices;
2659 std::fill(entity_vertices.begin(), entity_vertices.end(), 0);
2660
2661 // Same as above, make sure that there are only two possibilities
2662 // for face_dimensionality that we can cover with the ?: statement
2663 // below:
2664 Assert((face_dim == dim - 1) || ((dim == 3) && (face_dim == 1)),
2666 for (unsigned int i = 0;
2667 i < (face_dim == dim - 1 ?
2668 cell_type.face_reference_cell(e).n_vertices() :
2669 ReferenceCells::Line.n_vertices());
2670 ++i)
2671 entity_vertices[i] =
2672 local_vertices[face_dim == dim - 1 ?
2673 cell_type.face_to_cell_vertices(
2674 e,
2675 i,
2677 cell_type.line_to_cell_vertices(e, i)] +
2678 offset;
2679
2680 // ... create key
2681 std::array<unsigned int, max_n_vertices> key = entity_vertices;
2682 std::sort(key.begin(), key.end());
2683 keys.emplace_back(key, counter++);
2684
2685 ad_entity_vertices.emplace_back(entity_vertices);
2686
2687 if constexpr (face_dim == dim - 1)
2688 ad_entity_types.emplace_back(cell_type.face_reference_cell(e));
2689 else if constexpr (face_dim == dim - 2)
2690 {
2691 // Since we only deal with meshes up to dimension 3,
2692 // something that has co-dimensionality -2 must either be
2693 // a vertex or a line, regardless of what the object we are
2694 // working on actually us:
2695 if constexpr (face_dim == 0)
2696 ad_entity_types.emplace_back(ReferenceCells::Vertex);
2697 else if constexpr (face_dim == 1)
2698 ad_entity_types.emplace_back(ReferenceCells::Line);
2699 else
2700 // But it's probably useful to be conservative if someone
2701 // ever comes along to implement 4d meshes:
2703 }
2704 else
2706
2707 if (compatibility_mode)
2708 ad_compatibility.emplace_back(
2709 second_key_function(entity_vertices, cell_type, c, e));
2710 }
2711 }
2712
2713 std::vector<unsigned int> cells_to_faces_indices(keys.size());
2714 orientations.assign(keys.size(), numbers::default_geometric_orientation);
2715
2716 // step 2: sort according to key so that entities with same key can be
2717 // merged
2718 std::sort(keys.begin(), keys.end());
2719
2720 if (compatibility_mode)
2721 {
2722 unsigned int n_unique_entities = 0;
2723 unsigned int n_unique_entity_vertices = 0;
2724
2725 std::array<unsigned int, max_n_vertices> ref_key, new_key;
2726 std::fill(ref_key.begin(), ref_key.end(), 0);
2727 for (unsigned int i = 0; i < keys.size(); ++i)
2728 {
2729 const auto offset_i = std::get<1>(keys[i]);
2730
2731 if (ref_key != std::get<0>(keys[i]))
2732 {
2733 ref_key = std::get<0>(keys[i]);
2734
2735 ++n_unique_entities;
2736 n_unique_entity_vertices +=
2737 ad_entity_types[offset_i].n_vertices();
2738
2739 new_key = ad_compatibility[offset_i];
2740 }
2741
2742 std::get<0>(keys[i]) = new_key;
2743 }
2744
2745 std::sort(keys.begin(), keys.end());
2746
2747 offsets_0.reserve(n_unique_entities + 1);
2748 columns_0.reserve(n_unique_entity_vertices);
2749 }
2750
2751
2752 std::array<unsigned int, max_n_vertices> ref_key;
2753 std::array<unsigned int, max_n_vertices> ref_indices;
2754 std::fill(ref_key.begin(), ref_key.end(), 0);
2755
2756 unsigned int counter = ::numbers::invalid_unsigned_int;
2757 for (unsigned int i = 0; i < keys.size(); i++)
2758 {
2759 const auto offset_i = std::get<1>(keys[i]);
2760
2761 if (ref_key != std::get<0>(keys[i]))
2762 {
2763 // new key: default orientation is correct
2764 ++counter;
2765 ref_key = std::get<0>(keys[i]);
2766 ref_indices = ad_entity_vertices[offset_i];
2767
2768 offsets_0.push_back(columns_0.size());
2769 for (const auto j : ad_entity_vertices[offset_i])
2770 if (j != 0)
2771 columns_0.push_back(j - offset);
2772 }
2773 else
2774 {
2775 // previously seen key: set orientation relative to the first
2776 // occurrence
2777 orientations[offset_i] =
2778 ad_entity_types[offset_i]
2779 .template get_combined_orientation<unsigned int>(
2780 make_array_view(ad_entity_vertices[offset_i].begin(),
2781 ad_entity_vertices[offset_i].begin() +
2782 ad_entity_types[offset_i].n_vertices()),
2783 make_array_view(ref_indices.begin(),
2784 ref_indices.begin() +
2785 ad_entity_types[offset_i].n_vertices()));
2786 }
2787 cells_to_faces_indices[offset_i] = counter;
2788 }
2789 offsets_0.push_back(columns_0.size());
2790
2791 // Finally build the output objects:
2792 crs_0 = ArrayOfArrays(std::move(offsets_0), std::move(columns_0));
2793 cells_to_faces = ArrayOfArrays(std::move(cells_to_faces_offsets),
2794 std::move(cells_to_faces_indices));
2795 }
2796
2797
2798
2803 template <int face_dim, int dim, typename FU>
2804 void
2805 build_face_entities(const std::vector<ReferenceCell<dim>> &cell_types,
2806 const ArrayOfArrays &cells_to_vertices,
2807 ArrayOfArrays &cells_to_faces,
2808 ArrayOfArrays &crs_0,
2809 std::vector<types::geometric_orientation> &orientations,
2810 const FU &second_key_function)
2811 {
2812 unsigned int max_n_vertices = 0;
2813
2814 // If we are dealing with faces of cells, figure out how many vertices
2815 // each face may have. Otherwise, we're in 3d and are dealing with
2816 // lines, for which we know the number of vertices:
2817 for (const auto &c : cell_types)
2818 if (face_dim == dim - 1)
2819 {
2820 for (unsigned int f = 0; f < c.n_faces(); ++f)
2821 max_n_vertices =
2822 std::max(max_n_vertices, c.face_reference_cell(f).n_vertices());
2823 }
2824 else if (face_dim == 1)
2825 max_n_vertices = std::max(max_n_vertices, 2u);
2826 else
2828
2829 if (max_n_vertices == 2)
2831 cells_to_vertices,
2832 cells_to_faces,
2833 crs_0,
2834 orientations,
2835 second_key_function);
2836 else if (max_n_vertices == 3)
2838 cells_to_vertices,
2839 cells_to_faces,
2840 crs_0,
2841 orientations,
2842 second_key_function);
2843 else if (max_n_vertices == 4)
2845 cells_to_vertices,
2846 cells_to_faces,
2847 crs_0,
2848 orientations,
2849 second_key_function);
2850 else
2852 }
2853
2854
2855
2863 template <int dim>
2864 void
2866 const std::vector<ReferenceCell<dim>> &cell_types,
2867 const ArrayOfArrays &cells_to_vertices,
2868 const ArrayOfArrays &cells_to_lines,
2869 const ArrayOfArrays &lines_to_vertices,
2870 const ArrayOfArrays &cells_to_quads,
2871 const ArrayOfArrays &quads_to_vertices,
2872 const std::vector<types::geometric_orientation> &ori_cq,
2873 ArrayOfArrays &quads_to_lines, // result
2874 std::vector<types::geometric_orientation> &ori_ql, // result
2875 std::vector<ReferenceCell<2>> &quad_t_id // result
2876 )
2877 {
2878 quad_t_id.resize(quads_to_vertices.size());
2879
2880 // Build the offsets of the compressed representation of the
2881 // quads-to-lines array by counting the number of lines of each face.
2882 // We do this by looping over all cells and querying their faces.
2883 // This encounters faces in a random order, so we first
2884 // store the number of lines of the f'th face in the (f+1)st
2885 // offset and then run a prefix sum to sum up all
2886 // previous offsets
2887 std::vector<std::size_t> quads_to_lines_offsets(quads_to_vertices.size() +
2888 1);
2889 for (unsigned int c = 0; c < cells_to_quads.size(); ++c)
2890 {
2891 // loop over faces
2892 const ArrayView<const unsigned int> faces = cells_to_quads[c];
2893 for (unsigned int f = 0; f < faces.size(); ++f)
2894 {
2895 quads_to_lines_offsets[faces[f] + 1] =
2896 cell_types[c].face_reference_cell(f).n_lines();
2897 }
2898 }
2899 quads_to_lines_offsets[0] = 0;
2900 for (unsigned int i = 0; i < quads_to_lines_offsets.size() - 1; ++i)
2901 quads_to_lines_offsets[i + 1] += quads_to_lines_offsets[i];
2902
2903 // Now that we have the offsets, allocate memory for the indices:
2904 std::vector<unsigned int> quads_to_lines_indices(
2905 quads_to_lines_offsets.back());
2906 ori_ql.assign(quads_to_lines_offsets.back(),
2908
2909 // loop over cells
2910 unsigned int global_face_index = 0;
2911 for (unsigned int c = 0; c < cells_to_quads.size(); ++c)
2912 {
2913 const ReferenceCell<dim> cell_type = cell_types[c];
2914
2915 // loop over faces
2916 const ArrayView<const unsigned int> faces = cells_to_quads[c];
2917 for (unsigned int f_index = 0; f_index < faces.size();
2918 ++f_index, ++global_face_index)
2919 {
2920 const unsigned int f = faces[f_index];
2921
2922 // only faces with default orientation have to do something
2923 if (ori_cq[global_face_index] !=
2925 continue;
2926
2927 // loop over the lines of this face
2928 quad_t_id[f] = cell_type.face_reference_cell(f_index);
2929 for (unsigned int l = 0; l < quad_t_id[f].n_lines(); ++l)
2930 {
2931 // determine global index of line
2932 const unsigned int local_line_index =
2933 cell_type.face_to_cell_lines(
2935 const unsigned int global_line_index =
2936 cells_to_lines[c][local_line_index];
2937 quads_to_lines_indices[quads_to_lines_offsets[f] + l] =
2938 global_line_index;
2939
2940 // determine orientation of line
2941 bool same = true;
2942 for (unsigned int v = 0; v < 2; ++v)
2943 if (cells_to_vertices
2944 [c][cell_type.face_and_line_to_cell_vertices(
2945 f_index,
2946 l,
2947 v,
2949 lines_to_vertices[global_line_index][v])
2950 {
2951 same = false;
2952 break;
2953 }
2954
2955 // ... comparison gives orientation
2956 ori_ql[quads_to_lines_offsets[f] + l] =
2959 }
2960 }
2961 }
2962
2963 // Finally build the output object:
2964 quads_to_lines = ArrayOfArrays(std::move(quads_to_lines_offsets),
2965 std::move(quads_to_lines_indices));
2966 }
2967
2968
2969
2978 template <int dim>
2979 Connectivity<dim>
2980 build_connectivity(const std::vector<ReferenceCell<dim>> &cell_types,
2981 const std::set<ReferenceCell<dim>> &all_reference_cells,
2982 const ArrayOfArrays &cells_to_vertices)
2983 {
2984 Connectivity<dim> connectivity(cell_types, all_reference_cells);
2985
2986 ArrayOfArrays temp1; // needed for 3d
2987
2988 if constexpr (dim == 1)
2989 connectivity.entity_to_entities(1, 0) = cells_to_vertices;
2990
2991 if constexpr (dim == 2 || dim == 3) // build lines
2992 {
2993 std::vector<types::geometric_orientation> dummy;
2994
2996 connectivity.template entity_types<dim>(),
2997 cells_to_vertices,
2998 dim == 2 ? connectivity.entity_to_entities(2, 1) : temp1,
2999 connectivity.entity_to_entities(1, 0),
3000 dim == 2 ? connectivity.entity_orientations(1) : dummy,
3001 [](auto key, const auto &, const auto &, const auto &) {
3002 // to ensure same enumeration as in deal.II
3003 return key;
3004 });
3005 }
3006
3007 if constexpr (dim == 3) // build quads
3008 {
3010 connectivity.template entity_types<3>(),
3011 cells_to_vertices,
3012 connectivity.entity_to_entities(3, 2),
3013 connectivity.entity_to_entities(2, 0),
3014 connectivity.entity_orientations(2),
3015 [&](auto key, // of type std::array<unsigned int, max_n_vertices>
3016 // but max_n_vertices is not known here
3017 const ReferenceCell<dim> &cell_type,
3018 const unsigned int &c,
3019 const unsigned int &f) {
3020 // to ensure same enumeration as in deal.II
3021 AssertIndexRange(cell_type.face_reference_cell(f).n_lines(),
3022 key.size() + 1);
3023
3024 unsigned int l = 0;
3025
3026 for (; l < cell_type.face_reference_cell(f).n_lines(); ++l)
3027 {
3028 AssertIndexRange(l, key.size());
3029 key[l] = temp1[c][cell_type.face_to_cell_lines(
3030 f, l, numbers::default_geometric_orientation)] +
3031 1 /*offset!*/;
3032 }
3033
3034 for (; l < key.size(); ++l)
3035 key[l] = 0;
3036
3037 return key;
3038 });
3039
3040 // create connectivity: quad -> line
3041 build_intersection(connectivity.template entity_types<3>(),
3042 cells_to_vertices,
3043 temp1,
3044 connectivity.entity_to_entities(1, 0),
3045 connectivity.entity_to_entities(3, 2),
3046 connectivity.entity_to_entities(2, 0),
3047 connectivity.entity_orientations(2),
3048 connectivity.entity_to_entities(2, 1),
3049 connectivity.entity_orientations(1),
3050 connectivity.template entity_types<2>());
3051 }
3052
3053 // determine neighbors
3054 connectivity.entity_to_entities(dim, dim) =
3055 determine_neighbors(connectivity.entity_to_entities(dim, dim - 1));
3056
3057 return connectivity;
3058 }
3059
3060
3061
3065 template <int dim>
3066 Connectivity<dim>
3067 build_connectivity(const std::vector<CellData<dim>> &cells)
3068 {
3069 AssertThrow(cells.size() > 0, ExcMessage("No cells have been provided!"));
3070
3071 // determine cell types and process vertices
3072 std::vector<unsigned int> cell_vertices;
3073 cell_vertices.reserve(std::accumulate(cells.begin(),
3074 cells.end(),
3075 0u,
3076 [](const unsigned int accumulator,
3077 const CellData<dim> &cell) {
3078 return accumulator +
3079 cell.vertices.size();
3080 }));
3081
3082 std::vector<std::size_t> cell_vertices_offsets;
3083 cell_vertices_offsets.reserve(cells.size() + 1);
3084 cell_vertices_offsets.push_back(0);
3085
3086 std::vector<ReferenceCell<dim>> cell_types;
3087 cell_types.reserve(cells.size());
3088
3089 // Looping over all the cells can be expensive, so we mark the kinds of
3090 // ReferenceCells we have just once
3091 std::set<ReferenceCell<dim>> all_reference_cells;
3092 // loop over cells and create CRS
3093 for (const auto &cell : cells)
3094 {
3095 if constexpr (running_in_debug_mode())
3096 {
3097 auto vertices_unique = cell.vertices;
3098 std::sort(vertices_unique.begin(), vertices_unique.end());
3099 vertices_unique.erase(std::unique(vertices_unique.begin(),
3100 vertices_unique.end()),
3101 vertices_unique.end());
3102
3103 Assert(
3104 vertices_unique.size() == cell.vertices.size(),
3105 ExcMessage(
3106 "The definition of a cell refers to the same vertex several "
3107 "times. This is not possible. A common reason is that "
3108 "CellData::vertices has a size that does not match the "
3109 "size expected from the reference cell. Please resize "
3110 "CellData::vertices or use the appropriate constructor of "
3111 "CellData."));
3112 }
3113
3114 cell_types.push_back(
3116 cell.vertices.size()));
3117 all_reference_cells.insert(cell_types.back());
3118
3119 // create CRS of vertices (to remove template argument dim)
3120 cell_vertices.insert(cell_vertices.end(),
3121 cell.vertices.begin(),
3122 cell.vertices.end());
3123 cell_vertices_offsets.push_back(cell_vertices.size());
3124 }
3125
3126 // do the actual work
3127 return build_connectivity(cell_types,
3128 all_reference_cells,
3129 {std::move(cell_vertices_offsets),
3130 std::move(cell_vertices)});
3131 }
3132
3133
3230 {
3242 template <int dim, int spacedim>
3243 static void
3245 const Triangulation<dim, spacedim> &triangulation,
3246 const unsigned int level_objects,
3248 {
3249 using line_iterator =
3251
3252 number_cache.n_levels = 0;
3253 if (level_objects > 0)
3254 // find the last level on which there are used cells
3255 for (unsigned int level = 0; level < level_objects; ++level)
3256 if (triangulation.begin(level) != triangulation.end(level))
3257 number_cache.n_levels = level + 1;
3258
3259 // no cells at all?
3260 Assert(number_cache.n_levels > 0, ExcInternalError());
3261
3262 //---------------------------------
3263 // update the number of lines on the different levels in the
3264 // cache
3265 number_cache.n_lines = 0;
3266 number_cache.n_active_lines = 0;
3267
3268 // for 1d, lines have levels so take count the objects per
3269 // level and globally
3270 if (dim == 1)
3271 {
3272 number_cache.n_lines_level.resize(number_cache.n_levels);
3273 number_cache.n_active_lines_level.resize(number_cache.n_levels);
3274
3275 for (unsigned int level = 0; level < number_cache.n_levels; ++level)
3276 {
3277 // count lines on this level
3278 number_cache.n_lines_level[level] = 0;
3279 number_cache.n_active_lines_level[level] = 0;
3280
3281 line_iterator line = triangulation.begin_line(level),
3282 endc =
3283 (level == number_cache.n_levels - 1 ?
3284 line_iterator(triangulation.end_line()) :
3285 triangulation.begin_line(level + 1));
3286 for (; line != endc; ++line)
3287 {
3288 ++number_cache.n_lines_level[level];
3289 if (line->has_children() == false)
3290 ++number_cache.n_active_lines_level[level];
3291 }
3292
3293 // update total number of lines
3294 number_cache.n_lines += number_cache.n_lines_level[level];
3295 number_cache.n_active_lines +=
3296 number_cache.n_active_lines_level[level];
3297 }
3298 }
3299 else
3300 {
3301 // for dim>1, there are no levels for lines
3302 number_cache.n_lines_level.clear();
3303 number_cache.n_active_lines_level.clear();
3304
3305 line_iterator line = triangulation.begin_line(),
3306 endc = triangulation.end_line();
3307 for (; line != endc; ++line)
3308 {
3309 ++number_cache.n_lines;
3310 if (line->has_children() == false)
3311 ++number_cache.n_active_lines;
3312 }
3313 }
3314 }
3315
3330 template <int dim, int spacedim>
3331 static void
3333 const Triangulation<dim, spacedim> &triangulation,
3334 const unsigned int level_objects,
3336 {
3337 // update lines and n_levels in number_cache. since we don't
3338 // access any of these numbers, we can do this in the
3339 // background
3341 static_cast<
3342 void (*)(const Triangulation<dim, spacedim> &,
3343 const unsigned int,
3346 triangulation,
3347 level_objects,
3349 number_cache));
3350
3351 using quad_iterator =
3353
3354 //---------------------------------
3355 // update the number of quads on the different levels in the
3356 // cache
3357 number_cache.n_quads = 0;
3358 number_cache.n_active_quads = 0;
3359
3360 // for 2d, quads have levels so take count the objects per
3361 // level and globally
3362 if (dim == 2)
3363 {
3364 // count the number of levels; the function we called above
3365 // on a separate Task for lines also does this and puts it into
3366 // number_cache.n_levels, but this datum may not yet be
3367 // available as we call the function on a separate task
3368 unsigned int n_levels = 0;
3369 if (level_objects > 0)
3370 // find the last level on which there are used cells
3371 for (unsigned int level = 0; level < level_objects; ++level)
3372 if (triangulation.begin(level) != triangulation.end(level))
3373 n_levels = level + 1;
3374
3375 number_cache.n_quads_level.resize(n_levels);
3376 number_cache.n_active_quads_level.resize(n_levels);
3377
3378 for (unsigned int level = 0; level < n_levels; ++level)
3379 {
3380 // count quads on this level
3381 number_cache.n_quads_level[level] = 0;
3382 number_cache.n_active_quads_level[level] = 0;
3383
3384 quad_iterator quad = triangulation.begin_quad(level),
3385 endc =
3386 (level == n_levels - 1 ?
3387 quad_iterator(triangulation.end_quad()) :
3388 triangulation.begin_quad(level + 1));
3389 for (; quad != endc; ++quad)
3390 {
3391 ++number_cache.n_quads_level[level];
3392 if (quad->has_children() == false)
3393 ++number_cache.n_active_quads_level[level];
3394 }
3395
3396 // update total number of quads
3397 number_cache.n_quads += number_cache.n_quads_level[level];
3398 number_cache.n_active_quads +=
3399 number_cache.n_active_quads_level[level];
3400 }
3401 }
3402 else
3403 {
3404 // for dim>2, there are no levels for quads
3405 number_cache.n_quads_level.clear();
3406 number_cache.n_active_quads_level.clear();
3407
3408 quad_iterator quad = triangulation.begin_quad(),
3409 endc = triangulation.end_quad();
3410 for (; quad != endc; ++quad)
3411 {
3412 ++number_cache.n_quads;
3413 if (quad->has_children() == false)
3414 ++number_cache.n_active_quads;
3415 }
3416 }
3417
3418 // wait for the background computation for lines
3419 update_lines.join();
3420 }
3421
3437 template <int dim, int spacedim>
3438 static void
3440 const Triangulation<dim, spacedim> &triangulation,
3441 const unsigned int level_objects,
3443 {
3444 // update quads, lines and n_levels in number_cache. since we
3445 // don't access any of these numbers, we can do this in the
3446 // background
3447 Threads::Task<void> update_quads_and_lines = Threads::new_task(
3448 static_cast<
3449 void (*)(const Triangulation<dim, spacedim> &,
3450 const unsigned int,
3453 triangulation,
3454 level_objects,
3456 number_cache));
3457
3458 using hex_iterator =
3460
3461 //---------------------------------
3462 // update the number of hexes on the different levels in the
3463 // cache
3464 number_cache.n_hexes = 0;
3465 number_cache.n_active_hexes = 0;
3466
3467 // for 3d, hexes have levels so take count the objects per
3468 // level and globally
3469 if (dim == 3)
3470 {
3471 // count the number of levels; the function we called
3472 // above on a separate Task for quads (recursively, via
3473 // the lines function) also does this and puts it into
3474 // number_cache.n_levels, but this datum may not yet be
3475 // available as we call the function on a separate task
3476 unsigned int n_levels = 0;
3477 if (level_objects > 0)
3478 // find the last level on which there are used cells
3479 for (unsigned int level = 0; level < level_objects; ++level)
3480 if (triangulation.begin(level) != triangulation.end(level))
3481 n_levels = level + 1;
3482
3483 number_cache.n_hexes_level.resize(n_levels);
3484 number_cache.n_active_hexes_level.resize(n_levels);
3485
3486 for (unsigned int level = 0; level < n_levels; ++level)
3487 {
3488 // count hexes on this level
3489 number_cache.n_hexes_level[level] = 0;
3490 number_cache.n_active_hexes_level[level] = 0;
3491
3492 hex_iterator hex = triangulation.begin_hex(level),
3493 endc = (level == n_levels - 1 ?
3494 hex_iterator(triangulation.end_hex()) :
3495 triangulation.begin_hex(level + 1));
3496 for (; hex != endc; ++hex)
3497 {
3498 ++number_cache.n_hexes_level[level];
3499 if (hex->has_children() == false)
3500 ++number_cache.n_active_hexes_level[level];
3501 }
3502
3503 // update total number of hexes
3504 number_cache.n_hexes += number_cache.n_hexes_level[level];
3505 number_cache.n_active_hexes +=
3506 number_cache.n_active_hexes_level[level];
3507 }
3508 }
3509 else
3510 {
3511 // for dim>3, there are no levels for hexes
3512 number_cache.n_hexes_level.clear();
3513 number_cache.n_active_hexes_level.clear();
3514
3515 hex_iterator hex = triangulation.begin_hex(),
3516 endc = triangulation.end_hex();
3517 for (; hex != endc; ++hex)
3518 {
3519 ++number_cache.n_hexes;
3520 if (hex->has_children() == false)
3521 ++number_cache.n_active_hexes;
3522 }
3523 }
3524
3525 // wait for the background computation for quads
3526 update_quads_and_lines.join();
3527 }
3528
3529
3530 template <int dim, int spacedim>
3531 static void
3533 const Triangulation<dim, spacedim> &triangulation,
3534 const unsigned int level_objects,
3536 {
3537 compute_number_cache_dim(triangulation, level_objects, number_cache);
3538
3539 number_cache.active_cell_index_partitioner =
3540 std::make_shared<const Utilities::MPI::Partitioner>(
3541 triangulation.n_active_cells());
3542
3543 number_cache.level_cell_index_partitioners.resize(
3544 triangulation.n_levels());
3545 for (unsigned int level = 0; level < triangulation.n_levels(); ++level)
3546 number_cache.level_cell_index_partitioners[level] =
3547 std::make_shared<const Utilities::MPI::Partitioner>(
3548 triangulation.n_cells(level));
3549 }
3550
3551
3552 template <int spacedim>
3553 static void
3556
3557
3558 template <int dim, int spacedim>
3559 static void
3561 {
3562 // each face can be neighbored on two sides by cells. according to the
3563 // face's intrinsic normal we define the left neighbor as the one for
3564 // which the face normal points outward, and store that one first; the
3565 // second one is then the right neighbor for which the face normal
3566 // points inward. This information depends on the type of cell and
3567 // local number of face for the 'standard ordering and orientation' of
3568 // faces and then on the face_orientation information for the real
3569 // mesh. Set up a table to have fast access to those offsets (0 for
3570 // left and 1 for right). Some of the values are invalid as they
3571 // reference too large face numbers, but we just leave them at a zero
3572 // value.
3573 //
3574 // Note, that in 2d for lines as faces the normal direction given in
3575 // the GeometryInfo class is not consistent. We thus define here that
3576 // the normal for a line points to the right if the line points
3577 // upwards.
3578 //
3579 // There is one more point to consider, however: if we have
3580 // dim<spacedim, then we may have cases where cells are inverted. In
3581 // effect, both cells think they are the left neighbor of an edge, for
3582 // example, which leads us to forget neighborship information (a case
3583 // that shows this is codim_one/hanging_nodes_02). We store whether a
3584 // cell is inverted using the direction_flag, so if a cell has a false
3585 // direction_flag, then we need to invert our selection whether we are
3586 // a left or right neighbor in all following computations.
3587 //
3588 // first index: dimension (minus 2)
3589 // second index: local face index
3590 // third index: face_orientation (false and true)
3591 constexpr unsigned int left_right_offset[2][6][2] = {
3592 // quadrilateral
3593 {{0, 1}, // face 0, face_orientation = false and true
3594 {1, 0}, // face 1, face_orientation = false and true
3595 {1, 0}, // face 2, face_orientation = false and true
3596 {0, 1}, // face 3, face_orientation = false and true
3597 {0, 0}, // face 4, invalid face
3598 {0, 0}}, // face 5, invalid face
3599 // hexahedron
3600 {{0, 1}, {1, 0}, {0, 1}, {1, 0}, {0, 1}, {1, 0}}};
3601
3602 // now create a vector of the two active neighbors (left and right)
3603 // for each face and fill it by looping over all cells. For cases with
3604 // anisotropic refinement and more than one cell neighboring at a
3605 // given side of the face we will automatically get the active one on
3606 // the highest level as we loop over cells from lower levels first.
3608 std::vector<typename Triangulation<dim, spacedim>::cell_iterator>
3609 adjacent_cells(2 * triangulation.n_raw_faces(), dummy);
3610
3611 for (const auto &cell : triangulation.cell_iterators())
3612 for (auto f : cell->face_indices())
3613 {
3615 cell->face(f);
3616
3617 const unsigned int offset =
3618 (cell->direction_flag() ?
3619 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3620 1 -
3621 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3622
3623 adjacent_cells[2 * face->index() + offset] = cell;
3624
3625 // if this cell is not refined, but the face is, then we'll have
3626 // to set our cell as neighbor for the child faces as
3627 // well. Fortunately the normal orientation of children will be
3628 // just the same.
3629 if (dim == 2)
3630 {
3631 if (cell->is_active() && face->has_children())
3632 {
3633 adjacent_cells[2 * face->child(0)->index() + offset] =
3634 cell;
3635 adjacent_cells[2 * face->child(1)->index() + offset] =
3636 cell;
3637 }
3638 }
3639 else // -> dim == 3
3640 {
3641 // We need the same as in 2d here. Furthermore, if the face
3642 // is refined with cut_x or cut_y then those children again
3643 // in the other direction, and if this cell is refined
3644 // isotropically (along the face) then the neighbor will
3645 // (probably) be refined as cut_x or cut_y along the
3646 // face. For those neighboring children cells, their
3647 // neighbor will be the current, inactive cell, as our
3648 // children are too fine to be neighbors. Catch that case by
3649 // also acting on inactive cells with isotropic refinement
3650 // along the face. If the situation described is not
3651 // present, the data will be overwritten later on when we
3652 // visit cells on finer levels, so no harm will be done.
3653 if (face->has_children() &&
3654 (cell->is_active() ||
3656 cell->refinement_case(), f) ==
3658 {
3659 for (unsigned int c = 0; c < face->n_children(); ++c)
3660 adjacent_cells[2 * face->child(c)->index() + offset] =
3661 cell;
3662 if (face->child(0)->has_children())
3663 {
3664 adjacent_cells[2 * face->child(0)->child(0)->index() +
3665 offset] = cell;
3666 adjacent_cells[2 * face->child(0)->child(1)->index() +
3667 offset] = cell;
3668 }
3669 if (face->child(1)->has_children())
3670 {
3671 adjacent_cells[2 * face->child(1)->child(0)->index() +
3672 offset] = cell;
3673 adjacent_cells[2 * face->child(1)->child(1)->index() +
3674 offset] = cell;
3675 }
3676 } // if cell active and face refined
3677 } // else -> dim==3
3678 } // for all faces of all cells
3679
3680 // now loop again over all cells and set the corresponding neighbor
3681 // cell. Note, that we have to use the opposite of the
3682 // left_right_offset in this case as we want the offset of the
3683 // neighbor, not our own.
3684 for (const auto &cell : triangulation.cell_iterators())
3685 for (auto f : cell->face_indices())
3686 {
3687 const unsigned int offset =
3688 (cell->direction_flag() ?
3689 left_right_offset[dim - 2][f][cell->face_orientation(f)] :
3690 1 -
3691 left_right_offset[dim - 2][f][cell->face_orientation(f)]);
3692 cell->set_neighbor(
3693 f, adjacent_cells[2 * cell->face(f)->index() + 1 - offset]);
3694 }
3695 }
3696
3697
3701 template <int dim, int spacedim>
3702 static void
3703 create_triangulation(const std::vector<Point<spacedim>> &vertices,
3704 const std::vector<CellData<dim>> &cells,
3705 const SubCellData &subcelldata,
3707 {
3708 AssertThrow(vertices.size() > 0, ExcMessage("No vertices given"));
3709 AssertThrow(cells.size() > 0, ExcMessage("No cells given"));
3710
3711 // Check that all cells have positive volume.
3712#ifndef _MSC_VER
3713 // TODO: The following code does not compile with MSVC. Find a way
3714 // around it
3715 if (dim == spacedim)
3716 for (unsigned int cell_no = 0; cell_no < cells.size(); ++cell_no)
3717 {
3718 // If we should check for distorted cells, then we permit them
3719 // to exist. If a cell has negative measure, then it must be
3720 // distorted (the converse is not necessarily true); hence
3721 // throw an exception if no such cells should exist.
3723 {
3724 const double cell_measure = GridTools::cell_measure<spacedim>(
3725 vertices,
3726 ArrayView<const unsigned int>(cells[cell_no].vertices));
3727 AssertThrow(cell_measure > 0, ExcGridHasInvalidCell(cell_no));
3728 }
3729 }
3730#endif
3731
3732 // copy vertices
3733 tria.vertices = vertices;
3734 tria.vertices_used.assign(vertices.size(), true);
3735
3736 // compute connectivity
3737 const auto connectivity = build_connectivity(cells);
3738 const auto n_cells = cells.size();
3739
3740 // set up reference cells for the first time
3741 const auto all_reference_cells =
3742 Utilities::MPI::compute_set_union(connectivity.all_reference_cells(),
3743 tria.get_mpi_communicator());
3744 tria.reference_cells.assign(all_reference_cells.begin(),
3745 all_reference_cells.end());
3747 tria.reference_cells);
3748
3749 // clear old content
3750 tria.levels.clear();
3751 tria.levels.push_back(
3752 std::make_unique<
3754 tria.strides.max_children_per_cell,
3755 tria.strides.max_faces_per_cell,
3756 tria.strides.max_vertices_per_cell));
3757
3758 if (dim > 1)
3759 tria.faces = std::make_unique<
3761 tria.strides.max_children_per_face,
3762 tria.strides.max_lines_per_face);
3763
3764 const ArrayOfArrays empty;
3765 const ArrayOfArrays &lines_to_vertices =
3766 dim > 1 ? connectivity.entity_to_entities(1, 0) : empty;
3767 const ArrayOfArrays &quads_to_lines =
3768 dim == 3 ? connectivity.entity_to_entities(2, 1) : empty;
3769 const auto n_lines = lines_to_vertices.size();
3771 n_lines <= std::size_t(std::numeric_limits<int>::max()),
3772 ExcMessage("The number of lines must be less than the largest int."));
3773 const auto n_quads = quads_to_lines.size();
3775 n_quads <= std::size_t(std::numeric_limits<int>::max()),
3776 ExcMessage("The number of quads must be less than the largest int."));
3777
3778 if (dim > 1)
3779 tria.faces->allocate(n_lines, n_quads);
3780
3781 // TriaObjects: lines
3782 if (dim > 1)
3783 {
3784 auto &faces = *tria.faces;
3785 // loop over lines
3786 for (int line = 0; line < int(n_lines); ++line)
3787 {
3788 const auto vertices = lines_to_vertices[line];
3789 for (unsigned int v = 0; v < vertices.size(); ++v)
3790 faces.lines.set_bounding_object(line, v, vertices[v]);
3791 }
3792 }
3793
3794 // TriaObjects: quads
3795 if constexpr (dim == 3)
3796 {
3797 auto &faces = *tria.faces;
3798 // get connectivity between quads and lines
3799
3800 // loop over all quads -> entity type, line indices/orientations
3801 for (int q = 0, k = 0; q < int(n_quads); ++q)
3802 {
3803 // set entity type of quads
3804 const auto face_reference_cell =
3805 connectivity.template entity_types<2>()[q];
3806 faces.set_quad_type(q, face_reference_cell);
3807
3808 // loop over all its lines
3809 const auto lines = quads_to_lines[q];
3810 for (unsigned int l = 0; l < lines.size(); ++l, ++k)
3811 {
3812 AssertIndexRange(l, face_reference_cell.n_lines());
3813 // set line index
3814 faces.quads.set_bounding_object(q, l, lines[l]);
3815
3816 // set line orientations
3817 faces.set_line_orientation(
3818 q, l, connectivity.entity_orientations(1)[k]);
3819 }
3820 }
3821 }
3822
3823 // TriaObjects/TriaLevel: cell
3824 {
3825 auto &cells_0 = tria.levels[0]->cells; // data structure to be filled
3826 auto &level = *tria.levels[0];
3827
3828 // get connectivity between cells/faces and cells/cells
3829 const auto &cells_to_faces =
3830 connectivity.entity_to_entities(dim, dim - 1);
3831 const auto &cells_to_neighbor_cells =
3832 connectivity.entity_to_entities(dim, dim);
3833
3834 // in 2d optional: since in in pure QUAD meshes same line
3835 // orientations can be guaranteed
3836 bool orientation_needed = false;
3837 if (dim == 3)
3838 orientation_needed = true;
3839 else if (dim == 2)
3840 {
3841 const auto &orientations = connectivity.entity_orientations(1);
3842 orientation_needed = std::any_of(
3843 orientations.begin(), orientations.end(), [](const auto &a) {
3844 return a != numbers::default_geometric_orientation;
3845 });
3846 }
3847
3848 level.allocate(n_cells, orientation_needed);
3849 // loop over all cells
3850 unsigned int global_face_index = 0;
3851 for (unsigned int cell = 0; cell < n_cells; ++cell)
3852 {
3853 // set material ids
3854 cells_0.boundary_or_material_id[cell].material_id =
3855 cells[cell].material_id;
3856
3857 // set manifold ids
3858 cells_0.manifold_id[cell] = cells[cell].manifold_id;
3859
3860 // set entity types
3861 level.reference_cell[cell] =
3862 connectivity.template entity_types<dim>()[cell];
3863 Assert(all_reference_cells.count(level.reference_cell[cell]) ==
3864 1u,
3866
3867 // loop over faces
3868 const auto faces = cells_to_faces[cell];
3869 const auto neighbors = cells_to_neighbor_cells[cell];
3870 for (unsigned int f = 0; f < faces.size();
3871 ++f, ++global_face_index)
3872 {
3873 // set neighbor if not at boundary
3874 if (neighbors[f] != numbers::invalid_unsigned_int)
3875 level.set_neighbor(cell, f, 0, neighbors[f]);
3876
3877 // set face indices
3878 cells_0.set_bounding_object(cell, f, faces[f]);
3879
3880 // set face orientation if needed
3881 if (orientation_needed)
3882 {
3883 level.face_orientations.set_combined_orientation(
3884 cell,
3885 f,
3886 connectivity.entity_orientations(dim -
3887 1)[global_face_index]);
3888 }
3889 }
3890 }
3891 }
3892
3893 // TriaFaces: boundary id of boundary faces
3894 if (dim > 1)
3895 {
3896 auto &bids_face = dim == 3 ?
3897 tria.faces->quads.boundary_or_material_id :
3898 tria.faces->lines.boundary_or_material_id;
3899
3900 // count number of cells a face is belonging to
3901 std::vector<unsigned int> count(bids_face.size(), 0);
3902
3903 // get connectivity between cells/faces
3904 const auto &cells_to_faces =
3905 connectivity.entity_to_entities(dim, dim - 1);
3906
3907 // count how many cells are adjacent to the same face
3908 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3909 for (const unsigned int face : cells_to_faces[cell])
3910 ++count[face];
3911
3912 // loop over all faces
3913 for (unsigned int face = 0; face < count.size(); ++face)
3914 {
3915 if (count[face] != 1) // inner face
3916 continue;
3917
3918 // boundary faces ...
3919 bids_face[face].boundary_id = 0;
3920
3921 if (dim != 3)
3922 continue;
3923
3924 // ... and the lines of quads in 3d
3925 const auto &quads_to_lines =
3926 connectivity.entity_to_entities(2, 1);
3927 for (const unsigned int line : quads_to_lines[face])
3928 tria.faces->lines.boundary_or_material_id[line].boundary_id =
3929 0;
3930 }
3931 }
3932 else // 1d
3933 {
3934 constexpr unsigned int t_tba = static_cast<unsigned int>(-1);
3935 constexpr unsigned int t_inner = static_cast<unsigned int>(-2);
3936
3937 std::vector<unsigned int> type(vertices.size(), t_tba);
3938
3939 const auto &cells_to_vertices =
3940 connectivity.entity_to_entities(1, 0);
3941
3942 for (unsigned int cell = 0; cell < cells.size(); ++cell)
3943 {
3944 const auto vertices = cells_to_vertices[cell];
3945 for (unsigned int v = 0; v < vertices.size(); ++v)
3946 if (type[vertices[v]] != t_inner)
3947 type[vertices[v]] =
3948 (type[vertices[v]] == t_tba ? v : t_inner);
3949 }
3950
3951 for (unsigned int face = 0; face < type.size(); ++face)
3952 {
3953 // note: we also treat manifolds here!?
3954 (*tria.vertex_to_manifold_id_map_1d)[face] =
3956 if (type[face] != t_inner && type[face] != t_tba)
3957 (*tria.vertex_to_boundary_id_map_1d)[face] = type[face];
3958 }
3959 }
3960
3961 // SubCellData: line
3962 if (dim >= 2)
3963 process_subcelldata(connectivity.entity_to_entities(1, 0),
3964 tria.faces->lines,
3965 subcelldata.boundary_lines,
3966 vertices);
3967
3968 // SubCellData: quad
3969 if (dim == 3)
3970 process_subcelldata(connectivity.entity_to_entities(2, 0),
3971 tria.faces->quads,
3972 subcelldata.boundary_quads,
3973 vertices);
3974 }
3975
3976
3977 template <int structdim, int spacedim>
3978 static void
3980 const ArrayOfArrays &crs,
3981 TriaObjects &obj,
3982 const std::vector<CellData<structdim>> &boundary_objects_in,
3983 const std::vector<Point<spacedim>> &vertex_locations)
3984 {
3985 AssertDimension(obj.structdim, structdim);
3986
3987 if (boundary_objects_in.empty())
3988 return; // empty subcelldata -> nothing to do
3989
3990 // pre-sort subcelldata
3991 auto boundary_objects = boundary_objects_in;
3992
3993 // ... sort vertices
3994 for (auto &boundary_object : boundary_objects)
3995 std::sort(boundary_object.vertices.begin(),
3996 boundary_object.vertices.end());
3997
3998 // ... sort cells
3999 std::sort(boundary_objects.begin(),
4000 boundary_objects.end(),
4001 [](const auto &a, const auto &b) {
4002 return a.vertices < b.vertices;
4003 });
4004
4005 [[maybe_unused]] unsigned int counter = 0;
4006
4009 key;
4010
4011 for (unsigned int o = 0; o < obj.n_objects(); ++o)
4012 {
4013 auto &boundary_id = obj.boundary_or_material_id[o].boundary_id;
4014 auto &manifold_id = obj.manifold_id[o];
4015
4016 // assert that object has not been visited yet and its value
4017 // has not been modified yet
4018 AssertThrow(boundary_id == 0 ||
4023
4024 // create key
4025 const ArrayView<const unsigned int> indices = crs[o];
4026 key.assign(indices.begin(), indices.end());
4027 std::sort(key.begin(), key.end());
4028
4029 // is subcelldata provided? -> binary search
4030 const auto subcell_object =
4031 std::lower_bound(boundary_objects.begin(),
4032 boundary_objects.end(),
4033 key,
4034 [&](const auto &cell, const auto &key) {
4035 return cell.vertices < key;
4036 });
4037
4038 // no subcelldata provided for this object
4039 if (subcell_object == boundary_objects.end() ||
4040 subcell_object->vertices != key)
4041 continue;
4042
4043 ++counter;
4044
4045 // set manifold id
4046 manifold_id = subcell_object->manifold_id;
4047
4048 // set boundary id
4049 if (subcell_object->boundary_id !=
4051 {
4054 ExcMessage(
4055 "The input arguments for creating a triangulation "
4056 "specified a boundary id for an internal face. This "
4057 "is not allowed."
4058 "\n\n"
4059 "The object in question has vertex indices " +
4060 [subcell_object]() {
4061 std::string s;
4062 for (const auto v : subcell_object->vertices)
4063 s += std::to_string(v) + ',';
4064 return s;
4065 }() +
4066 " which are located at coordinates " +
4067 [vertex_locations, subcell_object]() {
4068 std::ostringstream s;
4069 for (unsigned int i = 0;
4070 i < subcell_object->vertices.size();
4071 ++i)
4072 s << '('
4073 << vertex_locations[subcell_object->vertices[i]]
4074 << (i != subcell_object->vertices.size() - 1 ? "), " :
4075 ")");
4076 return s.str();
4077 }() +
4078 "."));
4079 boundary_id = subcell_object->boundary_id;
4080 }
4081 }
4082
4083 // make sure that all subcelldata entries have been processed
4084 // TODO: this is not guaranteed, why?
4085 // AssertDimension(counter, boundary_objects_in.size());
4086 }
4087
4088
4089
4105 template <int spacedim>
4106 static void
4109 std::vector<unsigned int> &,
4110 std::vector<unsigned int> &)
4111 {
4112 const unsigned int dim = 1;
4113
4114 // first we need to reset the
4115 // neighbor pointers of the
4116 // neighbors of this cell's
4117 // children to this cell. This is
4118 // different for one dimension,
4119 // since there neighbors can have a
4120 // refinement level differing from
4121 // that of this cell's children by
4122 // more than one level.
4123
4124 Assert(!cell->child(0)->has_children() &&
4125 !cell->child(1)->has_children(),
4127
4128 // first do it for the cells to the
4129 // left
4130 if (cell->neighbor(0).state() == IteratorState::valid)
4131 if (cell->neighbor(0)->has_children())
4132 {
4134 cell->neighbor(0);
4135 Assert(neighbor->level() == cell->level(), ExcInternalError());
4136
4137 // right child
4138 neighbor = neighbor->child(1);
4139 while (true)
4140 {
4141 Assert(neighbor->neighbor(1) == cell->child(0),
4143 neighbor->set_neighbor(1, cell);
4144
4145 // move on to further
4146 // children on the
4147 // boundary between this
4148 // cell and its neighbor
4149 if (neighbor->has_children())
4150 neighbor = neighbor->child(1);
4151 else
4152 break;
4153 }
4154 }
4155
4156 // now do it for the cells to the
4157 // left
4158 if (cell->neighbor(1).state() == IteratorState::valid)
4159 if (cell->neighbor(1)->has_children())
4160 {
4162 cell->neighbor(1);
4163 Assert(neighbor->level() == cell->level(), ExcInternalError());
4164
4165 // left child
4166 neighbor = neighbor->child(0);
4167 while (true)
4168 {
4169 Assert(neighbor->neighbor(0) == cell->child(1),
4171 neighbor->set_neighbor(0, cell);
4172
4173 // move on to further
4174 // children on the
4175 // boundary between this
4176 // cell and its neighbor
4177 if (neighbor->has_children())
4178 neighbor = neighbor->child(0);
4179 else
4180 break;
4181 }
4182 }
4183
4184
4185 // delete the vertex which will not
4186 // be needed anymore. This vertex
4187 // is the second of the first child
4188 triangulation.vertices_used[cell->child(0)->vertex_index(1)] = false;
4189
4190 // invalidate children. clear user
4191 // pointers, to avoid that they may
4192 // appear at unwanted places later
4193 // on...
4194 for (unsigned int child = 0; child < cell->n_children(); ++child)
4195 {
4196 cell->child(child)->clear_user_data();
4197 cell->child(child)->clear_user_flag();
4198 cell->child(child)->clear_used_flag();
4199 }
4200
4201
4202 // delete pointer to children
4203 cell->clear_children();
4204 cell->clear_user_flag();
4205 }
4206
4207
4208
4209 template <int spacedim>
4210 static void
4213 std::vector<unsigned int> &line_cell_count,
4214 std::vector<unsigned int> &)
4215 {
4216 const unsigned int dim = 2;
4217 const RefinementCase<dim> ref_case = cell->refinement_case();
4218
4219 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
4221
4222 // vectors to hold all lines which
4223 // may be deleted
4224 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
4225 lines_to_delete(0);
4226
4227 lines_to_delete.reserve(4 * 2 + 4);
4228
4229 // now we decrease the counters for
4230 // lines contained in the child
4231 // cells
4232 for (unsigned int c = 0; c < cell->n_children(); ++c)
4233 {
4235 cell->child(c);
4236 for (unsigned int l = 0; l < GeometryInfo<dim>::lines_per_cell; ++l)
4237 --line_cell_count[child->line_index(l)];
4238 }
4239
4240
4241 // delete the vertex which will not
4242 // be needed anymore. This vertex
4243 // is the second of the second line
4244 // of the first child, if the cell
4245 // is refined with cut_xy, else there
4246 // is no inner vertex.
4247 // additionally delete unneeded inner
4248 // lines
4249 if (ref_case == RefinementCase<dim>::cut_xy)
4250 {
4251 triangulation
4252 .vertices_used[cell->child(0)->line(1)->vertex_index(1)] = false;
4253
4254 lines_to_delete.push_back(cell->child(0)->line(1));
4255 lines_to_delete.push_back(cell->child(0)->line(3));
4256 lines_to_delete.push_back(cell->child(3)->line(0));
4257 lines_to_delete.push_back(cell->child(3)->line(2));
4258 }
4259 else
4260 {
4261 unsigned int inner_face_no =
4262 ref_case == RefinementCase<dim>::cut_x ? 1 : 3;
4263
4264 // the inner line will not be
4265 // used any more
4266 lines_to_delete.push_back(cell->child(0)->line(inner_face_no));
4267 }
4268
4269 // invalidate children
4270 for (unsigned int child = 0; child < cell->n_children(); ++child)
4271 {
4272 cell->child(child)->clear_user_data();
4273 cell->child(child)->clear_user_flag();
4274 cell->child(child)->clear_used_flag();
4275 }
4276
4277
4278 // delete pointer to children
4279 cell->clear_children();
4280 cell->clear_refinement_case();
4281 cell->clear_user_flag();
4282
4283 // look at the refinement of outer
4284 // lines. if nobody needs those
4285 // anymore we can add them to the
4286 // list of lines to be deleted.
4287 for (unsigned int line_no = 0;
4288 line_no < GeometryInfo<dim>::lines_per_cell;
4289 ++line_no)
4290 {
4292 cell->line(line_no);
4293
4294 if (line->has_children())
4295 {
4296 // if one of the cell counters is
4297 // zero, the other has to be as well
4298
4299 Assert((line_cell_count[line->child_index(0)] == 0 &&
4300 line_cell_count[line->child_index(1)] == 0) ||
4301 (line_cell_count[line->child_index(0)] > 0 &&
4302 line_cell_count[line->child_index(1)] > 0),
4304
4305 if (line_cell_count[line->child_index(0)] == 0)
4306 {
4307 for (unsigned int c = 0; c < 2; ++c)
4308 Assert(!line->child(c)->has_children(),
4310
4311 // we may delete the line's
4312 // children and the middle vertex
4313 // as no cell references them
4314 // anymore
4315 triangulation
4316 .vertices_used[line->child(0)->vertex_index(1)] = false;
4317
4318 lines_to_delete.push_back(line->child(0));
4319 lines_to_delete.push_back(line->child(1));
4320
4321 line->clear_children();
4322 }
4323 }
4324 }
4325
4326 // finally, delete unneeded lines
4327
4328 // clear user pointers, to avoid that
4329 // they may appear at unwanted places
4330 // later on...
4331 // same for user flags, then finally
4332 // delete the lines
4333 typename std::vector<
4335 line = lines_to_delete.begin(),
4336 endline = lines_to_delete.end();
4337 for (; line != endline; ++line)
4338 {
4339 (*line)->clear_user_data();
4340 (*line)->clear_user_flag();
4341 (*line)->clear_used_flag();
4342 }
4343 }
4344
4345
4346
4347 template <int spacedim>
4348 static void
4351 std::vector<unsigned int> &line_cell_count,
4352 std::vector<unsigned int> &quad_cell_count)
4353 {
4354 const unsigned int dim = 3;
4355
4356 Assert(line_cell_count.size() == triangulation.n_raw_lines(),
4358 Assert(quad_cell_count.size() == triangulation.n_raw_quads(),
4360
4361 // first of all, we store the RefineCase of
4362 // this cell
4363 const RefinementCase<dim> ref_case = cell->refinement_case();
4364 // vectors to hold all lines and quads which
4365 // may be deleted
4366 std::vector<typename Triangulation<dim, spacedim>::line_iterator>
4367 lines_to_delete(0);
4368 std::vector<typename Triangulation<dim, spacedim>::quad_iterator>
4369 quads_to_delete(0);
4370
4371 lines_to_delete.reserve(12 * 2 + 6 * 4 + 6);
4372 quads_to_delete.reserve(6 * 4 + 12);
4373
4374 // now we decrease the counters for lines and
4375 // quads contained in the child cells
4376 for (unsigned int c = 0; c < cell->n_children(); ++c)
4377 {
4379 cell->child(c);
4380 const auto line_indices = TriaAccessorImplementation::
4381 Implementation::get_line_indices_of_cell(*child);
4382 for (const unsigned int l : cell->line_indices())
4383 --line_cell_count[line_indices[l]];
4384 for (auto f : GeometryInfo<dim>::face_indices())
4385 --quad_cell_count[child->quad_index(f)];
4386 }
4387
4388 //-------------------------------------
4389 // delete interior quads and lines and the
4390 // interior vertex, depending on the
4391 // refinement case of the cell
4392 //
4393 // for append quads and lines: only append
4394 // them to the list of objects to be deleted
4395
4396 switch (ref_case)
4397 {
4399 quads_to_delete.push_back(cell->child(0)->face(1));
4400 break;
4402 quads_to_delete.push_back(cell->child(0)->face(3));
4403 break;
4405 quads_to_delete.push_back(cell->child(0)->face(5));
4406 break;
4408 quads_to_delete.push_back(cell->child(0)->face(1));
4409 quads_to_delete.push_back(cell->child(0)->face(3));
4410 quads_to_delete.push_back(cell->child(3)->face(0));
4411 quads_to_delete.push_back(cell->child(3)->face(2));
4412
4413 lines_to_delete.push_back(cell->child(0)->line(11));
4414 break;
4416 quads_to_delete.push_back(cell->child(0)->face(1));
4417 quads_to_delete.push_back(cell->child(0)->face(5));
4418 quads_to_delete.push_back(cell->child(3)->face(0));
4419 quads_to_delete.push_back(cell->child(3)->face(4));
4420
4421 lines_to_delete.push_back(cell->child(0)->line(5));
4422 break;
4424 quads_to_delete.push_back(cell->child(0)->face(3));
4425 quads_to_delete.push_back(cell->child(0)->face(5));
4426 quads_to_delete.push_back(cell->child(3)->face(2));
4427 quads_to_delete.push_back(cell->child(3)->face(4));
4428
4429 lines_to_delete.push_back(cell->child(0)->line(7));
4430 break;
4432 quads_to_delete.push_back(cell->child(0)->face(1));
4433 quads_to_delete.push_back(cell->child(2)->face(1));
4434 quads_to_delete.push_back(cell->child(4)->face(1));
4435 quads_to_delete.push_back(cell->child(6)->face(1));
4436
4437 quads_to_delete.push_back(cell->child(0)->face(3));
4438 quads_to_delete.push_back(cell->child(1)->face(3));
4439 quads_to_delete.push_back(cell->child(4)->face(3));
4440 quads_to_delete.push_back(cell->child(5)->face(3));
4441
4442 quads_to_delete.push_back(cell->child(0)->face(5));
4443 quads_to_delete.push_back(cell->child(1)->face(5));
4444 quads_to_delete.push_back(cell->child(2)->face(5));
4445 quads_to_delete.push_back(cell->child(3)->face(5));
4446
4447 lines_to_delete.push_back(cell->child(0)->line(5));
4448 lines_to_delete.push_back(cell->child(0)->line(7));
4449 lines_to_delete.push_back(cell->child(0)->line(11));
4450 lines_to_delete.push_back(cell->child(7)->line(0));
4451 lines_to_delete.push_back(cell->child(7)->line(2));
4452 lines_to_delete.push_back(cell->child(7)->line(8));
4453 // delete the vertex which will not
4454 // be needed anymore. This vertex
4455 // is the vertex at the heart of
4456 // this cell, which is the sixth of
4457 // the first child
4458 triangulation.vertices_used[cell->child(0)->vertex_index(7)] =
4459 false;
4460 break;
4461 default:
4462 // only remaining case is
4463 // no_refinement, thus an error
4465 break;
4466 }
4467
4468
4469 // invalidate children
4470 for (unsigned int child = 0; child < cell->n_children(); ++child)
4471 {
4472 cell->child(child)->clear_user_data();
4473 cell->child(child)->clear_user_flag();
4474
4475 for (auto f : GeometryInfo<dim>::face_indices())
4476 // set flags denoting deviations from standard orientation of
4477 // faces back to initialization values
4480
4481 cell->child(child)->clear_used_flag();
4482 }
4483
4484
4485 // delete pointer to children
4486 cell->clear_children();
4487 cell->clear_refinement_case();
4488 cell->clear_user_flag();
4489
4490 // so far we only looked at inner quads,
4491 // lines and vertices. Now we have to
4492 // consider outer ones as well. here, we have
4493 // to check, whether there are other cells
4494 // still needing these objects. otherwise we
4495 // can delete them. first for quads (and
4496 // their inner lines).
4497
4498 for (const unsigned int quad_no : GeometryInfo<dim>::face_indices())
4499 {
4501 cell->face(quad_no);
4502
4503 Assert(
4504 (GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) &&
4505 quad->has_children()) ||
4506 GeometryInfo<dim>::face_refinement_case(ref_case, quad_no) ==
4509
4510 switch (quad->refinement_case())
4511 {
4512 case RefinementCase<dim - 1>::no_refinement:
4513 // nothing to do as the quad
4514 // is not refined
4515 break;
4516 case RefinementCase<dim - 1>::cut_x:
4517 case RefinementCase<dim - 1>::cut_y:
4518 {
4519 // if one of the cell counters is
4520 // zero, the other has to be as
4521 // well
4522 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4523 quad_cell_count[quad->child_index(1)] == 0) ||
4524 (quad_cell_count[quad->child_index(0)] > 0 &&
4525 quad_cell_count[quad->child_index(1)] > 0),
4527 // it might be, that the quad is
4528 // refined twice anisotropically,
4529 // first check, whether we may
4530 // delete possible grand_children
4531 unsigned int deleted_grandchildren = 0;
4532 unsigned int number_of_child_refinements = 0;
4533
4534 for (unsigned int c = 0; c < 2; ++c)
4535 if (quad->child(c)->has_children())
4536 {
4537 ++number_of_child_refinements;
4538 // if one of the cell counters is
4539 // zero, the other has to be as
4540 // well
4541 Assert(
4542 (quad_cell_count[quad->child(c)->child_index(0)] ==
4543 0 &&
4544 quad_cell_count[quad->child(c)->child_index(1)] ==
4545 0) ||
4546 (quad_cell_count[quad->child(c)->child_index(0)] >
4547 0 &&
4548 quad_cell_count[quad->child(c)->child_index(1)] >
4549 0),
4551 if (quad_cell_count[quad->child(c)->child_index(0)] ==
4552 0)
4553 {
4554 // Assert, that the two
4555 // anisotropic
4556 // refinements add up to
4557 // isotropic refinement
4558 Assert(quad->refinement_case() +
4559 quad->child(c)->refinement_case() ==
4562 // we may delete the
4563 // quad's children and
4564 // the inner line as no
4565 // cell references them
4566 // anymore
4567 quads_to_delete.push_back(
4568 quad->child(c)->child(0));
4569 quads_to_delete.push_back(
4570 quad->child(c)->child(1));
4571 if (quad->child(c)->refinement_case() ==
4573 lines_to_delete.push_back(
4574 quad->child(c)->child(0)->line(1));
4575 else
4576 lines_to_delete.push_back(
4577 quad->child(c)->child(0)->line(3));
4578 quad->child(c)->clear_children();
4579 quad->child(c)->clear_refinement_case();
4580 ++deleted_grandchildren;
4581 }
4582 }
4583 // if no grandchildren are left, we
4584 // may as well delete the
4585 // refinement of the inner line
4586 // between our children and the
4587 // corresponding vertex
4588 if (number_of_child_refinements > 0 &&
4589 deleted_grandchildren == number_of_child_refinements)
4590 {
4592 middle_line;
4593 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4594 middle_line = quad->child(0)->line(1);
4595 else
4596 middle_line = quad->child(0)->line(3);
4597
4598 lines_to_delete.push_back(middle_line->child(0));
4599 lines_to_delete.push_back(middle_line->child(1));
4600 triangulation
4601 .vertices_used[middle_vertex_index<dim, spacedim>(
4602 middle_line)] = false;
4603 middle_line->clear_children();
4604 }
4605
4606 // now consider the direct children
4607 // of the given quad
4608 if (quad_cell_count[quad->child_index(0)] == 0)
4609 {
4610 // we may delete the quad's
4611 // children and the inner line
4612 // as no cell references them
4613 // anymore
4614 quads_to_delete.push_back(quad->child(0));
4615 quads_to_delete.push_back(quad->child(1));
4616 if (quad->refinement_case() == RefinementCase<2>::cut_x)
4617 lines_to_delete.push_back(quad->child(0)->line(1));
4618 else
4619 lines_to_delete.push_back(quad->child(0)->line(3));
4620
4621 // if the counters just dropped
4622 // to zero, otherwise the
4623 // children would have been
4624 // deleted earlier, then this
4625 // cell's children must have
4626 // contained the anisotropic
4627 // quad children. thus, if
4628 // those have again anisotropic
4629 // children, which are in
4630 // effect isotropic children of
4631 // the original quad, those are
4632 // still needed by a
4633 // neighboring cell and we
4634 // cannot delete them. instead,
4635 // we have to reset this quad's
4636 // refine case to isotropic and
4637 // set the children
4638 // accordingly.
4639 if (quad->child(0)->has_children())
4640 if (quad->refinement_case() ==
4642 {
4643 // now evereything is
4644 // quite complicated. we
4645 // have the children
4646 // numbered according to
4647 //
4648 // *---*---*
4649 // |n+1|m+1|
4650 // *---*---*
4651 // | n | m |
4652 // *---*---*
4653 //
4654 // from the original
4655 // anisotropic
4656 // refinement. we have to
4657 // reorder them as
4658 //
4659 // *---*---*
4660 // | m |m+1|
4661 // *---*---*
4662 // | n |n+1|
4663 // *---*---*
4664 //
4665 // for isotropic refinement.
4666 //
4667 // this is a bit ugly, of
4668 // course: loop over all
4669 // cells on all levels
4670 // and look for faces n+1
4671 // (switch_1) and m
4672 // (switch_2).
4673 const typename Triangulation<dim, spacedim>::
4674 quad_iterator switch_1 =
4675 quad->child(0)->child(1),
4676 switch_2 =
4677 quad->child(1)->child(0);
4678
4679 Assert(!switch_1->has_children(),
4681 Assert(!switch_2->has_children(),
4683
4684 const int switch_1_index = switch_1->index();
4685 const int switch_2_index = switch_2->index();
4686 for (unsigned int l = 0;
4687 l < triangulation.levels.size();
4688 ++l)
4689 for (unsigned int h = 0;
4690 h <
4691 triangulation.levels[l]->cells.n_objects();
4692 ++h)
4693 for (const unsigned int q :
4695 {
4696 const int index =
4697 triangulation.levels[l]
4698 ->cells.get_bounding_object_indices(
4699 h)[q];
4700 if (index == switch_1_index)
4701 triangulation.levels[l]
4702 ->cells.get_bounding_object_indices(
4703 h)[q] = switch_2_index;
4704 else if (index == switch_2_index)
4705 triangulation.levels[l]
4706 ->cells.get_bounding_object_indices(
4707 h)[q] = switch_1_index;
4708 }
4709 // now we have to copy
4710 // all information of the
4711 // two quads
4712 const int switch_1_lines[4] = {
4713 static_cast<signed int>(
4714 switch_1->line_index(0)),
4715 static_cast<signed int>(
4716 switch_1->line_index(1)),
4717 static_cast<signed int>(
4718 switch_1->line_index(2)),
4719 static_cast<signed int>(
4720 switch_1->line_index(3))};
4722 switch_1_line_orientations[4] = {
4723 switch_1->line_orientation(0),
4724 switch_1->line_orientation(1),
4725 switch_1->line_orientation(2),
4726 switch_1->line_orientation(3)};
4727 const types::boundary_id switch_1_boundary_id =
4728 switch_1->boundary_id();
4729 const unsigned int switch_1_user_index =
4730 switch_1->user_index();
4731 const bool switch_1_user_flag =
4732 switch_1->user_flag_set();
4733
4734 switch_1->set_bounding_object_indices(
4735 {switch_2->line_index(0),
4736 switch_2->line_index(1),
4737 switch_2->line_index(2),
4738 switch_2->line_index(3)});
4739 switch_1->set_line_orientation(
4740 0, switch_2->line_orientation(0));
4741 switch_1->set_line_orientation(
4742 1, switch_2->line_orientation(1));
4743 switch_1->set_line_orientation(
4744 2, switch_2->line_orientation(2));
4745 switch_1->set_line_orientation(
4746 3, switch_2->line_orientation(3));
4747 switch_1->set_boundary_id_internal(
4748 switch_2->boundary_id());
4749 switch_1->set_manifold_id(
4750 switch_2->manifold_id());
4751 switch_1->set_user_index(switch_2->user_index());
4752 if (switch_2->user_flag_set())
4753 switch_1->set_user_flag();
4754 else
4755 switch_1->clear_user_flag();
4756
4757 switch_2->set_bounding_object_indices(
4758 {switch_1_lines[0],
4759 switch_1_lines[1],
4760 switch_1_lines[2],
4761 switch_1_lines[3]});
4762 switch_2->set_line_orientation(
4763 0, switch_1_line_orientations[0]);
4764 switch_2->set_line_orientation(
4765 1, switch_1_line_orientations[1]);
4766 switch_2->set_line_orientation(
4767 2, switch_1_line_orientations[2]);
4768 switch_2->set_line_orientation(
4769 3, switch_1_line_orientations[3]);
4770 switch_2->set_boundary_id_internal(
4771 switch_1_boundary_id);
4772 switch_2->set_manifold_id(
4773 switch_1->manifold_id());
4774 switch_2->set_user_index(switch_1_user_index);
4775 if (switch_1_user_flag)
4776 switch_2->set_user_flag();
4777 else
4778 switch_2->clear_user_flag();
4779
4780 const unsigned int child_0 =
4781 quad->child(0)->child_index(0);
4782 const unsigned int child_2 =
4783 quad->child(1)->child_index(0);
4784 quad->clear_children();
4785 quad->clear_refinement_case();
4786 quad->set_refinement_case(
4788 quad->set_children(0, child_0);
4789 quad->set_children(2, child_2);
4790 std::swap(quad_cell_count[child_0 + 1],
4791 quad_cell_count[child_2]);
4792 }
4793 else
4794 {
4795 // the face was refined
4796 // with cut_y, thus the
4797 // children are already
4798 // in correct order. we
4799 // only have to set them
4800 // correctly, deleting
4801 // the indirection of two
4802 // anisotropic refinement
4803 // and going directly
4804 // from the quad to
4805 // isotropic children
4806 const unsigned int child_0 =
4807 quad->child(0)->child_index(0);
4808 const unsigned int child_2 =
4809 quad->child(1)->child_index(0);
4810 quad->clear_children();
4811 quad->clear_refinement_case();
4812 quad->set_refinement_case(
4814 quad->set_children(0, child_0);
4815 quad->set_children(2, child_2);
4816 }
4817 else
4818 {
4819 quad->clear_children();
4820 quad->clear_refinement_case();
4821 }
4822 }
4823 break;
4824 }
4825 case RefinementCase<dim - 1>::cut_xy:
4826 {
4827 // if one of the cell counters is
4828 // zero, the others have to be as
4829 // well
4830
4831 Assert((quad_cell_count[quad->child_index(0)] == 0 &&
4832 quad_cell_count[quad->child_index(1)] == 0 &&
4833 quad_cell_count[quad->child_index(2)] == 0 &&
4834 quad_cell_count[quad->child_index(3)] == 0) ||
4835 (quad_cell_count[quad->child_index(0)] > 0 &&
4836 quad_cell_count[quad->child_index(1)] > 0 &&
4837 quad_cell_count[quad->child_index(2)] > 0 &&
4838 quad_cell_count[quad->child_index(3)] > 0),
4840
4841 if (quad_cell_count[quad->child_index(0)] == 0)
4842 {
4843 // we may delete the quad's
4844 // children, the inner lines
4845 // and the middle vertex as no
4846 // cell references them anymore
4847 lines_to_delete.push_back(quad->child(0)->line(1));
4848 lines_to_delete.push_back(quad->child(3)->line(0));
4849 lines_to_delete.push_back(quad->child(0)->line(3));
4850 lines_to_delete.push_back(quad->child(3)->line(2));
4851
4852 for (unsigned int child = 0; child < quad->n_children();
4853 ++child)
4854 quads_to_delete.push_back(quad->child(child));
4855
4856 triangulation
4857 .vertices_used[quad->child(0)->vertex_index(3)] =
4858 false;
4859
4860 quad->clear_children();
4861 quad->clear_refinement_case();
4862 }
4863 }
4864 break;
4865
4866 default:
4868 break;
4869 }
4870 }
4871
4872 // now we repeat a similar procedure
4873 // for the outer lines of this cell.
4874
4875 // if in debug mode: check that each
4876 // of the lines for which we consider
4877 // deleting the children in fact has
4878 // children (the bits/coarsening_3d
4879 // test tripped over this initially)
4880 for (unsigned int line_no = 0;
4881 line_no < GeometryInfo<dim>::lines_per_cell;
4882 ++line_no)
4883 {
4885 cell->line(line_no);
4886
4887 Assert(
4888 (GeometryInfo<dim>::line_refinement_case(ref_case, line_no) &&
4889 line->has_children()) ||
4890 GeometryInfo<dim>::line_refinement_case(ref_case, line_no) ==
4893
4894 if (line->has_children())
4895 {
4896 // if one of the cell counters is
4897 // zero, the other has to be as well
4898
4899 Assert((line_cell_count[line->child_index(0)] == 0 &&
4900 line_cell_count[line->child_index(1)] == 0) ||
4901 (line_cell_count[line->child_index(0)] > 0 &&
4902 line_cell_count[line->child_index(1)] > 0),
4904
4905 if (line_cell_count[line->child_index(0)] == 0)
4906 {
4907 for (unsigned int c = 0; c < 2; ++c)
4908 Assert(!line->child(c)->has_children(),
4910
4911 // we may delete the line's
4912 // children and the middle vertex
4913 // as no cell references them
4914 // anymore
4915 triangulation
4916 .vertices_used[line->child(0)->vertex_index(1)] = false;
4917
4918 lines_to_delete.push_back(line->child(0));
4919 lines_to_delete.push_back(line->child(1));
4920
4921 line->clear_children();
4922 }
4923 }
4924 }
4925
4926 // finally, delete unneeded quads and lines
4927
4928 // clear user pointers, to avoid that
4929 // they may appear at unwanted places
4930 // later on...
4931 // same for user flags, then finally
4932 // delete the quads and lines
4933 typename std::vector<
4935 line = lines_to_delete.begin(),
4936 endline = lines_to_delete.end();
4937 for (; line != endline; ++line)
4938 {
4939 (*line)->clear_user_data();
4940 (*line)->clear_user_flag();
4941 (*line)->clear_used_flag();
4942 }
4943
4944 typename std::vector<
4946 quad = quads_to_delete.begin(),
4947 endquad = quads_to_delete.end();
4948 for (; quad != endquad; ++quad)
4949 {
4950 (*quad)->clear_user_data();
4951 (*quad)->clear_children();
4952 (*quad)->clear_refinement_case();
4953 (*quad)->clear_user_flag();
4954 (*quad)->clear_used_flag();
4955 }
4956 }
4957
4958
4976 template <int spacedim>
4977 static void
4979 Triangulation<2, spacedim> &triangulation,
4980 unsigned int &next_unused_vertex,
4982 &next_unused_line,
4984 &next_unused_cell,
4985 const typename Triangulation<2, spacedim>::cell_iterator &cell)
4986 {
4987 const unsigned int dim = 2;
4988 // clear refinement flag
4989 const RefinementCase<dim> ref_case = cell->refine_flag_set();
4990 cell->clear_refine_flag();
4991
4992 /* For the refinement process: since we go the levels up from the
4993 lowest, there are (unlike above) only two possibilities: a neighbor
4994 cell is on the same level or one level up (in both cases, it may or
4995 may not be refined later on, but we don't care here).
4996
4997 First:
4998 Set up an array of the 3x3 vertices, which are distributed on the
4999 cell (the array consists of indices into the @p{vertices} std::vector
5000
5001 2--7--3
5002 | | |
5003 4--8--5
5004 | | |
5005 0--6--1
5006
5007 note: in case of cut_x or cut_y not all these vertices are needed for
5008 the new cells
5009
5010 Second:
5011 Set up an array of the new lines (the array consists of iterator
5012 pointers into the lines arrays)
5013
5014 .-6-.-7-. The directions are: .->-.->-.
5015 1 9 3 ^ ^ ^
5016 .-10.11-. .->-.->-.
5017 0 8 2 ^ ^ ^
5018 .-4-.-5-. .->-.->-.
5019
5020 cut_x:
5021 .-4-.-5-.
5022 | | |
5023 0 6 1
5024 | | |
5025 .-2-.-3-.
5026
5027 cut_y:
5028 .---5---.
5029 1 3
5030 .---6---.
5031 0 2
5032 .---4---.
5033
5034
5035 Third:
5036 Set up an array of neighbors:
5037
5038 6 7
5039 .--.--.
5040 1| | |3
5041 .--.--.
5042 0| | |2
5043 .--.--.
5044 4 5
5045
5046 We need this array for two reasons: first to get the lines which will
5047 bound the four subcells (if the neighboring cell is refined, these
5048 lines already exist), and second to update neighborship information.
5049 Since if a neighbor is not refined, its neighborship record only
5050 points to the present, unrefined, cell rather than the children we
5051 are presently creating, we only need the neighborship information
5052 if the neighbor cells are refined. In all other cases, we store
5053 the unrefined neighbor address
5054
5055 We also need for every neighbor (if refined) which number among its
5056 neighbors the present (unrefined) cell has, since that number is to
5057 be replaced and because that also is the number of the subline which
5058 will be the interface between that neighbor and the to be created
5059 cell. We will store this number (between 0 and 3) in the field
5060 @p{neighbors_neighbor}.
5061
5062 It would be sufficient to use the children of the common line to the
5063 neighbor, if we only wanted to get the new sublines and the new
5064 vertex, but because we need to update the neighborship information of
5065 the two refined subcells of the neighbor, we need to search these
5066 anyway.
5067
5068 Convention:
5069 The created children are numbered like this:
5070
5071 .--.--.
5072 |2 . 3|
5073 .--.--.
5074 |0 | 1|
5075 .--.--.
5076 */
5077 // collect the indices of the eight surrounding vertices
5078 // 2--7--3
5079 // | | |
5080 // 4--8--5
5081 // | | |
5082 // 0--6--1
5083 int new_vertices[9];
5084 for (unsigned int vertex_no = 0; vertex_no < 4; ++vertex_no)
5085 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5086 for (unsigned int line_no = 0; line_no < 4; ++line_no)
5087 if (cell->line(line_no)->has_children())
5088 new_vertices[4 + line_no] =
5089 cell->line(line_no)->child(0)->vertex_index(1);
5090
5091 if (ref_case == RefinementCase<dim>::cut_xy)
5092 {
5093 // find the next
5094 // unused vertex and
5095 // allocate it for
5096 // the new vertex we
5097 // need here
5098 while (triangulation.vertices_used[next_unused_vertex] == true)
5099 ++next_unused_vertex;
5100 Assert(next_unused_vertex < triangulation.vertices.size(),
5101 ExcMessage(
5102 "Internal error: During refinement, the triangulation "
5103 "wants to access an element of the 'vertices' array "
5104 "but it turns out that the array is not large enough."));
5105 triangulation.vertices_used[next_unused_vertex] = true;
5106
5107 new_vertices[8] = next_unused_vertex;
5108
5109 // determine middle vertex by transfinite interpolation to be
5110 // consistent with what happens to quads in a
5111 // Triangulation<3,3> when they are refined
5112 triangulation.vertices[next_unused_vertex] =
5113 cell->center(true, true);
5114 }
5115
5116
5117 // Now the lines:
5119 unsigned int lmin = 8;
5120 unsigned int lmax = 12;
5121 if (ref_case != RefinementCase<dim>::cut_xy)
5122 {
5123 lmin = 6;
5124 lmax = 7;
5125 }
5126
5127 for (unsigned int l = lmin; l < lmax; ++l)
5128 {
5129 while (next_unused_line->used() == true)
5130 ++next_unused_line;
5131 new_lines[l] = next_unused_line;
5132 ++next_unused_line;
5133
5134 AssertIsNotUsed(new_lines[l]);
5135 }
5136
5137 if (ref_case == RefinementCase<dim>::cut_xy)
5138 {
5139 // .-6-.-7-.
5140 // 1 9 3
5141 // .-10.11-.
5142 // 0 8 2
5143 // .-4-.-5-.
5144
5145 // lines 0-7 already exist, create only the four interior
5146 // lines 8-11
5147 unsigned int l = 0;
5148 for (const unsigned int face_no : GeometryInfo<dim>::face_indices())
5149 for (unsigned int c = 0; c < 2; ++c, ++l)
5150 new_lines[l] = cell->line(face_no)->child(c);
5151 Assert(l == 8, ExcInternalError());
5152
5153 new_lines[8]->set_bounding_object_indices(
5154 {new_vertices[6], new_vertices[8]});
5155 new_lines[9]->set_bounding_object_indices(
5156 {new_vertices[8], new_vertices[7]});
5157 new_lines[10]->set_bounding_object_indices(
5158 {new_vertices[4], new_vertices[8]});
5159 new_lines[11]->set_bounding_object_indices(
5160 {new_vertices[8], new_vertices[5]});
5161 }
5162 else if (ref_case == RefinementCase<dim>::cut_x)
5163 {
5164 // .-4-.-5-.
5165 // | | |
5166 // 0 6 1
5167 // | | |
5168 // .-2-.-3-.
5169 new_lines[0] = cell->line(0);
5170 new_lines[1] = cell->line(1);
5171 new_lines[2] = cell->line(2)->child(0);
5172 new_lines[3] = cell->line(2)->child(1);
5173 new_lines[4] = cell->line(3)->child(0);
5174 new_lines[5] = cell->line(3)->child(1);
5175 new_lines[6]->set_bounding_object_indices(
5176 {new_vertices[6], new_vertices[7]});
5177 }
5178 else
5179 {
5181 // .---5---.
5182 // 1 3
5183 // .---6---.
5184 // 0 2
5185 // .---4---.
5186 new_lines[0] = cell->line(0)->child(0);
5187 new_lines[1] = cell->line(0)->child(1);
5188 new_lines[2] = cell->line(1)->child(0);
5189 new_lines[3] = cell->line(1)->child(1);
5190 new_lines[4] = cell->line(2);
5191 new_lines[5] = cell->line(3);
5192 new_lines[6]->set_bounding_object_indices(
5193 {new_vertices[4], new_vertices[5]});
5194 }
5195
5196 for (unsigned int l = lmin; l < lmax; ++l)
5197 {
5198 new_lines[l]->set_used_flag();
5199 new_lines[l]->clear_user_flag();
5200 new_lines[l]->clear_user_data();
5201 new_lines[l]->clear_children();
5202 // interior line
5203 new_lines[l]->set_boundary_id_internal(
5205 new_lines[l]->set_manifold_id(cell->manifold_id());
5206 }
5207
5208 // Now add the four (two)
5209 // new cells!
5212 while (next_unused_cell->used() == true)
5213 ++next_unused_cell;
5214
5215 const unsigned int n_children = GeometryInfo<dim>::n_children(ref_case);
5216 for (unsigned int i = 0; i < n_children; ++i)
5217 {
5218 AssertIsNotUsed(next_unused_cell);
5219 subcells[i] = next_unused_cell;
5220 ++next_unused_cell;
5221 if (i % 2 == 1 && i < n_children - 1)
5222 while (next_unused_cell->used() == true)
5223 ++next_unused_cell;
5224 }
5225
5226 if (ref_case == RefinementCase<dim>::cut_xy)
5227 {
5228 // children:
5229 // .--.--.
5230 // |2 . 3|
5231 // .--.--.
5232 // |0 | 1|
5233 // .--.--.
5234 // lines:
5235 // .-6-.-7-.
5236 // 1 9 3
5237 // .-10.11-.
5238 // 0 8 2
5239 // .-4-.-5-.
5240 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5241 new_lines[8]->index(),
5242 new_lines[4]->index(),
5243 new_lines[10]->index()});
5244 subcells[1]->set_bounding_object_indices({new_lines[8]->index(),
5245 new_lines[2]->index(),
5246 new_lines[5]->index(),
5247 new_lines[11]->index()});
5248 subcells[2]->set_bounding_object_indices({new_lines[1]->index(),
5249 new_lines[9]->index(),
5250 new_lines[10]->index(),
5251 new_lines[6]->index()});
5252 subcells[3]->set_bounding_object_indices({new_lines[9]->index(),
5253 new_lines[3]->index(),
5254 new_lines[11]->index(),
5255 new_lines[7]->index()});
5256 }
5257 else if (ref_case == RefinementCase<dim>::cut_x)
5258 {
5259 // children:
5260 // .--.--.
5261 // | . |
5262 // .0 . 1.
5263 // | | |
5264 // .--.--.
5265 // lines:
5266 // .-4-.-5-.
5267 // | | |
5268 // 0 6 1
5269 // | | |
5270 // .-2-.-3-.
5271 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5272 new_lines[6]->index(),
5273 new_lines[2]->index(),
5274 new_lines[4]->index()});
5275 subcells[1]->set_bounding_object_indices({new_lines[6]->index(),
5276 new_lines[1]->index(),
5277 new_lines[3]->index(),
5278 new_lines[5]->index()});
5279 }
5280 else
5281 {
5283 // children:
5284 // .-----.
5285 // | 1 |
5286 // .-----.
5287 // | 0 |
5288 // .-----.
5289 // lines:
5290 // .---5---.
5291 // 1 3
5292 // .---6---.
5293 // 0 2
5294 // .---4---.
5295 subcells[0]->set_bounding_object_indices({new_lines[0]->index(),
5296 new_lines[2]->index(),
5297 new_lines[4]->index(),
5298 new_lines[6]->index()});
5299 subcells[1]->set_bounding_object_indices({new_lines[1]->index(),
5300 new_lines[3]->index(),
5301 new_lines[6]->index(),
5302 new_lines[5]->index()});
5303 }
5304
5305 types::subdomain_id subdomainid = cell->subdomain_id();
5306
5307 for (unsigned int i = 0; i < n_children; ++i)
5308 {
5309 subcells[i]->set_used_flag();
5310 subcells[i]->clear_refine_flag();
5311 subcells[i]->clear_user_flag();
5312 subcells[i]->clear_user_data();
5313 subcells[i]->clear_children();
5314 // inherit material properties
5315 subcells[i]->set_material_id(cell->material_id());
5316 subcells[i]->set_manifold_id(cell->manifold_id());
5317 subcells[i]->set_subdomain_id(subdomainid);
5318
5319 // We only store the parent for every second cell. That's because
5320 // cells are created during refinement in multiples of two, and so
5321 // two successive cells always share the same parent. As a
5322 // consequence, we can save a bit of work by skipping setting parent
5323 // indices for the odd children.
5324 if (i % 2 == 0)
5325 subcells[i]->set_parent(cell->index());
5326 }
5327
5328
5329
5330 // set child index for even children i=0,2 (0)
5331 for (unsigned int i = 0; i < n_children / 2; ++i)
5332 cell->set_children(2 * i, subcells[2 * i]->index());
5333 // set the refine case
5334 cell->set_refinement_case(ref_case);
5335
5336 // note that the
5337 // refinement flag was
5338 // already cleared at the
5339 // beginning of this function
5340
5341 if (dim == spacedim - 1)
5342 for (unsigned int c = 0; c < n_children; ++c)
5343 cell->child(c)->set_direction_flag(cell->direction_flag());
5344 }
5345
5346
5347
5348 template <int spacedim>
5351 Triangulation<1, spacedim> & /*triangulation*/,
5352 const bool /*check_for_distorted_cells*/)
5353 {
5355 }
5356
5357
5358
5359 template <int spacedim>
5362 const bool check_for_distorted_cells)
5363 {
5364 constexpr int dim = 2;
5365
5366 // Check whether a new level is needed. We have to check for
5367 // this on the highest level only
5368 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5369 triangulation.levels.size() - 1))
5370 if (cell->refine_flag_set())
5371 {
5372 triangulation.levels.push_back(
5373 std::make_unique<internal::TriangulationImplementation::
5375 triangulation.strides.max_children_per_cell,
5376 triangulation.strides.max_faces_per_cell,
5377 triangulation.strides.max_vertices_per_cell));
5378 break;
5379 }
5380
5382 triangulation.begin_line();
5383 line != triangulation.end_line();
5384 ++line)
5385 {
5386 line->clear_user_flag();
5387 line->clear_user_data();
5388 }
5389
5390 unsigned int n_single_lines = 0;
5391 unsigned int n_lines_in_pairs = 0;
5392 unsigned int needed_vertices = 0;
5393
5394 const bool orientation_needed =
5395 !triangulation.all_reference_cells_are_hyper_cube();
5396
5397 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
5398 --level_no)
5399 {
5400 // count number of flagged cells on this level and compute
5401 // how many new vertices and new lines will be needed
5402 std::size_t needed_cells = 0;
5403
5404 for (const auto &cell :
5405 triangulation.active_cell_iterators_on_level(level_no))
5406 if (cell->refine_flag_set())
5407 {
5409 {
5410 needed_cells += 4;
5411 needed_vertices += 0;
5412 n_single_lines += 3;
5413 }
5414 else if (cell->reference_cell() ==
5416 {
5417 needed_cells += 4;
5418 needed_vertices += 1;
5419 n_single_lines += 4;
5420 }
5421 else
5422 {
5424 }
5425
5426 for (const auto line_no : cell->face_indices())
5427 {
5428 auto line = cell->line(line_no);
5429 if (line->has_children() == false)
5430 line->set_user_flag();
5431 }
5432 }
5433
5434 // count number of used cells on the next higher level
5435 auto &next_level = *triangulation.levels[level_no + 1];
5436 const auto used_cells = std::count(next_level.cells.used.begin(),
5437 next_level.cells.used.end(),
5438 true);
5439
5440 if (used_cells + needed_cells > next_level.size())
5441 next_level.allocate_end((used_cells + needed_cells) -
5442 next_level.size(),
5443 orientation_needed,
5444 // We are in 2d so there are no tetrahedra
5445 false);
5446
5447 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
5448 next_level.cells.allocate_end(needed_cells, 0);
5449 }
5450
5451 for (auto line = triangulation.begin_line();
5452 line != triangulation.end_line();
5453 ++line)
5454 if (line->user_flag_set())
5455 {
5456 Assert(line->has_children() == false, ExcInternalError());
5457 n_lines_in_pairs += 2;
5458 needed_vertices += 1;
5459 }
5460
5461 triangulation.faces->lines.allocate_end(n_lines_in_pairs, 0);
5462
5463 needed_vertices += std::count(triangulation.vertices_used.begin(),
5464 triangulation.vertices_used.end(),
5465 true);
5466
5467 if (needed_vertices > triangulation.vertices.size())
5468 {
5469 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5470 triangulation.vertices_used.resize(needed_vertices, false);
5471 }
5472
5473 unsigned int next_unused_vertex = 0;
5474
5475 {
5477 line = triangulation.begin_active_line(),
5478 endl = triangulation.end_line();
5480 next_unused_line = triangulation.begin_raw_line();
5481
5482 for (; line != endl; ++line)
5483 if (line->user_flag_set())
5484 {
5485 // This line needs to be refined. Find the next unused vertex
5486 // and set it appropriately
5487 while (triangulation.vertices_used[next_unused_vertex] == true)
5488 ++next_unused_vertex;
5489 Assert(next_unused_vertex < triangulation.vertices.size(),
5490 ExcMessage(
5491 "Internal error: During refinement, the triangulation "
5492 "wants to access an element of the 'vertices' array "
5493 "but it turns out that the array is not large "
5494 "enough."));
5495 triangulation.vertices_used[next_unused_vertex] = true;
5496
5497 triangulation.vertices[next_unused_vertex] = line->center(true);
5498
5499 bool pair_found = false;
5500 for (; next_unused_line != endl; ++next_unused_line)
5501 if (!next_unused_line->used() &&
5502 !(++next_unused_line)->used())
5503 {
5504 --next_unused_line;
5505 pair_found = true;
5506 break;
5507 }
5508 Assert(pair_found, ExcInternalError());
5509
5510 line->set_children(0, next_unused_line->index());
5511
5513 children[2] = {next_unused_line, ++next_unused_line};
5514
5515 AssertIsNotUsed(children[0]);
5516 AssertIsNotUsed(children[1]);
5517
5518 children[0]->set_bounding_object_indices(
5519 {line->vertex_index(0), next_unused_vertex});
5520 children[1]->set_bounding_object_indices(
5521 {next_unused_vertex, line->vertex_index(1)});
5522
5523 for (auto &child : children)
5524 {
5525 child->set_used_flag();
5526 child->clear_children();
5527 child->clear_user_data();
5528 child->clear_user_flag();
5529 child->set_boundary_id_internal(line->boundary_id());
5530 child->set_manifold_id(line->manifold_id());
5531 // Line orientation is relative to the cell it is on so
5532 // those cannot be set at this point.
5533 }
5534
5535 line->clear_user_flag();
5536 }
5537 }
5538
5539 triangulation.faces->lines.allocate_end(0, n_single_lines);
5540
5541
5543 cells_with_distorted_children;
5544
5546 next_unused_line = triangulation.begin_raw_line();
5547
5548 const auto create_children = [](auto &triangulation,
5549 unsigned int &next_unused_vertex,
5550 auto &next_unused_line,
5551 auto &next_unused_cell,
5552 const auto &cell) {
5553 const auto ref_case = cell->refine_flag_set();
5554 cell->clear_refine_flag();
5555
5556 unsigned int n_new_vertices = 0;
5558 n_new_vertices = 6;
5560 n_new_vertices = 9;
5561 else
5563
5565 n_new_vertices, numbers::invalid_unsigned_int);
5566 for (unsigned int vertex_no = 0; vertex_no < cell->n_vertices();
5567 ++vertex_no)
5568 new_vertices[vertex_no] = cell->vertex_index(vertex_no);
5569 for (unsigned int line_no = 0; line_no < cell->n_lines(); ++line_no)
5570 if (cell->line(line_no)->has_children())
5571 new_vertices[cell->n_vertices() + line_no] =
5572 cell->line(line_no)->child(0)->vertex_index(1);
5573
5575 {
5576 while (triangulation.vertices_used[next_unused_vertex] == true)
5577 ++next_unused_vertex;
5578 Assert(
5579 next_unused_vertex < triangulation.vertices.size(),
5580 ExcMessage(
5581 "Internal error: During refinement, the triangulation wants "
5582 "to access an element of the 'vertices' array but it turns "
5583 "out that the array is not large enough."));
5584 triangulation.vertices_used[next_unused_vertex] = true;
5585
5586 new_vertices[8] = next_unused_vertex;
5587
5588 triangulation.vertices[next_unused_vertex] =
5589 cell->center(true, true);
5590 }
5591
5592 std::array<typename Triangulation<dim, spacedim>::raw_line_iterator,
5593 12>
5594 new_lines;
5595 std::array<types::geometric_orientation, 12> inherited_orientations;
5596 inherited_orientations.fill(numbers::default_geometric_orientation);
5597 unsigned int lmin = 0;
5598 unsigned int lmax = 0;
5599
5601 {
5602 lmin = 6;
5603 lmax = 9;
5604 // For triangles, the innermost faces are always reversed for the
5605 // first three children and are in the standard orientation for
5606 // the last one.
5607 std::fill(inherited_orientations.begin() + lmin,
5608 inherited_orientations.begin() + lmax,
5610 }
5612 {
5613 lmin = 8;
5614 lmax = 12;
5615 }
5616 else
5617 {
5619 }
5620
5621 for (unsigned int l = lmin; l < lmax; ++l)
5622 {
5623 while (next_unused_line->used() == true)
5624 ++next_unused_line;
5625 new_lines[l] = next_unused_line;
5626 ++next_unused_line;
5627
5628 AssertIsNotUsed(new_lines[l]);
5629 }
5630
5631 // set up lines which have parents:
5632 for (const unsigned int face_no : cell->face_indices())
5633 {
5634 // Check the face (line) orientation to ensure that the (six or
5635 // eight) outer lines in new_lines are indexed in the default
5636 // orientation. This way we can index into this array in the
5637 // without special casing orientations (e.g., quadrilateral child
5638 // 3 will always have lines 9, 3, 11, 7) when setting child lines.
5639 const auto combined_orientation =
5640 cell->combined_face_orientation(face_no);
5641 Assert(combined_orientation ==
5643 combined_orientation ==
5646 for (unsigned int c = 0; c < 2; ++c)
5647 {
5648 new_lines[2 * face_no + c] = cell->line(face_no)->child(c);
5649 inherited_orientations[2 * face_no + c] =
5650 cell->combined_face_orientation(face_no);
5651 }
5652 if (combined_orientation == numbers::reverse_line_orientation)
5653 std::swap(new_lines[2 * face_no], new_lines[2 * face_no + 1]);
5654 }
5655
5656 // set up lines which do not have parents:
5658 {
5659 new_lines[6]->set_bounding_object_indices(
5660 {new_vertices[3], new_vertices[4]});
5661 new_lines[7]->set_bounding_object_indices(
5662 {new_vertices[4], new_vertices[5]});
5663 new_lines[8]->set_bounding_object_indices(
5664 {new_vertices[5], new_vertices[3]});
5665 }
5667 {
5668 new_lines[8]->set_bounding_object_indices(
5669 {new_vertices[6], new_vertices[8]});
5670 new_lines[9]->set_bounding_object_indices(
5671 {new_vertices[8], new_vertices[7]});
5672 new_lines[10]->set_bounding_object_indices(
5673 {new_vertices[4], new_vertices[8]});
5674 new_lines[11]->set_bounding_object_indices(
5675 {new_vertices[8], new_vertices[5]});
5676 }
5677 else
5678 {
5680 }
5681
5682 for (unsigned int l = lmin; l < lmax; ++l)
5683 {
5684 new_lines[l]->set_used_flag();
5685 new_lines[l]->clear_user_flag();
5686 new_lines[l]->clear_user_data();
5687 new_lines[l]->clear_children();
5688 // new lines are always internal.
5689 new_lines[l]->set_boundary_id_internal(
5691 new_lines[l]->set_manifold_id(cell->manifold_id());
5692 }
5693
5696 while (next_unused_cell->used() == true)
5697 ++next_unused_cell;
5698
5699 unsigned int n_children = 0;
5701 n_children = 4;
5703 n_children = 4;
5704 else
5706
5707 for (unsigned int i = 0; i < n_children; ++i)
5708 {
5709 AssertIsNotUsed(next_unused_cell);
5710 subcells[i] = next_unused_cell;
5711 ++next_unused_cell;
5712 if (i % 2 == 1 && i < n_children - 1)
5713 while (next_unused_cell->used() == true)
5714 ++next_unused_cell;
5715 }
5716
5717 // Assign lines to child cells:
5718 constexpr unsigned int X = numbers::invalid_unsigned_int;
5719 constexpr ::ndarray<unsigned int, 4, 4> tri_child_lines = {
5720 {{{0, 8, 5, X}}, //
5721 {{1, 2, 6, X}}, //
5722 {{7, 3, 4, X}}, //
5723 {{6, 7, 8, X}}}};
5724 constexpr ::ndarray<unsigned int, 4, 4> quad_child_lines = {
5725 {{{0, 8, 4, 10}},
5726 {{8, 2, 5, 11}},
5727 {{1, 9, 10, 6}},
5728 {{9, 3, 11, 7}}}};
5729 // Here and below we assume that child cells have the same reference
5730 // cell type as the parent.
5731 const auto &child_lines =
5733 tri_child_lines :
5734 quad_child_lines;
5735 for (unsigned int i = 0; i < n_children; ++i)
5736 {
5738 subcells[i]->set_bounding_object_indices(
5739 {new_lines[child_lines[i][0]]->index(),
5740 new_lines[child_lines[i][1]]->index(),
5741 new_lines[child_lines[i][2]]->index()});
5742 else
5743 subcells[i]->set_bounding_object_indices(
5744 {new_lines[child_lines[i][0]]->index(),
5745 new_lines[child_lines[i][1]]->index(),
5746 new_lines[child_lines[i][2]]->index(),
5747 new_lines[child_lines[i][3]]->index()});
5748
5749 subcells[i]->set_used_flag();
5750 subcells[i]->clear_refine_flag();
5751 subcells[i]->clear_user_flag();
5752 subcells[i]->clear_user_data();
5753 subcells[i]->clear_children();
5754 // inherit material properties
5755 subcells[i]->set_material_id(cell->material_id());
5756 subcells[i]->set_manifold_id(cell->manifold_id());
5757 subcells[i]->set_subdomain_id(cell->subdomain_id());
5758
5759 triangulation.levels[subcells[i]->level()]
5760 ->reference_cell[subcells[i]->index()] = cell->reference_cell();
5761
5762 // Finally, now that children are marked as used, we can set
5763 // orientation flags (if needed):
5764 if (triangulation.levels[subcells[i]->level()]
5765 ->face_orientations.n_objects() > 0)
5766 for (unsigned int face_no : cell->face_indices())
5767 subcells[i]->set_combined_face_orientation(
5768 face_no, inherited_orientations[child_lines[i][face_no]]);
5769 else
5770 // It should not be possible to inherit a nonstandard
5771 // orientation when orientations are not set up
5772 for (unsigned int face_no : cell->face_indices())
5773 Assert(inherited_orientations[child_lines[i][face_no]] ==
5776
5777 // We only store the parent for every second cell. That's because
5778 // cells are created during refinement in multiples of two, and so
5779 // two successive cells always share the same parent. As a
5780 // consequence, we can save a bit of work by skipping setting
5781 // parent indices for the odd children.
5782 if (i % 2 == 0)
5783 subcells[i]->set_parent(cell->index());
5784 }
5785
5786 // Unlike the same lines on other children, the innermost triangle's
5787 // faces are all in the default orientation:
5789 for (unsigned int face_no : cell->face_indices())
5790 subcells[3]->set_combined_face_orientation(
5792
5793 for (unsigned int i = 0; i < n_children / 2; ++i)
5794 cell->set_children(2 * i, subcells[2 * i]->index());
5795
5796 cell->set_refinement_case(ref_case);
5797
5798 if (dim == spacedim - 1)
5799 for (unsigned int c = 0; c < n_children; ++c)
5800 cell->child(c)->set_direction_flag(cell->direction_flag());
5801 };
5802
5803 for (int level = 0;
5804 level < static_cast<int>(triangulation.levels.size()) - 1;
5805 ++level)
5806 {
5808 next_unused_cell = triangulation.begin_raw(level + 1);
5809
5810 for (const auto &cell :
5811 triangulation.active_cell_iterators_on_level(level))
5812 if (cell->refine_flag_set())
5813 {
5814 create_children(triangulation,
5815 next_unused_vertex,
5816 next_unused_line,
5817 next_unused_cell,
5818 cell);
5819
5821 check_for_distorted_cells &&
5822 has_distorted_children<dim, spacedim>(cell))
5823 cells_with_distorted_children.distorted_cells.push_back(
5824 cell);
5825
5826 triangulation.signals.post_refinement_on_cell(cell);
5827 }
5828 }
5829
5830 return cells_with_distorted_children;
5831 }
5832
5833
5834
5839 template <int spacedim>
5842 const bool /*check_for_distorted_cells*/)
5843 {
5844 const unsigned int dim = 1;
5845
5846 // Check whether a new level is needed. We have to check for
5847 // this on the highest level only
5848 for (const auto &cell : triangulation.active_cell_iterators_on_level(
5849 triangulation.levels.size() - 1))
5850 if (cell->refine_flag_set())
5851 {
5852 triangulation.levels.push_back(
5853 std::make_unique<internal::TriangulationImplementation::
5855 triangulation.strides.max_children_per_cell,
5856 triangulation.strides.max_faces_per_cell,
5857 triangulation.strides.max_vertices_per_cell));
5858 break;
5859 }
5860
5861 // check how much space is needed on every level. We need not
5862 // check the highest level since either - on the highest level
5863 // no cells are flagged for refinement - there are, but
5864 // prepare_refinement added another empty level
5865 std::size_t needed_vertices = 0;
5866 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
5867 --level_no)
5868 {
5869 std::size_t needed_cells = 0;
5870
5871 for (const auto &cell :
5872 triangulation.active_cell_iterators_on_level(level_no))
5873 if (cell->refine_flag_set())
5874 needed_cells += ReferenceCells::Line.n_isotropic_children();
5875
5876 // count number of used cells on the next higher level
5877 auto &next_level = *triangulation.levels[level_no + 1];
5878 const auto used_cells = std::count(next_level.cells.used.begin(),
5879 next_level.cells.used.end(),
5880 true);
5881
5882 if (used_cells + needed_cells > next_level.size())
5883 next_level.allocate_end((used_cells + needed_cells) -
5884 next_level.size(),
5885 // We are in 1d so there are no tetrahedra
5886 // and we do not need the orientation
5887 false,
5888 false);
5889
5890 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
5891 next_level.cells.allocate_end(needed_cells, 0);
5892 needed_vertices += needed_cells / 2;
5893 }
5894
5895 // add to needed vertices how many
5896 // vertices are already in use
5897 needed_vertices += std::count(triangulation.vertices_used.begin(),
5898 triangulation.vertices_used.end(),
5899 true);
5900 // if we need more vertices: create them, if not: leave the
5901 // array as is, since shrinking is not really possible because
5902 // some of the vertices at the end may be in use
5903 if (needed_vertices > triangulation.vertices.size())
5904 {
5905 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
5906 triangulation.vertices_used.resize(needed_vertices, false);
5907 }
5908
5909
5910 // Do REFINEMENT on every level; exclude highest level as
5911 // above
5912
5913 // index of next unused vertex
5914 unsigned int next_unused_vertex = 0;
5915
5916 for (int level = triangulation.levels.size() - 2; level >= 0; --level)
5917 {
5919 next_unused_cell = triangulation.begin_raw(level + 1);
5920
5921 for (const auto &cell :
5922 triangulation.active_cell_iterators_on_level(level))
5923 if (cell->refine_flag_set())
5924 {
5925 // clear refinement flag
5926 cell->clear_refine_flag();
5927
5928 // search for next unused
5929 // vertex
5930 while (triangulation.vertices_used[next_unused_vertex] ==
5931 true)
5932 ++next_unused_vertex;
5933 Assert(
5934 next_unused_vertex < triangulation.vertices.size(),
5935 ExcMessage(
5936 "Internal error: During refinement, the triangulation "
5937 "wants to access an element of the 'vertices' array "
5938 "but it turns out that the array is not large enough."));
5939
5940 // Now we always ask the cell itself where to put
5941 // the new point. The cell in turn will query the
5942 // manifold object internally.
5943 triangulation.vertices[next_unused_vertex] =
5944 cell->center(true);
5945
5946 triangulation.vertices_used[next_unused_vertex] = true;
5947
5948 // search for next two unused cell (++ takes care of
5949 // the end of the vector)
5951 first_child,
5952 second_child;
5953 while (next_unused_cell->used() == true)
5954 ++next_unused_cell;
5955 first_child = next_unused_cell;
5956 first_child->set_used_flag();
5957 first_child->clear_user_data();
5958 ++next_unused_cell;
5959 AssertIsNotUsed(next_unused_cell);
5960 second_child = next_unused_cell;
5961 second_child->set_used_flag();
5962 second_child->clear_user_data();
5963
5964 types::subdomain_id subdomainid = cell->subdomain_id();
5965
5966 // insert first child
5967 cell->set_children(0, first_child->index());
5968 first_child->clear_children();
5969 first_child->set_bounding_object_indices(
5970 {cell->vertex_index(0), next_unused_vertex});
5971 first_child->set_material_id(cell->material_id());
5972 first_child->set_manifold_id(cell->manifold_id());
5973 first_child->set_subdomain_id(subdomainid);
5974 if (dim == spacedim - 1)
5975 first_child->set_direction_flag(cell->direction_flag());
5976
5977 // We only store the parent for every second cell. That's
5978 // because cells are created during refinement in multiples of
5979 // two, and so two successive cells always share the same
5980 // parent. As a consequence, we can save a bit of work by
5981 // skipping setting parent indices for the second child.
5982 first_child->set_parent(cell->index());
5983
5984 // Set manifold id of the right face. Only do this
5985 // on the first child.
5986 first_child->face(1)->set_manifold_id(cell->manifold_id());
5987
5988 // reset neighborship info (refer to
5989 // internal::TriangulationImplementation::TriaLevel for
5990 // details)
5991 first_child->set_neighbor(1, second_child);
5992 if (cell->neighbor(0).state() != IteratorState::valid)
5993 first_child->set_neighbor(0, cell->neighbor(0));
5994 else if (cell->neighbor(0)->is_active())
5995 {
5996 // since the neighbors level is always <=level,
5997 // if the cell is active, then there are no
5998 // cells to the left which may want to know
5999 // about this new child cell.
6000 Assert(cell->neighbor(0)->level() <= cell->level(),
6002 first_child->set_neighbor(0, cell->neighbor(0));
6003 }
6004 else
6005 // left neighbor is refined
6006 {
6007 // set neighbor to cell on same level
6008 const unsigned int nbnb = cell->neighbor_of_neighbor(0);
6009 first_child->set_neighbor(0,
6010 cell->neighbor(0)->child(nbnb));
6011
6012 // reset neighbor info of all right descendant
6013 // of the left neighbor of cell
6015 left_neighbor = cell->neighbor(0);
6016 while (left_neighbor->has_children())
6017 {
6018 left_neighbor = left_neighbor->child(nbnb);
6019 left_neighbor->set_neighbor(nbnb, first_child);
6020 }
6021 }
6022
6023 // insert second child
6024 second_child->clear_children();
6025 second_child->set_bounding_object_indices(
6026 {next_unused_vertex, cell->vertex_index(1)});
6027 second_child->set_neighbor(0, first_child);
6028 second_child->set_material_id(cell->material_id());
6029 second_child->set_manifold_id(cell->manifold_id());
6030 second_child->set_subdomain_id(subdomainid);
6031 if (dim == spacedim - 1)
6032 second_child->set_direction_flag(cell->direction_flag());
6033
6034 if (cell->neighbor(1).state() != IteratorState::valid)
6035 second_child->set_neighbor(1, cell->neighbor(1));
6036 else if (cell->neighbor(1)->is_active())
6037 {
6038 Assert(cell->neighbor(1)->level() <= cell->level(),
6040 second_child->set_neighbor(1, cell->neighbor(1));
6041 }
6042 else
6043 // right neighbor is refined same as above
6044 {
6045 const unsigned int nbnb = cell->neighbor_of_neighbor(1);
6046 second_child->set_neighbor(
6047 1, cell->neighbor(1)->child(nbnb));
6048
6050 right_neighbor = cell->neighbor(1);
6051 while (right_neighbor->has_children())
6052 {
6053 right_neighbor = right_neighbor->child(nbnb);
6054 right_neighbor->set_neighbor(nbnb, second_child);
6055 }
6056 }
6057 // inform all listeners that cell refinement is done
6058 triangulation.signals.post_refinement_on_cell(cell);
6059 }
6060 }
6061
6062 // in 1d, we can not have distorted children unless the parent
6063 // was already distorted (that is because we don't use
6064 // boundary information for 1d triangulations). so return an
6065 // empty list
6067 }
6068
6069
6074 template <int spacedim>
6077 const bool check_for_distorted_cells)
6078 {
6079 const unsigned int dim = 2;
6080
6081 // First check whether we can get away with isotropic refinement, or
6082 // whether we need to run through the full anisotropic algorithm
6083 {
6084 bool do_isotropic_refinement = true;
6085 for (const auto &cell : triangulation.active_cell_iterators())
6088 {
6089 do_isotropic_refinement = false;
6090 break;
6091 }
6092
6093 if (do_isotropic_refinement)
6094 return execute_refinement_isotropic(triangulation,
6095 check_for_distorted_cells);
6096 }
6097
6098 // If we get here, we are doing anisotropic refinement.
6099
6100 // Check whether a new level is needed. We have to check for
6101 // this on the highest level only
6102 for (const auto &cell : triangulation.active_cell_iterators_on_level(
6103 triangulation.levels.size() - 1))
6104 if (cell->refine_flag_set())
6105 {
6106 triangulation.levels.push_back(
6107 std::make_unique<internal::TriangulationImplementation::
6109 triangulation.strides.max_children_per_cell,
6110 triangulation.strides.max_faces_per_cell,
6111 triangulation.strides.max_vertices_per_cell));
6112 break;
6113 }
6114
6115 // TODO[WB]: we clear user flags and pointers of lines; we're going
6116 // to use them to flag which lines need refinement
6118 triangulation.begin_line();
6119 line != triangulation.end_line();
6120 ++line)
6121 {
6122 line->clear_user_flag();
6123 line->clear_user_data();
6124 }
6125
6126 // running over all cells and lines count the number
6127 // n_single_lines of lines which can be stored as single
6128 // lines, e.g. inner lines
6129 unsigned int n_single_lines = 0;
6130
6131 // New lines to be created: number lines which are stored in
6132 // pairs (the children of lines must be stored in pairs)
6133 unsigned int n_lines_in_pairs = 0;
6134
6135 // check how much space is needed on every level. We need not
6136 // check the highest level since either - on the highest level
6137 // no cells are flagged for refinement - there are, but
6138 // prepare_refinement added another empty level
6139 unsigned int needed_vertices = 0;
6140
6141 const bool orientation_needed =
6142 !triangulation.all_reference_cells_are_hyper_cube();
6143
6144 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
6145 --level_no)
6146 {
6147 // count number of flagged cells on this level and compute
6148 // how many new vertices and new lines will be needed
6149 std::size_t needed_cells = 0;
6150
6151 for (const auto &cell :
6152 triangulation.active_cell_iterators_on_level(level_no))
6153 if (cell->refine_flag_set())
6154 {
6155 Assert(cell->reference_cell().is_hyper_cube(),
6158 {
6159 needed_cells += 4;
6160
6161 // new vertex at center of cell is needed in any
6162 // case
6163 ++needed_vertices;
6164
6165 // the four inner lines can be stored as singles
6166 n_single_lines += 4;
6167 }
6168 else // cut_x || cut_y
6169 {
6170 // set the flag showing that anisotropic
6171 // refinement is used for at least one cell
6172 triangulation.anisotropic_refinement = true;
6173
6174 needed_cells += 2;
6175 // no vertex at center
6176
6177 // the inner line can be stored as single
6178 n_single_lines += 1;
6179 }
6180
6181 // mark all faces (lines) for refinement; checking
6182 // locally whether the neighbor would also like to
6183 // refine them is rather difficult for lines so we
6184 // only flag them and after visiting all cells, we
6185 // decide which lines need refinement;
6186 for (const unsigned int line_no :
6188 {
6190 cell->refine_flag_set(), line_no) ==
6192 {
6194 line = cell->line(line_no);
6195 if (line->has_children() == false)
6196 line->set_user_flag();
6197 }
6198 }
6199 }
6200
6201 auto &next_level = *triangulation.levels[level_no + 1];
6202 const auto used_cells = std::count(next_level.cells.used.begin(),
6203 next_level.cells.used.end(),
6204 true);
6205 if (used_cells + needed_cells > next_level.size())
6206 next_level.allocate_end((used_cells + needed_cells) -
6207 next_level.size(),
6208 orientation_needed,
6209 // We are in 2d so there are no tetrahedra
6210 false);
6211
6212 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
6213 next_level.cells.allocate_end(needed_cells, 0);
6214 }
6215
6216 // now count the lines which were flagged for refinement
6218 triangulation.begin_line();
6219 line != triangulation.end_line();
6220 ++line)
6221 if (line->user_flag_set())
6222 {
6223 Assert(line->has_children() == false, ExcInternalError());
6224 n_lines_in_pairs += 2;
6225 needed_vertices += 1;
6226 }
6227 // reserve space for n_lines_in_pairs new lines. note, that
6228 // we can't reserve space for the single lines here as well,
6229 // as all the space reserved for lines in pairs would be
6230 // counted as unused and we would end up with too little space
6231 // to store all lines. memory reservation for n_single_lines
6232 // can only be done AFTER we refined the lines of the current
6233 // cells
6234 triangulation.faces->lines.allocate_end(n_lines_in_pairs, 0);
6235
6236 // add to needed vertices how many vertices are already in use
6237 needed_vertices += std::count(triangulation.vertices_used.begin(),
6238 triangulation.vertices_used.end(),
6239 true);
6240 // if we need more vertices: create them, if not: leave the
6241 // array as is, since shrinking is not really possible because
6242 // some of the vertices at the end may be in use
6243 if (needed_vertices > triangulation.vertices.size())
6244 {
6245 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6246 triangulation.vertices_used.resize(needed_vertices, false);
6247 }
6248
6249
6250 // Do REFINEMENT on every level; exclude highest level as
6251 // above
6252
6253 // index of next unused vertex
6254 unsigned int next_unused_vertex = 0;
6255
6256 // first the refinement of lines. children are stored
6257 // pairwise
6258 {
6259 // only active objects can be refined further
6261 line = triangulation.begin_active_line(),
6262 endl = triangulation.end_line();
6264 next_unused_line = triangulation.begin_raw_line();
6265
6266 for (; line != endl; ++line)
6267 if (line->user_flag_set())
6268 {
6269 // this line needs to be refined
6270
6271 // find the next unused vertex and set it
6272 // appropriately
6273 while (triangulation.vertices_used[next_unused_vertex] == true)
6274 ++next_unused_vertex;
6275 Assert(
6276 next_unused_vertex < triangulation.vertices.size(),
6277 ExcMessage(
6278 "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."));
6279 triangulation.vertices_used[next_unused_vertex] = true;
6280
6281 triangulation.vertices[next_unused_vertex] = 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
6306 children[2] = {next_unused_line, ++next_unused_line};
6307 // some tests; if any of the iterators should be
6308 // invalid, then already dereferencing will fail
6309 AssertIsNotUsed(children[0]);
6310 AssertIsNotUsed(children[1]);
6311
6312 children[0]->set_bounding_object_indices(
6313 {line->vertex_index(0), next_unused_vertex});
6314 children[1]->set_bounding_object_indices(
6315 {next_unused_vertex, line->vertex_index(1)});
6316
6317 children[0]->set_used_flag();
6318 children[1]->set_used_flag();
6319 children[0]->clear_children();
6320 children[1]->clear_children();
6321 children[0]->clear_user_data();
6322 children[1]->clear_user_data();
6323 children[0]->clear_user_flag();
6324 children[1]->clear_user_flag();
6325
6326
6327 children[0]->set_boundary_id_internal(line->boundary_id());
6328 children[1]->set_boundary_id_internal(line->boundary_id());
6329
6330 children[0]->set_manifold_id(line->manifold_id());
6331 children[1]->set_manifold_id(line->manifold_id());
6332
6333 // finally clear flag indicating the need for
6334 // refinement
6335 line->clear_user_flag();
6336 }
6337 }
6338
6339
6340 // Now set up the new cells
6341
6342 // reserve space for inner lines (can be stored as single
6343 // lines)
6344 triangulation.faces->lines.allocate_end(0, n_single_lines);
6345
6347 cells_with_distorted_children;
6348
6349 // reset next_unused_line, as now also single empty places in
6350 // the vector can be used
6352 next_unused_line = triangulation.begin_raw_line();
6353
6354 for (int level = 0;
6355 level < static_cast<int>(triangulation.levels.size()) - 1;
6356 ++level)
6357 {
6359 next_unused_cell = triangulation.begin_raw(level + 1);
6360
6361 for (const auto &cell :
6362 triangulation.active_cell_iterators_on_level(level))
6363 if (cell->refine_flag_set())
6364 {
6365 // actually set up the children and update neighbor
6366 // information
6367 create_children(triangulation,
6368 next_unused_vertex,
6369 next_unused_line,
6370 next_unused_cell,
6371 cell);
6372
6373 if (check_for_distorted_cells &&
6374 has_distorted_children<dim, spacedim>(cell))
6375 cells_with_distorted_children.distorted_cells.push_back(
6376 cell);
6377 // inform all listeners that cell refinement is done
6378 triangulation.signals.post_refinement_on_cell(cell);
6379 }
6380 }
6381
6382 return cells_with_distorted_children;
6383 }
6384
6385
6386 template <int spacedim>
6389 const bool check_for_distorted_cells)
6390 {
6391 constexpr int dim = 3;
6392 constexpr unsigned int X = numbers::invalid_unsigned_int;
6393 using raw_line_iterator =
6395 using raw_quad_iterator =
6397
6398 Assert(spacedim == 3, ExcNotImplemented());
6399
6400 Assert(triangulation.vertices.size() ==
6401 triangulation.vertices_used.size(),
6403
6404 // Check whether a new level is needed. We have to check for
6405 // this on the highest level only
6406 for (const auto &cell : triangulation.active_cell_iterators_on_level(
6407 triangulation.levels.size() - 1))
6408 if (cell->refine_flag_set())
6409 {
6411 triangulation.levels.size() < numbers::max_n_levels,
6413 triangulation.levels.push_back(
6414 std::make_unique<internal::TriangulationImplementation::
6416 triangulation.strides.max_children_per_cell,
6417 triangulation.strides.max_faces_per_cell,
6418 triangulation.strides.max_vertices_per_cell));
6419 break;
6420 }
6421
6422 // first clear user flags for quads and lines; we're going to
6423 // use them to flag which lines and quads need refinement
6424 triangulation.faces->quads.clear_user_data();
6425 triangulation.faces->lines.clear_user_flags();
6426 triangulation.faces->quads.clear_user_flags();
6427
6428 // check how much space is needed on every level. We need not
6429 // check the highest level since either
6430 // - on the highest level no cells are flagged for refinement
6431 // - there are, but prepare_refinement added another empty
6432 // level which then is the highest level
6433
6434 // Variables to hold the number of newly to be created
6435 // vertices, lines, and faces. As these are stored globally,
6436 // declare them outside the loop over all levels. We need lines
6437 // and faces in pairs for refinement of old lines/face. And lines and
6438 // faces stored individually for the ones created in the interior
6439 // of an existing cell
6440 { // STORAGE
6441 unsigned int needed_vertices = 0;
6442 unsigned int needed_lines_single = 0;
6443 unsigned int needed_faces_single = 0;
6444 unsigned int needed_lines_pair = 0;
6445 unsigned int needed_faces_pair = 0;
6446 for (int level_no = triangulation.levels.size() - 2; level_no >= 0;
6447 --level_no)
6448 {
6449 std::size_t needed_cells = 0;
6450
6451 for (const auto &cell :
6452 triangulation.active_cell_iterators_on_level(level_no))
6453 if (cell->refine_flag_set())
6454 {
6455 // Only support isotropic refinement
6456 Assert(cell->refine_flag_set() ==
6459
6460 // get reference cell type of current cell
6461 const auto cell_reference_cell = cell->reference_cell();
6462
6463 // Now count up how many new cells, faces, edges, and
6464 // vertices we will need to allocate to do this refinement.
6465 needed_cells += cell_reference_cell.n_isotropic_children();
6466
6467 switch (cell_reference_cell)
6468 {
6470 needed_lines_single += 1;
6471 needed_faces_single += 8;
6472 break;
6473
6475 // TODO: Pyramid
6476 // - No vertices (all provided by face refinement)
6477 // - 5 faces for center pyramid
6478 // - 4 times 2 for the remaining tets
6479 needed_lines_single += 4;
6480 needed_faces_single += 13;
6481 break;
6482
6484 // - We won't need vertices (all required vertices
6485 // will be provided by the refined faces)
6486 // - 3 lines will be required to build up the
6487 // "refined" middle triangle
6488 // - 4 faces for the new refined middle triangle + 6
6489 // faces for the quads building the wedges in
6490 // z-direction. Rest will be provided via refinement
6491 // of faces. Store them all as singles. See also
6492 // https://link.springer.com/article/10.1007/BF01221213
6493 needed_lines_single += 3;
6494 needed_faces_single += 10;
6495 break;
6496
6498 // One vertex in the center of the parent
6499 ++needed_vertices;
6500 needed_lines_single += 6;
6501 needed_faces_single += 12;
6502 break;
6503
6504 default:
6506 }
6507
6508 // Also check whether we have to refine any of the faces and
6509 // edges that bound this cell. They may of course already be
6510 // refined, so we only *mark* them for refinement by setting
6511 // the user flags
6512
6513 // Faces
6514 for (const auto face : cell->face_indices())
6515 if (cell->face(face)->n_children() == 0)
6516 cell->face(face)->set_user_flag();
6517 else
6518 // Check that the child of the cell has enough children
6519 Assert(cell->face(face)->n_children() ==
6520 cell_reference_cell.face_reference_cell(face)
6521 .n_isotropic_children(),
6523
6524 // Edges
6525 for (const auto line : cell->line_indices())
6526 if (cell->line(line)->has_children() == false)
6527 cell->line(line)->set_user_flag();
6528 else
6529 Assert(cell->line(line)->n_children() == 2,
6531 }
6532
6533 auto &next_level = *triangulation.levels[level_no + 1];
6534 const auto used_cells = std::count(next_level.cells.used.begin(),
6535 next_level.cells.used.end(),
6536 true);
6537 if (used_cells + needed_cells > next_level.size())
6538 next_level.allocate_end(
6539 (used_cells + needed_cells) - next_level.size(),
6540 // We unconditionally store the orientation in 3d
6541 true,
6542 // TODO: we can get rid of this check (i.e., we don't need to
6543 // store this value for purely wedge meshes). This will be
6544 // simpler to do once we merge IsotropicRefinementChoice and
6545 // RefinementCase.
6546 !triangulation.all_reference_cells_are_hyper_cube());
6547
6548 // TODO: perhaps we can merge this with TriaLevel::allocate_end()
6549 next_level.cells.allocate_end(needed_cells, 0);
6550 }
6551
6552 // now count the faces and lines which were flagged for
6553 // refinement
6555 triangulation.begin_quad();
6556 quad != triangulation.end_quad();
6557 ++quad)
6558 {
6559 if (quad->user_flag_set() == false)
6560 continue;
6561
6562 if (quad->reference_cell() == ReferenceCells::Quadrilateral)
6563 {
6564 needed_faces_pair += 4;
6565 needed_lines_pair += 4;
6566 needed_vertices += 1;
6567 }
6568 else if (quad->reference_cell() == ReferenceCells::Triangle)
6569 {
6570 needed_faces_pair += 4;
6571 needed_lines_single += 3;
6572 }
6573 else
6574 {
6576 }
6577 }
6578
6580 triangulation.begin_line();
6581 line != triangulation.end_line();
6582 ++line)
6583 {
6584 if (line->user_flag_set() == false)
6585 continue;
6586
6587 needed_lines_pair += 2;
6588 needed_vertices += 1;
6589 }
6590
6591 triangulation.faces->allocate_end(needed_faces_pair,
6592 needed_faces_single);
6593 triangulation.faces->lines.allocate_end(needed_lines_pair,
6594 needed_lines_single);
6595
6596 // add to needed vertices how many vertices are already in use
6597 needed_vertices += std::count(triangulation.vertices_used.begin(),
6598 triangulation.vertices_used.end(),
6599 true);
6600
6601 if (needed_vertices > triangulation.vertices.size())
6602 {
6603 triangulation.vertices.resize(needed_vertices, Point<spacedim>());
6604 triangulation.vertices_used.resize(needed_vertices, false);
6605 }
6606 } // STORAGE
6607
6608 //-----------------------------------------
6609 // Before we start with the actual refinement, we do some
6610 // sanity checks if in debug mode. especially, we try to catch
6611 // the notorious problem with lines being twice refined,
6612 // i.e. there are cells adjacent at one line ("around the
6613 // edge", but not at a face), with two cells differing by more
6614 // than one refinement level
6615 //
6616 // this check is very simple to implement here, since we have
6617 // all lines flagged if they shall be refined
6618 if constexpr (running_in_debug_mode())
6619 {
6620 for (const auto &cell : triangulation.active_cell_iterators())
6621 if (!cell->refine_flag_set())
6622 for (unsigned int line_n = 0; line_n < cell->n_lines();
6623 ++line_n)
6624 if (cell->line(line_n)->has_children())
6625 for (unsigned int c = 0; c < 2; ++c)
6626 Assert(cell->line(line_n)->child(c)->user_flag_set() ==
6627 false,
6629 }
6630
6631 unsigned int current_vertex = 0;
6632
6633 // helper function - find the next available vertex number and mark it
6634 // as used.
6635 auto get_next_unused_vertex = [](const unsigned int current_vertex,
6636 std::vector<bool> &vertices_used) {
6637 unsigned int next_vertex = current_vertex;
6638 while (next_vertex < vertices_used.size() &&
6639 vertices_used[next_vertex] == true)
6640 ++next_vertex;
6641 Assert(next_vertex < vertices_used.size(), ExcInternalError());
6642 vertices_used[next_vertex] = true;
6643
6644 return next_vertex;
6645 };
6646
6647
6648 { // LINES
6650 line = triangulation.begin_active_line(),
6651 endl = triangulation.end_line();
6652 raw_line_iterator next_unused_line = triangulation.begin_raw_line();
6653
6654 for (; line != endl; ++line)
6655 {
6656 if (line->user_flag_set() == false)
6657 continue;
6658
6659 next_unused_line =
6660 triangulation.faces->lines.template next_free_pair_object<1>(
6661 triangulation);
6662 Assert(next_unused_line.state() == IteratorState::valid,
6664
6665 // now we found two consecutive unused lines, such
6666 // that the children of a line will be consecutive.
6667 // then set the child pointer of the present line
6668 line->set_children(0, next_unused_line->index());
6669
6670 const std::array<raw_line_iterator, 2> children{
6671 {next_unused_line, ++next_unused_line}};
6672
6673 AssertIsNotUsed(children[0]);
6674 AssertIsNotUsed(children[1]);
6675
6676 current_vertex =
6677 get_next_unused_vertex(current_vertex,
6678 triangulation.vertices_used);
6679 triangulation.vertices[current_vertex] = line->center(true);
6680
6681 children[0]->set_bounding_object_indices(
6682 {line->vertex_index(0), current_vertex});
6683 children[1]->set_bounding_object_indices(
6684 {current_vertex, line->vertex_index(1)});
6685
6686 const auto manifold_id = line->manifold_id();
6687 const auto boundary_id = line->boundary_id();
6688 for (const auto &child : children)
6689 {
6690 child->set_used_flag();
6691 child->clear_children();
6692 child->clear_user_data();
6693 child->clear_user_flag();
6694 child->set_boundary_id_internal(boundary_id);
6695 child->set_manifold_id(manifold_id);
6696 }
6697
6698 line->clear_user_flag();
6699 }
6700 }
6701
6702 { // FACES
6703 // (i.e., quads or triangles, or both)
6705 face = triangulation.begin_face(),
6706 endf = triangulation.end_face();
6707
6708 for (; face != endf; ++face)
6709 {
6710 if (face->user_flag_set() == false)
6711 continue;
6712
6713 const auto reference_face_type = face->reference_cell();
6714
6715 // 1) Create new lines (property is set later).
6716 // Maximum of 4 new lines (4 quadrilateral, 3 triangle).
6717 std::array<raw_line_iterator, 4> new_lines;
6718 switch (reference_face_type)
6719 {
6721 for (unsigned int l = 0; l < 3; ++l)
6722 new_lines[l] =
6723 triangulation.faces->lines
6724 .template next_free_single_object<1>(triangulation);
6725 break;
6726
6728 for (unsigned int l = 0; l < 2; ++l)
6729 {
6730 auto next_unused_line =
6731 triangulation.faces->lines
6732 .template next_free_pair_object<1>(triangulation);
6733 new_lines[2 * l] = next_unused_line;
6734 new_lines[2 * l + 1] = ++next_unused_line;
6735 }
6736 break;
6737
6738 default:
6740 }
6741
6742 if constexpr (running_in_debug_mode())
6743 {
6744 for (const unsigned int line : face->line_indices())
6745 AssertIsNotUsed(new_lines[line]);
6746 }
6747
6748 // 2) Create new face (properties are set below).
6749 // Both triangles and quads are divided in four. (For historical
6750 // reasons, we only have `raw_quad_iterator`, not
6751 // `raw_face_iterator`, but the former also works if a face is
6752 // actually a triangle.)
6753 std::array<raw_quad_iterator, 4> new_faces;
6754 for (unsigned int f = 0; f < 2; ++f)
6755 {
6756 auto next_unused_quad =
6757 triangulation.faces->quads
6758 .template next_free_pair_object<2>(triangulation);
6759
6760 new_faces[2 * f] = next_unused_quad;
6761 new_faces[2 * f + 1] = ++next_unused_quad;
6762
6763 face->set_children(2 * f, new_faces[2 * f]->index());
6764 }
6765 // Tell the original face that is has been isotropically refined.
6766 face->set_refinement_case(RefinementCase<2>::cut_xy);
6767
6768 if constexpr (running_in_debug_mode())
6769 {
6770 for (const auto &quad : new_faces)
6771 AssertIsNotUsed(quad);
6772 }
6773
6774 // 3) Create an ordered list of vertices.
6775 // The order is determined by the physical position of the
6776 // vertices within the face reference cell, enabling easy
6777 // identification/lookup by the vertex's index in this list.
6778 // Additionally the center vertex required for quadrilaterals is
6779 // created.
6780
6781 // Maximum of 9 vertices per refined face (9 for Quadrilateral, 6
6782 // for Triangle)
6783 std::array<unsigned int, 9> vertex_indices = {};
6784 unsigned int k = 0;
6785 for (const auto i : face->vertex_indices())
6786 vertex_indices[k++] = face->vertex_index(i);
6787
6788 for (const auto i : face->line_indices())
6789 vertex_indices[k++] = face->line(i)->child(0)->vertex_index(1);
6790
6791 if (reference_face_type == ReferenceCells::Quadrilateral)
6792 {
6793 current_vertex =
6794 get_next_unused_vertex(current_vertex,
6795 triangulation.vertices_used);
6796 vertex_indices[k++] = current_vertex;
6797
6798 triangulation.vertices[current_vertex] =
6799 face->center(true, true);
6800 }
6801
6802 // 4) Set new lines on these faces and their properties.
6803 // 'magic numbers' in `line_vertices_X` are indices in the list
6804 // created in step 3).
6805 std::array<raw_line_iterator, 12> lines;
6806 unsigned int n_lines = 0;
6807 for (unsigned int l = 0; l < face->n_lines(); ++l)
6808 for (unsigned int c = 0; c < 2; ++c)
6809 lines[n_lines++] = face->line(l)->child(
6810 child_line_index(c, face->line_orientation(l)));
6811
6812 for (unsigned int l = 0; l < face->n_lines(); ++l)
6813 lines[n_lines++] = new_lines[l];
6814
6815 std::array<int, 12> line_indices;
6816 for (unsigned int i = 0; i < n_lines; ++i)
6817 line_indices[i] = lines[i]->index();
6818
6819 // 2---7---3 .-6-.-7-. .---.---.
6820 // | | | 1 9 3 | 2 | 3 |
6821 // 4---8---5 .-10.11-. .---.---.
6822 // | | | 0 8 2 | 0 | 1 |
6823 // 0---6---1 .-4-.-5-. .---.---.
6824 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_quad{
6825 {{{0, 4}},
6826 {{4, 2}},
6827 {{1, 5}},
6828 {{5, 3}},
6829 {{0, 6}},
6830 {{6, 1}},
6831 {{2, 7}},
6832 {{7, 3}},
6833 {{6, 8}},
6834 {{8, 7}},
6835 {{4, 8}},
6836 {{8, 5}}}};
6837
6838 constexpr ::ndarray<unsigned int, 4, 4> quad_lines_quad{
6839 {{{0, 8, 4, 10}},
6840 {{8, 2, 5, 11}},
6841 {{1, 9, 10, 6}},
6842 {{9, 3, 11, 7}}}};
6843
6844 // 2 * * .
6845 // |\ |\ |\ .
6846 // v ^ 4 3 | \ .
6847 // | \ | \ | 2 \ .
6848 // 5--<--4 *--7--* *-----* .
6849 // |\ |\ |\ |\ |\ 3 |\ .
6850 // v ^ ^ ^ 5 8 6 2 | \ | \ .
6851 // | \| \ | \| \ | 0 \| 1 \ .
6852 // 0-->--3-->--1 *--0--*--1--* *-----*-----* .
6853 constexpr ::ndarray<unsigned int, 12, 2> line_vertices_tri{
6854 {{{0, 3}},
6855 {{3, 1}},
6856 {{1, 4}},
6857 {{4, 2}},
6858 {{2, 5}},
6859 {{5, 0}},
6860 {{3, 4}},
6861 {{4, 5}},
6862 {{3, 5}},
6863 {{X, X}},
6864 {{X, X}},
6865 {{X, X}}}};
6866
6867 constexpr ::ndarray<unsigned int, 4, 4> tri_lines_tri{
6868 {{{0, 8, 5, X}},
6869 {{1, 2, 6, X}},
6870 {{7, 3, 4, X}},
6871 {{6, 7, 8, X}}}};
6872
6873 // The defined lines in `line_vertices_tri` do not satisfy the
6874 // expected orientations of all the children's reference cells.
6875 // This table specifies the expected line orientations (i.e.
6876 // vertex order) necessary for `set_line_orientation(...)`.
6877 constexpr ::ndarray<unsigned int, 4, 4, 2>
6878 tri_line_vertices_tri{
6879 {{{{{0, 3}}, {{3, 5}}, {{5, 0}}, {{X, X}}}},
6880 {{{{3, 1}}, {{1, 4}}, {{4, 3}}, {{X, X}}}},
6881 {{{{5, 4}}, {{4, 2}}, {{2, 5}}, {{X, X}}}},
6882 {{{{3, 4}}, {{4, 5}}, {{5, 3}}, {{X, X}}}}}};
6883
6884 // Select lookup table according to reference cell of parent.
6885 const auto &line_vertices =
6886 (reference_face_type == ReferenceCells::Quadrilateral) ?
6887 line_vertices_quad :
6888 line_vertices_tri;
6889 const auto &face_lines =
6890 (reference_face_type == ReferenceCells::Quadrilateral) ?
6891 quad_lines_quad :
6892 tri_lines_tri;
6893
6894 // The first 2*face->n_lines() lines are already created by
6895 // refining the original lines on the face. Therefore, only the
6896 // subsequent face->n_lines() lines need to be processed now.
6897 for (unsigned int i = 0, j = 2 * face->n_lines();
6898 i < face->n_lines();
6899 ++i, ++j)
6900 {
6901 auto &new_line = new_lines[i];
6902 new_line->set_bounding_object_indices(
6903 {vertex_indices[line_vertices[j][0]],
6904 vertex_indices[line_vertices[j][1]]});
6905 new_line->set_used_flag();
6906 new_line->clear_user_flag();
6907 new_line->clear_user_data();
6908 new_line->clear_children();
6909 new_line->set_boundary_id_internal(face->boundary_id());
6910 new_line->set_manifold_id(face->manifold_id());
6911 }
6912
6913 // 5) Set properties of faces
6914 for (unsigned int i = 0; i < new_faces.size(); ++i)
6915 {
6916 // 5.a) Create faces
6917 auto &new_face = new_faces[i];
6918
6919 // We assume here that all children have the same type as the
6920 // parent face.
6921 triangulation.faces->set_quad_type(new_face->index(),
6922 reference_face_type);
6923
6924 switch (reference_face_type)
6925 {
6927 new_face->set_bounding_object_indices(
6928 {line_indices[face_lines[i][0]],
6929 line_indices[face_lines[i][1]],
6930 line_indices[face_lines[i][2]]});
6931 break;
6932
6934 new_face->set_bounding_object_indices(
6935 {line_indices[face_lines[i][0]],
6936 line_indices[face_lines[i][1]],
6937 line_indices[face_lines[i][2]],
6938 line_indices[face_lines[i][3]]});
6939 break;
6940
6941 default:
6943 }
6944
6945 new_face->set_used_flag();
6946 new_face->clear_user_flag();
6947 new_face->clear_user_data();
6948 new_face->clear_children();
6949 new_face->set_boundary_id_internal(face->boundary_id());
6950 new_face->set_manifold_id(face->manifold_id());
6951
6952 [[maybe_unused]] std::set<unsigned int> s;
6953
6954 // 5.b.I) Fix orientation of lines of face
6955 // For triangles an expensive algorithm is used,
6956 // quadrilaterals are treated a few lines below by a cheaper
6957 // algorithm
6958 if (reference_face_type == ReferenceCells::Triangle)
6959 {
6960 for (const auto f : new_face->line_indices())
6961 {
6962 const std::array<unsigned int, 2> vertices_0 = {
6963 {lines[face_lines[i][f]]->vertex_index(0),
6964 lines[face_lines[i][f]]->vertex_index(1)}};
6965
6966 const std::array<unsigned int, 2> vertices_1 = {
6967 {vertex_indices[tri_line_vertices_tri[i][f][0]],
6968 vertex_indices[tri_line_vertices_tri[i][f][1]]}};
6969
6970 const auto orientation =
6971 ReferenceCells::Line.get_combined_orientation(
6972 make_array_view(vertices_0),
6973 make_array_view(vertices_1));
6974
6975 if constexpr (library_build_mode ==
6977 {
6978 for (const auto i : vertices_0)
6979 s.insert(i);
6980 for (const auto i : vertices_1)
6981 s.insert(i);
6982 }
6983
6984 new_face->set_line_orientation(f, orientation);
6985 }
6986 if constexpr (library_build_mode ==
6988 {
6989 AssertDimension(s.size(), 3);
6990 }
6991 }
6992 }
6993
6994 // 5.b.II) Fix orientation of lines of faces for quadrilaterals
6995 // with cheap algorithm.
6996 if (reference_face_type == ReferenceCells::Quadrilateral)
6997 {
6998 constexpr ::ndarray<unsigned int, 4, 2>
6999 quad_child_line_vertices{{{{0, 2}}, //
7000 {{1, 3}}, //
7001 {{0, 1}}, //
7002 {{2, 3}}}};
7003
7004 for (unsigned int i = 0; i < 4; ++i)
7005 for (unsigned int j = 0; j < 2; ++j)
7006 new_faces[quad_child_line_vertices[i][j]]
7007 ->set_line_orientation(i, face->line_orientation(i));
7008 }
7009
7010 face->clear_user_flag();
7011 }
7012 } // FACES
7013
7014 // Cells
7016 cells_with_distorted_children;
7017
7019 triangulation.begin_active(0);
7020 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
7021 ++level)
7022 {
7024 next_unused_cell = triangulation.begin_raw(level + 1);
7025 Assert(cell == triangulation.end() ||
7026 cell->level() >= static_cast<int>(level),
7028
7029 // Iterate over all active cells in the current level
7030 for (; cell != triangulation.end() &&
7031 cell->level() == static_cast<int>(level);
7032 ++cell)
7033 {
7034 if (cell->refine_flag_set() ==
7036 continue;
7037
7038 // Copy the requested refinement case to the cell's actual
7039 // refinement flag, informing the cell how it has been refined.
7040 const RefinementCase<dim> ref_case = cell->refine_flag_set();
7041 cell->clear_refine_flag();
7042 cell->set_refinement_case(ref_case);
7043
7044 const auto cell_reference_cell = cell->reference_cell();
7045
7046 unsigned int n_new_lines = 0;
7047 unsigned int n_new_faces = 0;
7048 const unsigned int n_new_cells =
7049 cell_reference_cell.n_isotropic_children();
7050
7051 // Must match the information used close the beginning of this
7052 // function.
7053 switch (cell_reference_cell)
7054 {
7056 n_new_lines = 1;
7057 n_new_faces = 8;
7058 break;
7059
7061 n_new_lines = 4;
7062 n_new_faces = 13;
7063 break;
7064
7066 n_new_lines = 3;
7067 n_new_faces = 10;
7068 break;
7069
7071 n_new_lines = 6;
7072 n_new_faces = 12;
7073 break;
7074
7075 default:
7077 }
7078
7079 // the following numbers should be the max numbers of the above.
7080 // They are used for sizing of arrays.
7081 constexpr unsigned int max_n_new_lines = 6;
7082 constexpr unsigned int max_n_new_faces = 13;
7083 constexpr unsigned int max_n_new_children = 10;
7084 constexpr unsigned int max_relevant_vertices = 27;
7085 constexpr unsigned int max_relevant_lines = 30;
7086 constexpr unsigned int max_face_indices = 36;
7087
7088 std::array<raw_line_iterator, max_n_new_lines> new_lines;
7089 for (unsigned int i = 0; i < n_new_lines; ++i)
7090 {
7091 new_lines[i] =
7092 triangulation.faces->lines
7093 .template next_free_single_object<1>(triangulation);
7094
7095 AssertIsNotUsed(new_lines[i]);
7096 new_lines[i]->set_used_flag();
7097 new_lines[i]->clear_user_flag();
7098 new_lines[i]->clear_user_data();
7099 new_lines[i]->clear_children();
7100 new_lines[i]->set_boundary_id_internal(
7102 new_lines[i]->set_manifold_id(cell->manifold_id());
7103 }
7104
7105 std::array<raw_quad_iterator, max_n_new_faces> new_faces;
7106 for (unsigned int i = 0; i < n_new_faces; ++i)
7107 {
7108 new_faces[i] =
7109 triangulation.faces->quads
7110 .template next_free_single_object<2>(triangulation);
7111
7112 auto &new_face = new_faces[i];
7113
7114 AssertIsNotUsed(new_face);
7115 new_face->set_used_flag();
7116 new_face->clear_user_flag();
7117 new_face->clear_user_data();
7118 new_face->clear_children();
7119 new_face->set_boundary_id_internal(
7121 new_face->set_manifold_id(cell->manifold_id());
7122
7123 // At this point the face doesn't have its ReferenceCell
7124 // set, so rely on lower-level functionality to reset
7125 // per-line data
7126 for (unsigned int j = 0;
7127 j < triangulation.faces->lines_per_quad;
7128 ++j)
7129 new_face->set_line_orientation(
7131 }
7132
7133
7134 { // CREATE_CELLS
7135 // Build a list of all relevant vertices required for
7136 // - The creation of additional faces not generated by the
7137 // refinement of the parent faces.
7138 // - The definition of the child cells.
7139 //
7140 // Number of meaningful entries in this list is
7141 // 10 Tetrahedron 18 Wedge
7142 // 14 Pyramid 27 Hexahedron
7143 // In case the maximum changes, edit `max_relevant_vertices` a
7144 // few lines above (or in case it was moved to ReferenceCell,
7145 // update it there).
7146 //
7147 // The following algorithm is used to get the vertices.
7148 // 1. Get vertices of the parent as provided.
7149 // https://dealii.org/developer/doxygen/deal.II/group__simplex.html#simplex_reference_cells.
7150 //
7151 // 2. Get the center vertices of the (refined) bounding lines
7152 // of the parent's faces (quad and tet (i.e. all) faces)
7153 //
7154 // .---3---. .
7155 // | | /|
7156 // 0 1 or 2 1
7157 // | | / |
7158 // .---2---. .-0-. n: vertices retrieved
7159 //
7160 // 3. Get the remaining new vertices that were created in the
7161 // center of the parent's bounding faces during refinement
7162 // (quad faces)
7163 //
7164 // .-------.
7165 // | |
7166 // .---O |
7167 // | | |
7168 // .---.---. O: vertex retrieved
7169 //
7170 // 4. Get (or, better yet, create) the newly required
7171 // vertices. (i.e. the new vertex in the middle of a hex,
7172 // only relevant for hexes)
7173 //
7174 // .-------.
7175 // /| |
7176 // . | / |
7177 // | - -O |
7178 // | .--:----.
7179 // |/ : /
7180 // .-------.
7181
7182 std::array<unsigned int, max_relevant_vertices>
7183 vertex_indices = {};
7184
7185 { // GET_VERTICES
7186 // continuous counter variable
7187 unsigned int k = 0;
7188
7189 // avoid a compiler warning by fixing max number of
7190 // iterations to 8.
7191 const unsigned int n_vertices =
7192 std::min(cell->n_vertices(), 8u);
7193
7194 // Step 1 Get vertices of the parent
7195 for (unsigned int i = 0; i < n_vertices; ++i)
7196 vertex_indices[k++] = cell->vertex_index(i);
7197
7198 // Step 2 (relevant for all faces)
7199
7200 // Avoid a compiler warning by fixing the max number of loop
7201 // iterations to 12 (max number of new lines)
7202 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
7203
7204 const std::array<unsigned int, 12> line_indices =
7205 TriaAccessorImplementation::Implementation::
7206 get_line_indices_of_cell(*cell);
7207
7208 for (unsigned int l = 0; l < n_lines; ++l)
7209 {
7210 raw_line_iterator line(&triangulation,
7211 0,
7212 line_indices[l]);
7213 vertex_indices[k++] = line->child(0)->vertex_index(1);
7214 }
7215
7216 // Step 3 (depends on the reference cell type of face, only
7217 // quads affected)
7218 for (auto quad_face_index :
7219 cell_reference_cell.face_indices_by_type(
7221 {
7222 vertex_indices[k++] = cell->face(quad_face_index)
7223 ->child(0)
7224 ->vertex_index(3);
7225 }
7226
7227 // Step 4 Create the center vertex for hex cells
7228 if (cell_reference_cell == ReferenceCells::Hexahedron)
7229 {
7230 // Set single new vertex in the center
7231 current_vertex =
7232 get_next_unused_vertex(current_vertex,
7233 triangulation.vertices_used);
7234 vertex_indices[k++] = current_vertex;
7235
7236 triangulation.vertices[current_vertex] =
7237 cell->center(true, true);
7238 }
7239 } // GET_VERTICES
7240
7241
7242 unsigned int chosen_line_tetrahedron = 0;
7243
7244 // set up new lines
7245 switch (cell_reference_cell)
7246 {
7248 {
7249 // in the tetrahedron case, we have the three
7250 // possibilities (6,8), (5,7), (4,9) -> pick the
7251 // shortest line to guarantee the best possible aspect
7252 // ratios
7253 constexpr ::ndarray<unsigned int, 3, 2>
7254 new_line_vertices = {{{{6, 8}}, //
7255 {{5, 7}}, //
7256 {{4, 9}}}};
7257
7258 // choose line to cut either by refinement case or by
7259 // shortest distance between edge midpoints
7260 std::uint8_t refinement_choice =
7261 cell->refine_choice();
7262 if (refinement_choice ==
7263 static_cast<char>(IsotropicRefinementChoice::
7265 {
7266 const auto &vertices =
7267 triangulation.get_vertices();
7268 double min_distance =
7269 std::numeric_limits<double>::infinity();
7270 for (unsigned int i = 0;
7271 i < new_line_vertices.size();
7272 ++i)
7273 {
7274 const double current_distance =
7275 vertices[vertex_indices
7276 [new_line_vertices[i][0]]]
7277 .distance(
7278 vertices[vertex_indices
7279 [new_line_vertices[i][1]]]);
7280 if (current_distance < min_distance)
7281 {
7282 chosen_line_tetrahedron = i;
7283 min_distance = current_distance;
7284 }
7285 }
7286 }
7287 else if (refinement_choice ==
7288 static_cast<char>(
7290 chosen_line_tetrahedron = 0;
7291 else if (refinement_choice ==
7292 static_cast<char>(
7294 chosen_line_tetrahedron = 1;
7295 else if (refinement_choice ==
7296 static_cast<char>(
7298 chosen_line_tetrahedron = 2;
7299 else
7301
7302 cell->set_refinement_case(
7303 RefinementCase<dim>(chosen_line_tetrahedron + 1));
7304
7305 new_lines[0]->set_bounding_object_indices(
7306 {vertex_indices
7307 [new_line_vertices[chosen_line_tetrahedron][0]],
7308 vertex_indices[new_line_vertices
7309 [chosen_line_tetrahedron][1]]});
7310 }
7311 break;
7312
7314 {
7315 // Directions so that middle bottom pyramids all have
7316 // lines with default orientation. Order as children
7317 // of refined bottom quad.
7318 static constexpr ::ndarray<unsigned int, 4, 2>
7319 new_line_vertices = {{{{13, 9}}, //
7320 {{13, 10}}, //
7321 {{13, 11}}, //
7322 {{13, 12}}}};
7323
7324 for (unsigned int i = 0; i < n_new_lines; ++i)
7325 new_lines[i]->set_bounding_object_indices(
7326 {vertex_indices[new_line_vertices[i][0]],
7327 vertex_indices[new_line_vertices[i][1]]});
7328 }
7329 break;
7330
7332 {
7333 // Directions so that middle tri looks like a 'normal'
7334 // refined tri (refined quads define outer lines)
7335 constexpr ::ndarray<unsigned int, 3, 2>
7336 new_line_vertices = {{{{15, 16}}, //
7337 {{16, 17}}, //
7338 {{15, 17}}}};
7339
7340 for (unsigned int i = 0; i < n_new_lines; ++i)
7341 new_lines[i]->set_bounding_object_indices(
7342 {vertex_indices[new_line_vertices[i][0]],
7343 vertex_indices[new_line_vertices[i][1]]});
7344 }
7345 break;
7346
7348 {
7349 constexpr ::ndarray<unsigned int, 6, 2>
7350 new_line_vertices = {{{{22, 26}},
7351 {{26, 23}},
7352 {{20, 26}},
7353 {{26, 21}},
7354 {{24, 26}},
7355 {{26, 25}}}};
7356 for (unsigned int i = 0; i < n_new_lines; ++i)
7357 new_lines[i]->set_bounding_object_indices(
7358 {vertex_indices[new_line_vertices[i][0]],
7359 vertex_indices[new_line_vertices[i][1]]});
7360 }
7361 break;
7362
7363 default:
7365 }
7366
7367 // Get the corrected orientation of the child indices of
7368 // `child` for a refined face, given the `face_ref_cell_type`
7369 // and the `face_orientation` as stored in the cell it bounds.
7370 auto standard_to_real_quad_child_index =
7371 [](const unsigned int child,
7372 const types::geometric_orientation face_orientation,
7373 const ReferenceCell<dim - 1> face_ref_cell_type) {
7374 // The parent vertex indices correlate nicely with the
7375 // child indices of a tri and quad, as shown in the
7376 // drawing for 2D face refinement (see the curly brackets
7377 // tagged {} // FACES). We can thus apply the existing
7378 // algorithm for orientation correction of vertex indices
7379 // and reinterpret the output. The only problem is child 3
7380 // in triangles. However it is always in the center so no
7381 // correction is necessary at all.
7382 switch (face_ref_cell_type)
7383 {
7385 // A complicated way to query the private attribute
7386 // `ReferenceCell::triangle_vertex_permutations[face_orientation][vertex]`
7387 if (child != 3)
7389 .standard_to_real_face_vertex(child,
7390 0,
7391 face_orientation);
7392 else
7393 return 3u;
7394
7396 // `ReferenceCell::quadrilateral_vertex_permutations[face_orientation][vertex]`.
7398 .standard_to_real_face_vertex(child,
7399 0,
7400 face_orientation);
7401 default:
7403 }
7404 };
7405
7406 // set up new faces
7407 {
7408 // Similar to `vertex_indices` above the `relevant_lines`
7409 // are filled in multiple steps. The order is once again
7410 // determined by the reference cell and the refinement
7411 // algorithms used by the faces. (For Tetrahedron
7412 // `chosen_line_tetrahedron` is also relevant).
7413 // 1. Get the lines from the faces that are Quadrilaterals.
7414 //
7415 // .- -.- -.
7416 // : 1 :
7417 // .-2-.-3-.
7418 // : 0 :
7419 // .- - - -. n: extracted lines
7420 //
7421 // 2. Get the lines from the faces that are Triangles.
7422 //
7423 // | \ .
7424 // *--1--* .
7425 // |\ |\ .
7426 // | 2 0 \ .
7427 // | \| .
7428 // *-----*--- .
7429 //
7430 // 3. Newly created lines (see above)
7431 // 4. Load indices for the extracted lines
7432 //
7433 // Number of meaningful entries in this list is
7434 // 13 Tetrahedron 21 Wedge
7435 // 20 Pyramid 30 Hexahedron
7436 // In case the maximum changes, edit `max_relevant_lines` a
7437 // few lines above (or in case it was moved to
7438 // ReferenceCell, update it there).
7439
7440 std::array<raw_line_iterator, max_relevant_lines>
7441 relevant_lines;
7442 std::array<unsigned int, max_relevant_lines>
7443 relevant_line_indices;
7444
7445 unsigned int relevant_lines_counter = 0;
7446
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],
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 =
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 =
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() ||
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(
8490 {vertex_indices[0], vertex_indices[1]});
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() ==
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 const unsigned int switch_1_lines[4] = {
8798 switch_1->line_index(0),
8799 switch_1->line_index(1),
8800 switch_1->line_index(2),
8801 switch_1->line_index(3)};
8803 switch_1_line_orientations[4] = {
8804 switch_1->line_orientation(0),
8805 switch_1->line_orientation(1),
8806 switch_1->line_orientation(2),
8807 switch_1->line_orientation(3)};
8808 const types::boundary_id switch_1_boundary_id =
8809 switch_1->boundary_id();
8810 const unsigned int switch_1_user_index =
8811 switch_1->user_index();
8812 const bool switch_1_user_flag =
8813 switch_1->user_flag_set();
8814 const RefinementCase<dim - 1>
8815 switch_1_refinement_case =
8816 switch_1->refinement_case();
8817 const int switch_1_first_child_pair =
8818 (switch_1_refinement_case ?
8819 switch_1->child_index(0) :
8820 -1);
8821 const int switch_1_second_child_pair =
8822 (switch_1_refinement_case ==
8823 RefinementCase<dim - 1>::cut_xy ?
8824 switch_1->child_index(2) :
8825 -1);
8826
8827 switch_1->set_bounding_object_indices(
8828 {switch_2->line_index(0),
8829 switch_2->line_index(1),
8830 switch_2->line_index(2),
8831 switch_2->line_index(3)});
8832 switch_1->set_line_orientation(
8833 0, switch_2->line_orientation(0));
8834 switch_1->set_line_orientation(
8835 1, switch_2->line_orientation(1));
8836 switch_1->set_line_orientation(
8837 2, switch_2->line_orientation(2));
8838 switch_1->set_line_orientation(
8839 3, switch_2->line_orientation(3));
8840 switch_1->set_boundary_id_internal(
8841 switch_2->boundary_id());
8842 switch_1->set_manifold_id(switch_2->manifold_id());
8843 switch_1->set_user_index(switch_2->user_index());
8844 if (switch_2->user_flag_set())
8845 switch_1->set_user_flag();
8846 else
8847 switch_1->clear_user_flag();
8848 switch_1->clear_refinement_case();
8849 switch_1->set_refinement_case(
8850 switch_2->refinement_case());
8851 switch_1->clear_children();
8852 if (switch_2->refinement_case())
8853 switch_1->set_children(0,
8854 switch_2->child_index(0));
8855 if (switch_2->refinement_case() ==
8857 switch_1->set_children(2,
8858 switch_2->child_index(2));
8859
8860 switch_2->set_bounding_object_indices(
8861 {switch_1_lines[0],
8862 switch_1_lines[1],
8863 switch_1_lines[2],
8864 switch_1_lines[3]});
8865 switch_2->set_line_orientation(
8866 0, switch_1_line_orientations[0]);
8867 switch_2->set_line_orientation(
8868 1, switch_1_line_orientations[1]);
8869 switch_2->set_line_orientation(
8870 2, switch_1_line_orientations[2]);
8871 switch_2->set_line_orientation(
8872 3, switch_1_line_orientations[3]);
8873 switch_2->set_boundary_id_internal(
8874 switch_1_boundary_id);
8875 switch_2->set_manifold_id(switch_1->manifold_id());
8876 switch_2->set_user_index(switch_1_user_index);
8877 if (switch_1_user_flag)
8878 switch_2->set_user_flag();
8879 else
8880 switch_2->clear_user_flag();
8881 switch_2->clear_refinement_case();
8882 switch_2->set_refinement_case(
8883 switch_1_refinement_case);
8884 switch_2->clear_children();
8885 switch_2->set_children(0,
8886 switch_1_first_child_pair);
8887 switch_2->set_children(2,
8888 switch_1_second_child_pair);
8889
8890 new_quads[0]->set_refinement_case(
8892 new_quads[0]->set_children(0, quad->child_index(0));
8893 new_quads[1]->set_refinement_case(
8895 new_quads[1]->set_children(0, quad->child_index(2));
8896 }
8897 else
8898 {
8899 new_quads[0]->set_refinement_case(
8901 new_quads[0]->set_children(0, quad->child_index(0));
8902 new_quads[1]->set_refinement_case(
8904 new_quads[1]->set_children(0, quad->child_index(2));
8905 new_line->set_children(
8906 0, quad->child(0)->line_index(3));
8907 Assert(new_line->child(1) ==
8908 quad->child(1)->line(3),
8910 }
8911 quad->clear_children();
8912 }
8913
8914 // note these quads as children to the present one
8915 quad->set_children(0, new_quads[0]->index());
8916
8917 quad->set_refinement_case(aniso_quad_ref_case);
8918
8919 // finally clear flag indicating the need for
8920 // refinement
8921 quad->clear_user_data();
8922 } // if (anisotropic refinement)
8923
8924 if (quad->user_flag_set())
8925 {
8926 // this quad needs to be refined isotropically
8927
8928 // first of all: we only get here in the first run
8929 // of the loop
8930 Assert(loop == 0, ExcInternalError());
8931
8932 // find the next unused vertex. we'll need this in
8933 // any case
8934 while (triangulation.vertices_used[next_unused_vertex] ==
8935 true)
8936 ++next_unused_vertex;
8937 Assert(
8938 next_unused_vertex < triangulation.vertices.size(),
8939 ExcMessage(
8940 "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."));
8941
8942 // now: if the quad is refined anisotropically
8943 // already, set the anisotropic refinement flag
8944 // for both children. Additionally, we have to
8945 // refine the inner line, as it is an outer line
8946 // of the two (anisotropic) children
8947 const RefinementCase<dim - 1> quad_ref_case =
8948 quad->refinement_case();
8949
8950 if (quad_ref_case == RefinementCase<dim - 1>::cut_x ||
8951 quad_ref_case == RefinementCase<dim - 1>::cut_y)
8952 {
8953 // set the 'opposite' refine case for children
8954 quad->child(0)->set_user_index(
8955 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8956 quad->child(1)->set_user_index(
8957 RefinementCase<dim - 1>::cut_xy - quad_ref_case);
8958 // refine the inner line
8960 middle_line;
8961 if (quad_ref_case == RefinementCase<dim - 1>::cut_x)
8962 middle_line = quad->child(0)->line(1);
8963 else
8964 middle_line = quad->child(0)->line(3);
8965
8966 // if the face has been refined
8967 // anisotropically in the last refinement step
8968 // it might be, that it is flagged already and
8969 // that the middle line is thus refined
8970 // already. if not create children.
8971 if (!middle_line->has_children())
8972 {
8973 // set the middle vertex
8974 // appropriately. double refinement of
8975 // quads can only happen in the interior
8976 // of the domain, so we need not care
8977 // about boundary quads here
8978 triangulation.vertices[next_unused_vertex] =
8979 middle_line->center(true);
8980 triangulation.vertices_used[next_unused_vertex] =
8981 true;
8982
8983 // now search a slot for the two
8984 // child lines
8985 next_unused_line =
8986 triangulation.faces->lines
8987 .template next_free_pair_object<1>(
8988 triangulation);
8989
8990 // set the child pointer of the present
8991 // line
8992 middle_line->set_children(
8993 0, next_unused_line->index());
8994
8995 // set the two new lines
8996 const typename Triangulation<dim, spacedim>::
8997 raw_line_iterator children[2] = {
8998 next_unused_line, ++next_unused_line};
8999
9000 // some tests; if any of the iterators
9001 // should be invalid, then already
9002 // dereferencing will fail
9003 AssertIsNotUsed(children[0]);
9004 AssertIsNotUsed(children[1]);
9005
9006 children[0]->set_bounding_object_indices(
9007 {middle_line->vertex_index(0),
9008 next_unused_vertex});
9009 children[1]->set_bounding_object_indices(
9010 {next_unused_vertex,
9011 middle_line->vertex_index(1)});
9012
9013 children[0]->set_used_flag();
9014 children[1]->set_used_flag();
9015 children[0]->clear_children();
9016 children[1]->clear_children();
9017 children[0]->clear_user_data();
9018 children[1]->clear_user_data();
9019 children[0]->clear_user_flag();
9020 children[1]->clear_user_flag();
9021
9022 children[0]->set_boundary_id_internal(
9023 middle_line->boundary_id());
9024 children[1]->set_boundary_id_internal(
9025 middle_line->boundary_id());
9026
9027 children[0]->set_manifold_id(
9028 middle_line->manifold_id());
9029 children[1]->set_manifold_id(
9030 middle_line->manifold_id());
9031 }
9032 // now remove the flag from the quad and go to
9033 // the next quad, the actual refinement of the
9034 // quad takes place later on in this pass of
9035 // the loop or in the next one
9036 quad->clear_user_flag();
9037 continue;
9038 } // if (several refinement cases)
9039
9040 // if we got here, we have an unrefined quad and
9041 // have to do the usual work like in an purely
9042 // isotropic refinement
9043 Assert(quad_ref_case ==
9046
9047 // set the middle vertex appropriately: it might be that
9048 // the quad itself is not at the boundary, but that one of
9049 // its lines actually is. in this case, the newly created
9050 // vertices at the centers of the lines are not
9051 // necessarily the mean values of the adjacent vertices,
9052 // so do not compute the new vertex as the mean value of
9053 // the 4 vertices of the face, but rather as a weighted
9054 // mean value of the 8 vertices which we already have (the
9055 // four old ones, and the four ones inserted as middle
9056 // points for the four lines). summing up some more points
9057 // is generally cheaper than first asking whether one of
9058 // the lines is at the boundary
9059 //
9060 // note that the exact weights are chosen such as to
9061 // minimize the distortion of the four new quads from the
9062 // optimal shape. their description uses the formulas
9063 // underlying the TransfiniteInterpolationManifold
9064 // implementation
9065 triangulation.vertices[next_unused_vertex] =
9066 quad->center(true, true);
9067 triangulation.vertices_used[next_unused_vertex] = true;
9068
9069 // now that we created the right point, make up
9070 // the four lines interior to the quad (++ takes
9071 // care of the end of the vector)
9073 new_lines[4];
9074
9075 for (unsigned int i = 0; i < 4; ++i)
9076 {
9077 if (i % 2 == 0)
9078 // search a free pair of lines for 0. and
9079 // 2. line, so that two of them end up
9080 // together, which is necessary if later on
9081 // we want to refine the quad
9082 // anisotropically and the two lines end up
9083 // as children of new line
9084 next_unused_line =
9085 triangulation.faces->lines
9086 .template next_free_pair_object<1>(triangulation);
9087
9088 new_lines[i] = next_unused_line;
9089 ++next_unused_line;
9090
9091 AssertIsNotUsed(new_lines[i]);
9092 }
9093
9094 // set the data of the four lines. first collect
9095 // the indices of the five vertices:
9096 //
9097 // *--3--*
9098 // | | |
9099 // 0--4--1
9100 // | | |
9101 // *--2--*
9102 //
9103 // the lines are numbered as follows:
9104 //
9105 // *--*--*
9106 // | 1 |
9107 // *2-*-3*
9108 // | 0 |
9109 // *--*--*
9110
9111 const unsigned int vertex_indices[5] = {
9112 quad->line(0)->child(0)->vertex_index(1),
9113 quad->line(1)->child(0)->vertex_index(1),
9114 quad->line(2)->child(0)->vertex_index(1),
9115 quad->line(3)->child(0)->vertex_index(1),
9116 next_unused_vertex};
9117
9118 new_lines[0]->set_bounding_object_indices(
9119 {vertex_indices[2], vertex_indices[4]});
9120 new_lines[1]->set_bounding_object_indices(
9121 {vertex_indices[4], vertex_indices[3]});
9122 new_lines[2]->set_bounding_object_indices(
9123 {vertex_indices[0], vertex_indices[4]});
9124 new_lines[3]->set_bounding_object_indices(
9125 {vertex_indices[4], vertex_indices[1]});
9126
9127 for (const auto &new_line : new_lines)
9128 {
9129 new_line->set_used_flag();
9130 new_line->clear_user_flag();
9131 new_line->clear_user_data();
9132 new_line->clear_children();
9133 new_line->set_boundary_id_internal(quad->boundary_id());
9134 new_line->set_manifold_id(quad->manifold_id());
9135 }
9136
9137 // now for the quads. again, first collect some
9138 // data about the indices of the lines, with the
9139 // following numbering:
9140 //
9141 // .-6-.-7-.
9142 // 1 9 3
9143 // .-10.11-.
9144 // 0 8 2
9145 // .-4-.-5-.
9146
9147 const int line_indices[12] = {
9148 quad->line(0)
9149 ->child(child_line_index(0, quad->line_orientation(0)))
9150 ->index(),
9151 quad->line(0)
9152 ->child(child_line_index(1, quad->line_orientation(0)))
9153 ->index(),
9154 quad->line(1)
9155 ->child(child_line_index(0, quad->line_orientation(1)))
9156 ->index(),
9157 quad->line(1)
9158 ->child(child_line_index(1, quad->line_orientation(1)))
9159 ->index(),
9160 quad->line(2)
9161 ->child(child_line_index(0, quad->line_orientation(2)))
9162 ->index(),
9163 quad->line(2)
9164 ->child(child_line_index(1, quad->line_orientation(2)))
9165 ->index(),
9166 quad->line(3)
9167 ->child(child_line_index(0, quad->line_orientation(3)))
9168 ->index(),
9169 quad->line(3)
9170 ->child(child_line_index(1, quad->line_orientation(3)))
9171 ->index(),
9172 new_lines[0]->index(),
9173 new_lines[1]->index(),
9174 new_lines[2]->index(),
9175 new_lines[3]->index()};
9176
9177 // find some space (consecutive)
9178 // for the first two newly to be
9179 // created quads.
9181 new_quads[4];
9182
9183 next_unused_quad =
9184 triangulation.faces->quads
9185 .template next_free_pair_object<2>(triangulation);
9186
9187 new_quads[0] = next_unused_quad;
9188 AssertIsNotUsed(new_quads[0]);
9189
9190 ++next_unused_quad;
9191 new_quads[1] = next_unused_quad;
9192 AssertIsNotUsed(new_quads[1]);
9193
9194 next_unused_quad =
9195 triangulation.faces->quads
9196 .template next_free_pair_object<2>(triangulation);
9197 new_quads[2] = next_unused_quad;
9198 AssertIsNotUsed(new_quads[2]);
9199
9200 ++next_unused_quad;
9201 new_quads[3] = next_unused_quad;
9202 AssertIsNotUsed(new_quads[3]);
9203
9204 // note these quads as children to the present one
9205 quad->set_children(0, new_quads[0]->index());
9206 quad->set_children(2, new_quads[2]->index());
9207 quad->set_refinement_case(RefinementCase<2>::cut_xy);
9208
9209 new_quads[0]->set_bounding_object_indices(
9210 {line_indices[0],
9211 line_indices[8],
9212 line_indices[4],
9213 line_indices[10]});
9214 new_quads[1]->set_bounding_object_indices(
9215 {line_indices[8],
9216 line_indices[2],
9217 line_indices[5],
9218 line_indices[11]});
9219 new_quads[2]->set_bounding_object_indices(
9220 {line_indices[1],
9221 line_indices[9],
9222 line_indices[10],
9223 line_indices[6]});
9224 new_quads[3]->set_bounding_object_indices(
9225 {line_indices[9],
9226 line_indices[3],
9227 line_indices[11],
9228 line_indices[7]});
9229 for (const auto &new_quad : new_quads)
9230 {
9231 new_quad->set_used_flag();
9232 new_quad->clear_user_flag();
9233 new_quad->clear_user_data();
9234 new_quad->clear_children();
9235 new_quad->set_boundary_id_internal(quad->boundary_id());
9236 new_quad->set_manifold_id(quad->manifold_id());
9237 // set all line orientations to true, change
9238 // this after the loop, as we have to consider
9239 // different lines for each child
9240 for (unsigned int j = 0;
9241 j < GeometryInfo<dim>::lines_per_face;
9242 ++j)
9243 new_quad->set_line_orientation(
9245 }
9246 // now set the line orientation of children of
9247 // outer lines correctly, the lines in the
9248 // interior of the refined quad are automatically
9249 // oriented conforming to the standard
9250 new_quads[0]->set_line_orientation(
9251 0, quad->line_orientation(0));
9252 new_quads[0]->set_line_orientation(
9253 2, quad->line_orientation(2));
9254 new_quads[1]->set_line_orientation(
9255 1, quad->line_orientation(1));
9256 new_quads[1]->set_line_orientation(
9257 2, quad->line_orientation(2));
9258 new_quads[2]->set_line_orientation(
9259 0, quad->line_orientation(0));
9260 new_quads[2]->set_line_orientation(
9261 3, quad->line_orientation(3));
9262 new_quads[3]->set_line_orientation(
9263 1, quad->line_orientation(1));
9264 new_quads[3]->set_line_orientation(
9265 3, quad->line_orientation(3));
9266
9267 // finally clear flag indicating the need for
9268 // refinement
9269 quad->clear_user_flag();
9270 } // if (isotropic refinement)
9271 } // for all quads
9272 } // looped two times over all quads, all quads refined now
9273
9274 //---------------------------------
9275 // Now, finally, set up the new
9276 // cells
9277 //---------------------------------
9278
9280 cells_with_distorted_children;
9281
9282 for (unsigned int level = 0; level != triangulation.levels.size() - 1;
9283 ++level)
9284 {
9285 // only active objects can be refined further; remember
9286 // that we won't operate on the finest level, so
9287 // triangulation.begin_*(level+1) is allowed
9289 hex = triangulation.begin_active_hex(level),
9290 endh = triangulation.begin_active_hex(level + 1);
9292 next_unused_hex = triangulation.begin_raw_hex(level + 1);
9293
9294 for (; hex != endh; ++hex)
9295 if (hex->refine_flag_set())
9296 {
9297 // this hex needs to be refined
9298
9299 // clear flag indicating the need for refinement. do
9300 // it here already, since we can't do it anymore
9301 // once the cell has children
9302 const RefinementCase<dim> ref_case = hex->refine_flag_set();
9303 hex->clear_refine_flag();
9304 hex->set_refinement_case(ref_case);
9305
9306 // depending on the refine case we might have to
9307 // create additional vertices, lines and quads
9308 // interior of the hex before the actual children
9309 // can be set up.
9310
9311 // in a first step: reserve the needed space for
9312 // lines, quads and hexes and initialize them
9313 // correctly
9314
9315 unsigned int n_new_lines = 0;
9316 unsigned int n_new_quads = 0;
9317 unsigned int n_new_hexes = 0;
9318 switch (ref_case)
9319 {
9323 n_new_lines = 0;
9324 n_new_quads = 1;
9325 n_new_hexes = 2;
9326 break;
9330 n_new_lines = 1;
9331 n_new_quads = 4;
9332 n_new_hexes = 4;
9333 break;
9335 n_new_lines = 6;
9336 n_new_quads = 12;
9337 n_new_hexes = 8;
9338 break;
9339 default:
9341 break;
9342 }
9343
9344 // find some space for the newly to be created
9345 // interior lines and initialize them.
9346 std::vector<
9348 new_lines(n_new_lines);
9349 for (unsigned int i = 0; i < n_new_lines; ++i)
9350 {
9351 new_lines[i] =
9352 triangulation.faces->lines
9353 .template next_free_single_object<1>(triangulation);
9354
9355 AssertIsNotUsed(new_lines[i]);
9356 new_lines[i]->set_used_flag();
9357 new_lines[i]->clear_user_flag();
9358 new_lines[i]->clear_user_data();
9359 new_lines[i]->clear_children();
9360 // interior line
9361 new_lines[i]->set_boundary_id_internal(
9363 // they inherit geometry description of the hex they
9364 // belong to
9365 new_lines[i]->set_manifold_id(hex->manifold_id());
9366 }
9367
9368 // find some space for the newly to be created
9369 // interior quads and initialize them.
9370 std::vector<
9372 new_quads(n_new_quads);
9373 for (unsigned int i = 0; i < n_new_quads; ++i)
9374 {
9375 new_quads[i] =
9376 triangulation.faces->quads
9377 .template next_free_single_object<2>(triangulation);
9378
9379 AssertIsNotUsed(new_quads[i]);
9380 new_quads[i]->set_used_flag();
9381 new_quads[i]->clear_user_flag();
9382 new_quads[i]->clear_user_data();
9383 new_quads[i]->clear_children();
9384 // interior quad
9385 new_quads[i]->set_boundary_id_internal(
9387 // they inherit geometry description of the hex they
9388 // belong to
9389 new_quads[i]->set_manifold_id(hex->manifold_id());
9390 // set all line orientation flags to true by
9391 // default, change this afterwards, if necessary
9392 for (unsigned int j = 0;
9393 j < GeometryInfo<dim>::lines_per_face;
9394 ++j)
9395 new_quads[i]->set_line_orientation(
9397 }
9398
9399 types::subdomain_id subdomainid = hex->subdomain_id();
9400
9401 // find some space for the newly to be created hexes
9402 // and initialize them.
9403 std::vector<
9405 new_hexes(n_new_hexes);
9406 for (unsigned int i = 0; i < n_new_hexes; ++i)
9407 {
9408 if (i % 2 == 0)
9409 next_unused_hex =
9410 triangulation.levels[level + 1]->cells.next_free_hex(
9411 triangulation, level + 1);
9412 else
9413 ++next_unused_hex;
9414
9415 new_hexes[i] = next_unused_hex;
9416
9417 AssertIsNotUsed(new_hexes[i]);
9418 new_hexes[i]->set_used_flag();
9419 new_hexes[i]->clear_user_flag();
9420 new_hexes[i]->clear_user_data();
9421 new_hexes[i]->clear_children();
9422 // inherit material
9423 // properties
9424 new_hexes[i]->set_material_id(hex->material_id());
9425 new_hexes[i]->set_manifold_id(hex->manifold_id());
9426 new_hexes[i]->set_subdomain_id(subdomainid);
9427
9428 // We only store the parent for every second cell. That's
9429 // because cells are created during refinement in
9430 // multiples of two, and so two successive cells always
9431 // share the same parent.
9432 if (i % 2 == 0)
9433 new_hexes[i]->set_parent(hex->index());
9434
9435 // set the face_orientation flag to true for all
9436 // faces initially, as this is the default value
9437 // which is true for all faces interior to the
9438 // hex. later on go the other way round and
9439 // reset faces that are at the boundary of the
9440 // mother cube
9441 //
9442 // the same is true for the face_flip and
9443 // face_rotation flags. however, the latter two
9444 // are set to false by default as this is the
9445 // standard value
9446 for (const unsigned int f :
9448 new_hexes[i]->set_combined_face_orientation(
9450 }
9451 // note these hexes as children to the present cell
9452 for (unsigned int i = 0; i < n_new_hexes / 2; ++i)
9453 hex->set_children(2 * i, new_hexes[2 * i]->index());
9454
9455 // we have to take into account whether the
9456 // different faces are oriented correctly or in the
9457 // opposite direction, so store that up front
9458
9459 // face_orientation
9460 const bool f_or[6] = {hex->face_orientation(0),
9461 hex->face_orientation(1),
9462 hex->face_orientation(2),
9463 hex->face_orientation(3),
9464 hex->face_orientation(4),
9465 hex->face_orientation(5)};
9466
9467 // face_flip
9468 const bool f_fl[6] = {hex->face_flip(0),
9469 hex->face_flip(1),
9470 hex->face_flip(2),
9471 hex->face_flip(3),
9472 hex->face_flip(4),
9473 hex->face_flip(5)};
9474
9475 // face_rotation
9476 const bool f_ro[6] = {hex->face_rotation(0),
9477 hex->face_rotation(1),
9478 hex->face_rotation(2),
9479 hex->face_rotation(3),
9480 hex->face_rotation(4),
9481 hex->face_rotation(5)};
9482
9483 // combined orientation
9484 const types::geometric_orientation f_co[6] = {
9485 hex->combined_face_orientation(0),
9486 hex->combined_face_orientation(1),
9487 hex->combined_face_orientation(2),
9488 hex->combined_face_orientation(3),
9489 hex->combined_face_orientation(4),
9490 hex->combined_face_orientation(5)};
9491
9492 // little helper table, indicating, whether the
9493 // child with index 0 or with index 1 can be found
9494 // at the standard origin of an anisotropically
9495 // refined quads in real orientation index 1:
9496 // (RefineCase - 1) index 2: face_flip
9497
9498 // index 3: face rotation
9499 // note: face orientation has no influence
9500 const unsigned int child_at_origin[2][2][2] = {
9501 {{0, 0}, // RefinementCase<dim>::cut_x, face_flip=false,
9502 // face_rotation=false and true
9503 {1, 1}}, // RefinementCase<dim>::cut_x, face_flip=true,
9504 // face_rotation=false and true
9505 {{0, 1}, // RefinementCase<dim>::cut_y, face_flip=false,
9506 // face_rotation=false and true
9507 {1, 0}}}; // RefinementCase<dim>::cut_y, face_flip=true,
9508 // face_rotation=false and true
9509
9510 //-------------------------------------
9511 //
9512 // in the following we will do the same thing for
9513 // each refinement case: create a new vertex (if
9514 // needed), create new interior lines (if needed),
9515 // create new interior quads and afterwards build
9516 // the children hexes out of these and the existing
9517 // subfaces of the outer quads (which have been
9518 // created above). However, even if the steps are
9519 // quite similar, the actual work strongly depends
9520 // on the actual refinement case. therefore, we use
9521 // separate blocks of code for each of these cases,
9522 // which hopefully increases the readability to some
9523 // extend.
9524
9525 switch (ref_case)
9526 {
9528 {
9529 //----------------------------
9530 //
9531 // RefinementCase<dim>::cut_x
9532 //
9533 // the refined cube will look
9534 // like this:
9535 //
9536 // *----*----*
9537 // / / /|
9538 // / / / |
9539 // / / / |
9540 // *----*----* |
9541 // | | | |
9542 // | | | *
9543 // | | | /
9544 // | | | /
9545 // | | |/
9546 // *----*----*
9547 //
9548 // again, first collect some data about the
9549 // indices of the lines, with the following
9550 // numbering:
9551
9552 // face 2: front plane
9553 // (note: x,y exchanged)
9554 // *---*---*
9555 // | | |
9556 // | 0 |
9557 // | | |
9558 // *---*---*
9559 // m0
9560 // face 3: back plane
9561 // (note: x,y exchanged)
9562 // m1
9563 // *---*---*
9564 // | | |
9565 // | 1 |
9566 // | | |
9567 // *---*---*
9568 // face 4: bottom plane
9569 // *---*---*
9570 // / / /
9571 // / 2 /
9572 // / / /
9573 // *---*---*
9574 // m0
9575 // face 5: top plane
9576 // m1
9577 // *---*---*
9578 // / / /
9579 // / 3 /
9580 // / / /
9581 // *---*---*
9582
9583 // set up a list of line iterators first. from
9584 // this, construct lists of line_indices and
9585 // line orientations later on
9586 const typename Triangulation<dim, spacedim>::
9587 raw_line_iterator lines[4] = {
9588 hex->face(2)->child(0)->line(
9589 (hex->face(2)->refinement_case() ==
9591 1 :
9592 3), // 0
9593 hex->face(3)->child(0)->line(
9594 (hex->face(3)->refinement_case() ==
9596 1 :
9597 3), // 1
9598 hex->face(4)->child(0)->line(
9599 (hex->face(4)->refinement_case() ==
9601 1 :
9602 3), // 2
9603 hex->face(5)->child(0)->line(
9604 (hex->face(5)->refinement_case() ==
9606 1 :
9607 3) // 3
9608 };
9609
9610 unsigned int line_indices[4];
9611 for (unsigned int i = 0; i < 4; ++i)
9612 line_indices[i] = lines[i]->index();
9613
9614 // the orientation of lines for the inner quads
9615 // is quite tricky. as these lines are newly
9616 // created ones and thus have no parents, they
9617 // cannot inherit this property. set up an array
9618 // and fill it with the respective values
9619 types::geometric_orientation line_orientation[4]{};
9620
9621 // the middle vertex marked as m0 above is the
9622 // start vertex for lines 0 and 2 in standard
9623 // orientation, whereas m1 is the end vertex of
9624 // lines 1 and 3 in standard orientation
9625 const unsigned int middle_vertices[2] = {
9626 hex->line(2)->child(0)->vertex_index(1),
9627 hex->line(7)->child(0)->vertex_index(1)};
9628
9629 for (unsigned int i = 0; i < 4; ++i)
9630 if (lines[i]->vertex_index(i % 2) ==
9631 middle_vertices[i % 2])
9632 line_orientation[i] =
9634 else
9635 {
9636 // it must be the other way round then
9637 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9638 middle_vertices[i % 2],
9640 line_orientation[i] =
9642 }
9643
9644 // set up the new quad, line numbering is as
9645 // indicated above
9646 new_quads[0]->set_bounding_object_indices(
9647 {line_indices[0],
9648 line_indices[1],
9649 line_indices[2],
9650 line_indices[3]});
9651
9652 new_quads[0]->set_line_orientation(
9653 0, line_orientation[0]);
9654 new_quads[0]->set_line_orientation(
9655 1, line_orientation[1]);
9656 new_quads[0]->set_line_orientation(
9657 2, line_orientation[2]);
9658 new_quads[0]->set_line_orientation(
9659 3, line_orientation[3]);
9660
9661 // the quads are numbered as follows:
9662 //
9663 // planes in the interior of the old hex:
9664 //
9665 // *
9666 // /|
9667 // / | x
9668 // / | *-------* *---------*
9669 // * | | | / /
9670 // | 0 | | | / /
9671 // | * | | / /
9672 // | / *-------*y *---------*x
9673 // | /
9674 // |/
9675 // *
9676 //
9677 // children of the faces of the old hex
9678 //
9679 // *---*---* *---*---*
9680 // /| | | / / /|
9681 // / | | | / 9 / 10/ |
9682 // / | 5 | 6 | / / / |
9683 // * | | | *---*---* |
9684 // | 1 *---*---* | | | 2 *
9685 // | / / / | | | /
9686 // | / 7 / 8 / | 3 | 4 | /
9687 // |/ / / | | |/
9688 // *---*---* *---*---*
9689 //
9690 // note that we have to take care of the
9691 // orientation of faces.
9692 const int quad_indices[11] = {
9693 new_quads[0]->index(), // 0
9694
9695 hex->face(0)->index(), // 1
9696
9697 hex->face(1)->index(), // 2
9698
9699 hex->face(2)->child_index(
9700 child_at_origin[hex->face(2)->refinement_case() -
9701 1][f_fl[2]][f_ro[2]]), // 3
9702 hex->face(2)->child_index(
9703 1 -
9704 child_at_origin[hex->face(2)->refinement_case() -
9705 1][f_fl[2]][f_ro[2]]),
9706
9707 hex->face(3)->child_index(
9708 child_at_origin[hex->face(3)->refinement_case() -
9709 1][f_fl[3]][f_ro[3]]), // 5
9710 hex->face(3)->child_index(
9711 1 -
9712 child_at_origin[hex->face(3)->refinement_case() -
9713 1][f_fl[3]][f_ro[3]]),
9714
9715 hex->face(4)->child_index(
9716 child_at_origin[hex->face(4)->refinement_case() -
9717 1][f_fl[4]][f_ro[4]]), // 7
9718 hex->face(4)->child_index(
9719 1 -
9720 child_at_origin[hex->face(4)->refinement_case() -
9721 1][f_fl[4]][f_ro[4]]),
9722
9723 hex->face(5)->child_index(
9724 child_at_origin[hex->face(5)->refinement_case() -
9725 1][f_fl[5]][f_ro[5]]), // 9
9726 hex->face(5)->child_index(
9727 1 -
9728 child_at_origin[hex->face(5)->refinement_case() -
9729 1][f_fl[5]][f_ro[5]])
9730
9731 };
9732
9733 new_hexes[0]->set_bounding_object_indices(
9734 {quad_indices[1],
9735 quad_indices[0],
9736 quad_indices[3],
9737 quad_indices[5],
9738 quad_indices[7],
9739 quad_indices[9]});
9740 new_hexes[1]->set_bounding_object_indices(
9741 {quad_indices[0],
9742 quad_indices[2],
9743 quad_indices[4],
9744 quad_indices[6],
9745 quad_indices[8],
9746 quad_indices[10]});
9747 break;
9748 }
9749
9751 {
9752 //----------------------------
9753 //
9754 // RefinementCase<dim>::cut_y
9755 //
9756 // the refined cube will look like this:
9757 //
9758 // *---------*
9759 // / /|
9760 // *---------* |
9761 // / /| |
9762 // *---------* | |
9763 // | | | |
9764 // | | | *
9765 // | | |/
9766 // | | *
9767 // | |/
9768 // *---------*
9769 //
9770 // again, first collect some data about the
9771 // indices of the lines, with the following
9772 // numbering:
9773
9774 // face 0: left plane
9775 // *
9776 // /|
9777 // * |
9778 // /| |
9779 // * | |
9780 // | 0 |
9781 // | | *
9782 // | |/
9783 // | *m0
9784 // |/
9785 // *
9786 // face 1: right plane
9787 // *
9788 // /|
9789 // m1* |
9790 // /| |
9791 // * | |
9792 // | 1 |
9793 // | | *
9794 // | |/
9795 // | *
9796 // |/
9797 // *
9798 // face 4: bottom plane
9799 // *-------*
9800 // / /
9801 // m0*---2---*
9802 // / /
9803 // *-------*
9804 // face 5: top plane
9805 // *-------*
9806 // / /
9807 // *---3---*m1
9808 // / /
9809 // *-------*
9810
9811 // set up a list of line iterators first. from
9812 // this, construct lists of line_indices and
9813 // line orientations later on
9814 const typename Triangulation<dim, spacedim>::
9815 raw_line_iterator lines[4] = {
9816 hex->face(0)->child(0)->line(
9817 (hex->face(0)->refinement_case() ==
9819 1 :
9820 3), // 0
9821 hex->face(1)->child(0)->line(
9822 (hex->face(1)->refinement_case() ==
9824 1 :
9825 3), // 1
9826 hex->face(4)->child(0)->line(
9827 (hex->face(4)->refinement_case() ==
9829 1 :
9830 3), // 2
9831 hex->face(5)->child(0)->line(
9832 (hex->face(5)->refinement_case() ==
9834 1 :
9835 3) // 3
9836 };
9837
9838 unsigned int line_indices[4];
9839 for (unsigned int i = 0; i < 4; ++i)
9840 line_indices[i] = lines[i]->index();
9841
9842 // the orientation of lines for the inner quads
9843 // is quite tricky. as these lines are newly
9844 // created ones and thus have no parents, they
9845 // cannot inherit this property. set up an array
9846 // and fill it with the respective values
9847 types::geometric_orientation line_orientation[4]{};
9848
9849 // the middle vertex marked as m0 above is the
9850 // start vertex for lines 0 and 2 in standard
9851 // orientation, whereas m1 is the end vertex of
9852 // lines 1 and 3 in standard orientation
9853 const unsigned int middle_vertices[2] = {
9854 hex->line(0)->child(0)->vertex_index(1),
9855 hex->line(5)->child(0)->vertex_index(1)};
9856
9857 for (unsigned int i = 0; i < 4; ++i)
9858 if (lines[i]->vertex_index(i % 2) ==
9859 middle_vertices[i % 2])
9860 line_orientation[i] =
9862 else
9863 {
9864 // it must be the other way round then
9865 Assert(lines[i]->vertex_index((i + 1) % 2) ==
9866 middle_vertices[i % 2],
9868 line_orientation[i] =
9870 }
9871
9872 // set up the new quad, line numbering is as
9873 // indicated above
9874 new_quads[0]->set_bounding_object_indices(
9875 {line_indices[2],
9876 line_indices[3],
9877 line_indices[0],
9878 line_indices[1]});
9879
9880 new_quads[0]->set_line_orientation(
9881 0, line_orientation[2]);
9882 new_quads[0]->set_line_orientation(
9883 1, line_orientation[3]);
9884 new_quads[0]->set_line_orientation(
9885 2, line_orientation[0]);
9886 new_quads[0]->set_line_orientation(
9887 3, line_orientation[1]);
9888
9889 // the quads are numbered as follows:
9890 //
9891 // planes in the interior of the old hex:
9892 //
9893 // *
9894 // /|
9895 // / | x
9896 // / | *-------* *---------*
9897 // * | | | / /
9898 // | | | 0 | / /
9899 // | * | | / /
9900 // | / *-------*y *---------*x
9901 // | /
9902 // |/
9903 // *
9904 //
9905 // children of the faces of the old hex
9906 //
9907 // *-------* *-------*
9908 // /| | / 10 /|
9909 // * | | *-------* |
9910 // /| | 6 | / 9 /| |
9911 // * |2| | *-------* |4|
9912 // | | *-------* | | | *
9913 // |1|/ 8 / | |3|/
9914 // | *-------* | 5 | *
9915 // |/ 7 / | |/
9916 // *-------* *-------*
9917 //
9918 // note that we have to take care of the
9919 // orientation of faces.
9920 const int quad_indices[11] = {
9921 new_quads[0]->index(), // 0
9922
9923 hex->face(0)->child_index(
9924 child_at_origin[hex->face(0)->refinement_case() -
9925 1][f_fl[0]][f_ro[0]]), // 1
9926 hex->face(0)->child_index(
9927 1 -
9928 child_at_origin[hex->face(0)->refinement_case() -
9929 1][f_fl[0]][f_ro[0]]),
9930
9931 hex->face(1)->child_index(
9932 child_at_origin[hex->face(1)->refinement_case() -
9933 1][f_fl[1]][f_ro[1]]), // 3
9934 hex->face(1)->child_index(
9935 1 -
9936 child_at_origin[hex->face(1)->refinement_case() -
9937 1][f_fl[1]][f_ro[1]]),
9938
9939 hex->face(2)->index(), // 5
9940
9941 hex->face(3)->index(), // 6
9942
9943 hex->face(4)->child_index(
9944 child_at_origin[hex->face(4)->refinement_case() -
9945 1][f_fl[4]][f_ro[4]]), // 7
9946 hex->face(4)->child_index(
9947 1 -
9948 child_at_origin[hex->face(4)->refinement_case() -
9949 1][f_fl[4]][f_ro[4]]),
9950
9951 hex->face(5)->child_index(
9952 child_at_origin[hex->face(5)->refinement_case() -
9953 1][f_fl[5]][f_ro[5]]), // 9
9954 hex->face(5)->child_index(
9955 1 -
9956 child_at_origin[hex->face(5)->refinement_case() -
9957 1][f_fl[5]][f_ro[5]])
9958
9959 };
9960
9961 new_hexes[0]->set_bounding_object_indices(
9962 {quad_indices[1],
9963 quad_indices[3],
9964 quad_indices[5],
9965 quad_indices[0],
9966 quad_indices[7],
9967 quad_indices[9]});
9968 new_hexes[1]->set_bounding_object_indices(
9969 {quad_indices[2],
9970 quad_indices[4],
9971 quad_indices[0],
9972 quad_indices[6],
9973 quad_indices[8],
9974 quad_indices[10]});
9975 break;
9976 }
9977
9979 {
9980 //----------------------------
9981 //
9982 // RefinementCase<dim>::cut_z
9983 //
9984 // the refined cube will look like this:
9985 //
9986 // *---------*
9987 // / /|
9988 // / / |
9989 // / / *
9990 // *---------* /|
9991 // | | / |
9992 // | |/ *
9993 // *---------* /
9994 // | | /
9995 // | |/
9996 // *---------*
9997 //
9998 // again, first collect some data about the
9999 // indices of the lines, with the following
10000 // numbering:
10001
10002 // face 0: left plane
10003 // *
10004 // /|
10005 // / |
10006 // / *
10007 // * /|
10008 // | 0 |
10009 // |/ *
10010 // m0* /
10011 // | /
10012 // |/
10013 // *
10014 // face 1: right plane
10015 // *
10016 // /|
10017 // / |
10018 // / *m1
10019 // * /|
10020 // | 1 |
10021 // |/ *
10022 // * /
10023 // | /
10024 // |/
10025 // *
10026 // face 2: front plane
10027 // (note: x,y exchanged)
10028 // *-------*
10029 // | |
10030 // m0*---2---*
10031 // | |
10032 // *-------*
10033 // face 3: back plane
10034 // (note: x,y exchanged)
10035 // *-------*
10036 // | |
10037 // *---3---*m1
10038 // | |
10039 // *-------*
10040
10041 // set up a list of line iterators first. from
10042 // this, construct lists of line_indices and
10043 // line orientations later on
10044 const typename Triangulation<dim, spacedim>::
10045 raw_line_iterator lines[4] = {
10046 hex->face(0)->child(0)->line(
10047 (hex->face(0)->refinement_case() ==
10049 1 :
10050 3), // 0
10051 hex->face(1)->child(0)->line(
10052 (hex->face(1)->refinement_case() ==
10054 1 :
10055 3), // 1
10056 hex->face(2)->child(0)->line(
10057 (hex->face(2)->refinement_case() ==
10059 1 :
10060 3), // 2
10061 hex->face(3)->child(0)->line(
10062 (hex->face(3)->refinement_case() ==
10064 1 :
10065 3) // 3
10066 };
10067
10068 unsigned int line_indices[4];
10069 for (unsigned int i = 0; i < 4; ++i)
10070 line_indices[i] = lines[i]->index();
10071
10072 // the orientation of lines for the inner quads
10073 // is quite tricky. as these lines are newly
10074 // created ones and thus have no parents, they
10075 // cannot inherit this property. set up an array
10076 // and fill it with the respective values
10077 types::geometric_orientation line_orientation[4]{};
10078
10079 // the middle vertex marked as m0 above is the
10080 // start vertex for lines 0 and 2 in standard
10081 // orientation, whereas m1 is the end vertex of
10082 // lines 1 and 3 in standard orientation
10083 const unsigned int middle_vertices[2] = {
10084 middle_vertex_index<dim, spacedim>(hex->line(8)),
10085 middle_vertex_index<dim, spacedim>(hex->line(11))};
10086
10087 for (unsigned int i = 0; i < 4; ++i)
10088 if (lines[i]->vertex_index(i % 2) ==
10089 middle_vertices[i % 2])
10090 line_orientation[i] =
10092 else
10093 {
10094 // it must be the other way round then
10095 Assert(lines[i]->vertex_index((i + 1) % 2) ==
10096 middle_vertices[i % 2],
10098 line_orientation[i] =
10100 }
10101
10102 // set up the new quad, line numbering is as
10103 // indicated above
10104 new_quads[0]->set_bounding_object_indices(
10105 {line_indices[0],
10106 line_indices[1],
10107 line_indices[2],
10108 line_indices[3]});
10109
10110 new_quads[0]->set_line_orientation(
10111 0, line_orientation[0]);
10112 new_quads[0]->set_line_orientation(
10113 1, line_orientation[1]);
10114 new_quads[0]->set_line_orientation(
10115 2, line_orientation[2]);
10116 new_quads[0]->set_line_orientation(
10117 3, line_orientation[3]);
10118
10119 // the quads are numbered as follows:
10120 //
10121 // planes in the interior of the old hex:
10122 //
10123 // *
10124 // /|
10125 // / | x
10126 // / | *-------* *---------*
10127 // * | | | / /
10128 // | | | | / 0 /
10129 // | * | | / /
10130 // | / *-------*y *---------*x
10131 // | /
10132 // |/
10133 // *
10134 //
10135 // children of the faces of the old hex
10136 //
10137 // *---*---* *-------*
10138 // /| 8 | / /|
10139 // / | | / 10 / |
10140 // / *-------* / / *
10141 // * 2/| | *-------* 4/|
10142 // | / | 7 | | 6 | / |
10143 // |/1 *-------* | |/3 *
10144 // * / / *-------* /
10145 // | / 9 / | | /
10146 // |/ / | 5 |/
10147 // *-------* *---*---*
10148 //
10149 // note that we have to take care of the
10150 // orientation of faces.
10151 const int quad_indices[11] = {
10152 new_quads[0]->index(), // 0
10153
10154 hex->face(0)->child_index(
10155 child_at_origin[hex->face(0)->refinement_case() -
10156 1][f_fl[0]][f_ro[0]]), // 1
10157 hex->face(0)->child_index(
10158 1 -
10159 child_at_origin[hex->face(0)->refinement_case() -
10160 1][f_fl[0]][f_ro[0]]),
10161
10162 hex->face(1)->child_index(
10163 child_at_origin[hex->face(1)->refinement_case() -
10164 1][f_fl[1]][f_ro[1]]), // 3
10165 hex->face(1)->child_index(
10166 1 -
10167 child_at_origin[hex->face(1)->refinement_case() -
10168 1][f_fl[1]][f_ro[1]]),
10169
10170 hex->face(2)->child_index(
10171 child_at_origin[hex->face(2)->refinement_case() -
10172 1][f_fl[2]][f_ro[2]]), // 5
10173 hex->face(2)->child_index(
10174 1 -
10175 child_at_origin[hex->face(2)->refinement_case() -
10176 1][f_fl[2]][f_ro[2]]),
10177
10178 hex->face(3)->child_index(
10179 child_at_origin[hex->face(3)->refinement_case() -
10180 1][f_fl[3]][f_ro[3]]), // 7
10181 hex->face(3)->child_index(
10182 1 -
10183 child_at_origin[hex->face(3)->refinement_case() -
10184 1][f_fl[3]][f_ro[3]]),
10185
10186 hex->face(4)->index(), // 9
10187
10188 hex->face(5)->index() // 10
10189 };
10190
10191 new_hexes[0]->set_bounding_object_indices(
10192 {quad_indices[1],
10193 quad_indices[3],
10194 quad_indices[5],
10195 quad_indices[7],
10196 quad_indices[9],
10197 quad_indices[0]});
10198 new_hexes[1]->set_bounding_object_indices(
10199 {quad_indices[2],
10200 quad_indices[4],
10201 quad_indices[6],
10202 quad_indices[8],
10203 quad_indices[0],
10204 quad_indices[10]});
10205 break;
10206 }
10207
10209 {
10210 //----------------------------
10211 //
10212 // RefinementCase<dim>::cut_xy
10213 //
10214 // the refined cube will look like this:
10215 //
10216 // *----*----*
10217 // / / /|
10218 // *----*----* |
10219 // / / /| |
10220 // *----*----* | |
10221 // | | | | |
10222 // | | | | *
10223 // | | | |/
10224 // | | | *
10225 // | | |/
10226 // *----*----*
10227 //
10228
10229 // first, create the new internal line
10230 new_lines[0]->set_bounding_object_indices(
10231 {middle_vertex_index<dim, spacedim>(hex->face(4)),
10232 middle_vertex_index<dim, spacedim>(hex->face(5))});
10233
10234 // again, first collect some data about the
10235 // indices of the lines, with the following
10236 // numbering:
10237
10238 // face 0: left plane
10239 // *
10240 // /|
10241 // * |
10242 // /| |
10243 // * | |
10244 // | 0 |
10245 // | | *
10246 // | |/
10247 // | *
10248 // |/
10249 // *
10250 // face 1: right plane
10251 // *
10252 // /|
10253 // * |
10254 // /| |
10255 // * | |
10256 // | 1 |
10257 // | | *
10258 // | |/
10259 // | *
10260 // |/
10261 // *
10262 // face 2: front plane
10263 // (note: x,y exchanged)
10264 // *---*---*
10265 // | | |
10266 // | 2 |
10267 // | | |
10268 // *-------*
10269 // face 3: back plane
10270 // (note: x,y exchanged)
10271 // *---*---*
10272 // | | |
10273 // | 3 |
10274 // | | |
10275 // *---*---*
10276 // face 4: bottom plane
10277 // *---*---*
10278 // / 5 /
10279 // *-6-*-7-*
10280 // / 4 /
10281 // *---*---*
10282 // face 5: top plane
10283 // *---*---*
10284 // / 9 /
10285 // *10-*-11*
10286 // / 8 /
10287 // *---*---*
10288 // middle planes
10289 // *-------* *---*---*
10290 // / / | | |
10291 // / / | 12 |
10292 // / / | | |
10293 // *-------* *---*---*
10294
10295 // set up a list of line iterators first. from
10296 // this, construct lists of line_indices and
10297 // line orientations later on
10298 const typename Triangulation<
10299 dim,
10300 spacedim>::raw_line_iterator lines[13] = {
10301 hex->face(0)->child(0)->line(
10302 (hex->face(0)->refinement_case() ==
10304 1 :
10305 3), // 0
10306 hex->face(1)->child(0)->line(
10307 (hex->face(1)->refinement_case() ==
10309 1 :
10310 3), // 1
10311 hex->face(2)->child(0)->line(
10312 (hex->face(2)->refinement_case() ==
10314 1 :
10315 3), // 2
10316 hex->face(3)->child(0)->line(
10317 (hex->face(3)->refinement_case() ==
10319 1 :
10320 3), // 3
10321
10322 hex->face(4)
10323 ->isotropic_child(
10325 0, f_or[4], f_fl[4], f_ro[4]))
10326 ->line(
10328 1, f_or[4], f_fl[4], f_ro[4])), // 4
10329 hex->face(4)
10330 ->isotropic_child(
10332 3, f_or[4], f_fl[4], f_ro[4]))
10333 ->line(
10335 0, f_or[4], f_fl[4], f_ro[4])), // 5
10336 hex->face(4)
10337 ->isotropic_child(
10339 0, f_or[4], f_fl[4], f_ro[4]))
10340 ->line(
10342 3, f_or[4], f_fl[4], f_ro[4])), // 6
10343 hex->face(4)
10344 ->isotropic_child(
10346 3, f_or[4], f_fl[4], f_ro[4]))
10347 ->line(
10349 2, f_or[4], f_fl[4], f_ro[4])), // 7
10350
10351 hex->face(5)
10352 ->isotropic_child(
10354 0, f_or[5], f_fl[5], f_ro[5]))
10355 ->line(
10357 1, f_or[5], f_fl[5], f_ro[5])), // 8
10358 hex->face(5)
10359 ->isotropic_child(
10361 3, f_or[5], f_fl[5], f_ro[5]))
10362 ->line(
10364 0, f_or[5], f_fl[5], f_ro[5])), // 9
10365 hex->face(5)
10366 ->isotropic_child(
10368 0, f_or[5], f_fl[5], f_ro[5]))
10369 ->line(
10371 3, f_or[5], f_fl[5], f_ro[5])), // 10
10372 hex->face(5)
10373 ->isotropic_child(
10375 3, f_or[5], f_fl[5], f_ro[5]))
10376 ->line(
10378 2, f_or[5], f_fl[5], f_ro[5])), // 11
10379
10380 new_lines[0] // 12
10381 };
10382
10383 unsigned int line_indices[13];
10384 for (unsigned int i = 0; i < 13; ++i)
10385 line_indices[i] = lines[i]->index();
10386
10387 // the orientation of lines for the inner quads
10388 // is quite tricky. as these lines are newly
10389 // created ones and thus have no parents, they
10390 // cannot inherit this property. set up an array
10391 // and fill it with the respective values
10392 types::geometric_orientation line_orientation[13]{};
10393
10394 // the middle vertices of the lines of our
10395 // bottom face
10396 const unsigned int middle_vertices[4] = {
10397 hex->line(0)->child(0)->vertex_index(1),
10398 hex->line(1)->child(0)->vertex_index(1),
10399 hex->line(2)->child(0)->vertex_index(1),
10400 hex->line(3)->child(0)->vertex_index(1),
10401 };
10402
10403 // note: for lines 0 to 3 the orientation of the
10404 // line is 'true', if vertex 0 is on the bottom
10405 // face
10406 for (unsigned int i = 0; i < 4; ++i)
10407 if (lines[i]->vertex_index(0) == middle_vertices[i])
10408 line_orientation[i] =
10410 else
10411 {
10412 // it must be the other way round then
10413 Assert(lines[i]->vertex_index(1) ==
10414 middle_vertices[i],
10416 line_orientation[i] =
10418 }
10419
10420 // note: for lines 4 to 11 (inner lines of the
10421 // outer quads) the following holds: the second
10422 // vertex of the even lines in standard
10423 // orientation is the vertex in the middle of
10424 // the quad, whereas for odd lines the first
10425 // vertex is the same middle vertex.
10426 for (unsigned int i = 4; i < 12; ++i)
10427 if (lines[i]->vertex_index((i + 1) % 2) ==
10428 middle_vertex_index<dim, spacedim>(
10429 hex->face(3 + i / 4)))
10430 line_orientation[i] =
10432 else
10433 {
10434 // it must be the other way round then
10435 Assert(lines[i]->vertex_index(i % 2) ==
10436 (middle_vertex_index<dim, spacedim>(
10437 hex->face(3 + i / 4))),
10439 line_orientation[i] =
10441 }
10442 // for the last line the line orientation is
10443 // always true, since it was just constructed
10444 // that way
10445 line_orientation[12] =
10447
10448 // set up the 4 quads, numbered as follows (left
10449 // quad numbering, right line numbering
10450 // extracted from above)
10451 //
10452 // * *
10453 // /| 9|
10454 // * | * |
10455 // y/| | 8| 3
10456 // * |1| * | |
10457 // | | |x | 12|
10458 // |0| * | | *
10459 // | |/ 2 |5
10460 // | * | *
10461 // |/ |4
10462 // * *
10463 //
10464 // x
10465 // *---*---* *10-*-11*
10466 // | | | | | |
10467 // | 2 | 3 | 0 12 1
10468 // | | | | | |
10469 // *---*---*y *-6-*-7-*
10470
10471 new_quads[0]->set_bounding_object_indices(
10472 {line_indices[2],
10473 line_indices[12],
10474 line_indices[4],
10475 line_indices[8]});
10476 new_quads[1]->set_bounding_object_indices(
10477 {line_indices[12],
10478 line_indices[3],
10479 line_indices[5],
10480 line_indices[9]});
10481 new_quads[2]->set_bounding_object_indices(
10482 {line_indices[6],
10483 line_indices[10],
10484 line_indices[0],
10485 line_indices[12]});
10486 new_quads[3]->set_bounding_object_indices(
10487 {line_indices[7],
10488 line_indices[11],
10489 line_indices[12],
10490 line_indices[1]});
10491
10492 new_quads[0]->set_line_orientation(
10493 0, line_orientation[2]);
10494 new_quads[0]->set_line_orientation(
10495 2, line_orientation[4]);
10496 new_quads[0]->set_line_orientation(
10497 3, line_orientation[8]);
10498
10499 new_quads[1]->set_line_orientation(
10500 1, line_orientation[3]);
10501 new_quads[1]->set_line_orientation(
10502 2, line_orientation[5]);
10503 new_quads[1]->set_line_orientation(
10504 3, line_orientation[9]);
10505
10506 new_quads[2]->set_line_orientation(
10507 0, line_orientation[6]);
10508 new_quads[2]->set_line_orientation(
10509 1, line_orientation[10]);
10510 new_quads[2]->set_line_orientation(
10511 2, line_orientation[0]);
10512
10513 new_quads[3]->set_line_orientation(
10514 0, line_orientation[7]);
10515 new_quads[3]->set_line_orientation(
10516 1, line_orientation[11]);
10517 new_quads[3]->set_line_orientation(
10518 3, line_orientation[1]);
10519
10520 // the quads are numbered as follows:
10521 //
10522 // planes in the interior of the old hex:
10523 //
10524 // *
10525 // /|
10526 // * | x
10527 // /| | *---*---* *---------*
10528 // * |1| | | | / /
10529 // | | | | 2 | 3 | / /
10530 // |0| * | | | / /
10531 // | |/ *---*---*y *---------*x
10532 // | *
10533 // |/
10534 // *
10535 //
10536 // children of the faces of the old hex
10537 //
10538 // *---*---* *---*---*
10539 // /| | | /18 / 19/|
10540 // * |10 | 11| /---/---* |
10541 // /| | | | /16 / 17/| |
10542 // * |5| | | *---*---* |7|
10543 // | | *---*---* | | | | *
10544 // |4|/14 / 15/ | | |6|/
10545 // | *---/---/ | 8 | 9 | *
10546 // |/12 / 13/ | | |/
10547 // *---*---* *---*---*
10548 //
10549 // note that we have to take care of the
10550 // orientation of faces.
10551 const int quad_indices[20] = {
10552 new_quads[0]->index(), // 0
10553 new_quads[1]->index(),
10554 new_quads[2]->index(),
10555 new_quads[3]->index(),
10556
10557 hex->face(0)->child_index(
10558 child_at_origin[hex->face(0)->refinement_case() -
10559 1][f_fl[0]][f_ro[0]]), // 4
10560 hex->face(0)->child_index(
10561 1 -
10562 child_at_origin[hex->face(0)->refinement_case() -
10563 1][f_fl[0]][f_ro[0]]),
10564
10565 hex->face(1)->child_index(
10566 child_at_origin[hex->face(1)->refinement_case() -
10567 1][f_fl[1]][f_ro[1]]), // 6
10568 hex->face(1)->child_index(
10569 1 -
10570 child_at_origin[hex->face(1)->refinement_case() -
10571 1][f_fl[1]][f_ro[1]]),
10572
10573 hex->face(2)->child_index(
10574 child_at_origin[hex->face(2)->refinement_case() -
10575 1][f_fl[2]][f_ro[2]]), // 8
10576 hex->face(2)->child_index(
10577 1 -
10578 child_at_origin[hex->face(2)->refinement_case() -
10579 1][f_fl[2]][f_ro[2]]),
10580
10581 hex->face(3)->child_index(
10582 child_at_origin[hex->face(3)->refinement_case() -
10583 1][f_fl[3]][f_ro[3]]), // 10
10584 hex->face(3)->child_index(
10585 1 -
10586 child_at_origin[hex->face(3)->refinement_case() -
10587 1][f_fl[3]][f_ro[3]]),
10588
10589 hex->face(4)->isotropic_child_index(
10591 0, f_or[4], f_fl[4], f_ro[4])), // 12
10592 hex->face(4)->isotropic_child_index(
10594 1, f_or[4], f_fl[4], f_ro[4])),
10595 hex->face(4)->isotropic_child_index(
10597 2, f_or[4], f_fl[4], f_ro[4])),
10598 hex->face(4)->isotropic_child_index(
10600 3, f_or[4], f_fl[4], f_ro[4])),
10601
10602 hex->face(5)->isotropic_child_index(
10604 0, f_or[5], f_fl[5], f_ro[5])), // 16
10605 hex->face(5)->isotropic_child_index(
10607 1, f_or[5], f_fl[5], f_ro[5])),
10608 hex->face(5)->isotropic_child_index(
10610 2, f_or[5], f_fl[5], f_ro[5])),
10611 hex->face(5)->isotropic_child_index(
10613 3, f_or[5], f_fl[5], f_ro[5]))};
10614
10615 new_hexes[0]->set_bounding_object_indices(
10616 {quad_indices[4],
10617 quad_indices[0],
10618 quad_indices[8],
10619 quad_indices[2],
10620 quad_indices[12],
10621 quad_indices[16]});
10622 new_hexes[1]->set_bounding_object_indices(
10623 {quad_indices[0],
10624 quad_indices[6],
10625 quad_indices[9],
10626 quad_indices[3],
10627 quad_indices[13],
10628 quad_indices[17]});
10629 new_hexes[2]->set_bounding_object_indices(
10630 {quad_indices[5],
10631 quad_indices[1],
10632 quad_indices[2],
10633 quad_indices[10],
10634 quad_indices[14],
10635 quad_indices[18]});
10636 new_hexes[3]->set_bounding_object_indices(
10637 {quad_indices[1],
10638 quad_indices[7],
10639 quad_indices[3],
10640 quad_indices[11],
10641 quad_indices[15],
10642 quad_indices[19]});
10643 break;
10644 }
10645
10647 {
10648 //----------------------------
10649 //
10650 // RefinementCase<dim>::cut_xz
10651 //
10652 // the refined cube will look like this:
10653 //
10654 // *----*----*
10655 // / / /|
10656 // / / / |
10657 // / / / *
10658 // *----*----* /|
10659 // | | | / |
10660 // | | |/ *
10661 // *----*----* /
10662 // | | | /
10663 // | | |/
10664 // *----*----*
10665 //
10666
10667 // first, create the new internal line
10668 new_lines[0]->set_bounding_object_indices(
10669 {middle_vertex_index<dim, spacedim>(hex->face(2)),
10670 middle_vertex_index<dim, spacedim>(hex->face(3))});
10671
10672 // again, first collect some data about the
10673 // indices of the lines, with the following
10674 // numbering:
10675
10676 // face 0: left plane
10677 // *
10678 // /|
10679 // / |
10680 // / *
10681 // * /|
10682 // | 0 |
10683 // |/ *
10684 // * /
10685 // | /
10686 // |/
10687 // *
10688 // face 1: right plane
10689 // *
10690 // /|
10691 // / |
10692 // / *
10693 // * /|
10694 // | 1 |
10695 // |/ *
10696 // * /
10697 // | /
10698 // |/
10699 // *
10700 // face 2: front plane
10701 // (note: x,y exchanged)
10702 // *---*---*
10703 // | 5 |
10704 // *-6-*-7-*
10705 // | 4 |
10706 // *---*---*
10707 // face 3: back plane
10708 // (note: x,y exchanged)
10709 // *---*---*
10710 // | 9 |
10711 // *10-*-11*
10712 // | 8 |
10713 // *---*---*
10714 // face 4: bottom plane
10715 // *---*---*
10716 // / / /
10717 // / 2 /
10718 // / / /
10719 // *---*---*
10720 // face 5: top plane
10721 // *---*---*
10722 // / / /
10723 // / 3 /
10724 // / / /
10725 // *---*---*
10726 // middle planes
10727 // *---*---* *-------*
10728 // / / / | |
10729 // / 12 / | |
10730 // / / / | |
10731 // *---*---* *-------*
10732
10733 // set up a list of line iterators first. from
10734 // this, construct lists of line_indices and
10735 // line orientations later on
10736 const typename Triangulation<
10737 dim,
10738 spacedim>::raw_line_iterator lines[13] = {
10739 hex->face(0)->child(0)->line(
10740 (hex->face(0)->refinement_case() ==
10742 1 :
10743 3), // 0
10744 hex->face(1)->child(0)->line(
10745 (hex->face(1)->refinement_case() ==
10747 1 :
10748 3), // 1
10749 hex->face(4)->child(0)->line(
10750 (hex->face(4)->refinement_case() ==
10752 1 :
10753 3), // 2
10754 hex->face(5)->child(0)->line(
10755 (hex->face(5)->refinement_case() ==
10757 1 :
10758 3), // 3
10759
10760 hex->face(2)
10761 ->isotropic_child(
10763 0, f_or[2], f_fl[2], f_ro[2]))
10764 ->line(
10766 3, f_or[2], f_fl[2], f_ro[2])), // 4
10767 hex->face(2)
10768 ->isotropic_child(
10770 3, f_or[2], f_fl[2], f_ro[2]))
10771 ->line(
10773 2, f_or[2], f_fl[2], f_ro[2])), // 5
10774 hex->face(2)
10775 ->isotropic_child(
10777 0, f_or[2], f_fl[2], f_ro[2]))
10778 ->line(
10780 1, f_or[2], f_fl[2], f_ro[2])), // 6
10781 hex->face(2)
10782 ->isotropic_child(
10784 3, f_or[2], f_fl[2], f_ro[2]))
10785 ->line(
10787 0, f_or[2], f_fl[2], f_ro[2])), // 7
10788
10789 hex->face(3)
10790 ->isotropic_child(
10792 0, f_or[3], f_fl[3], f_ro[3]))
10793 ->line(
10795 3, f_or[3], f_fl[3], f_ro[3])), // 8
10796 hex->face(3)
10797 ->isotropic_child(
10799 3, f_or[3], f_fl[3], f_ro[3]))
10800 ->line(
10802 2, f_or[3], f_fl[3], f_ro[3])), // 9
10803 hex->face(3)
10804 ->isotropic_child(
10806 0, f_or[3], f_fl[3], f_ro[3]))
10807 ->line(
10809 1, f_or[3], f_fl[3], f_ro[3])), // 10
10810 hex->face(3)
10811 ->isotropic_child(
10813 3, f_or[3], f_fl[3], f_ro[3]))
10814 ->line(
10816 0, f_or[3], f_fl[3], f_ro[3])), // 11
10817
10818 new_lines[0] // 12
10819 };
10820
10821 unsigned int line_indices[13];
10822 for (unsigned int i = 0; i < 13; ++i)
10823 line_indices[i] = lines[i]->index();
10824
10825 // the orientation of lines for the inner quads
10826 // is quite tricky. as these lines are newly
10827 // created ones and thus have no parents, they
10828 // cannot inherit this property. set up an array
10829 // and fill it with the respective values
10830 types::geometric_orientation line_orientation[13]{};
10831
10832 // the middle vertices of the
10833 // lines of our front face
10834 const unsigned int middle_vertices[4] = {
10835 hex->line(8)->child(0)->vertex_index(1),
10836 hex->line(9)->child(0)->vertex_index(1),
10837 hex->line(2)->child(0)->vertex_index(1),
10838 hex->line(6)->child(0)->vertex_index(1),
10839 };
10840
10841 // note: for lines 0 to 3 the orientation of the
10842 // line is 'true', if vertex 0 is on the front
10843 for (unsigned int i = 0; i < 4; ++i)
10844 if (lines[i]->vertex_index(0) == middle_vertices[i])
10845 line_orientation[i] =
10847 else
10848 {
10849 // it must be the other way round then
10850 Assert(lines[i]->vertex_index(1) ==
10851 middle_vertices[i],
10853 line_orientation[i] =
10855 }
10856
10857 // note: for lines 4 to 11 (inner lines of the
10858 // outer quads) the following holds: the second
10859 // vertex of the even lines in standard
10860 // orientation is the vertex in the middle of
10861 // the quad, whereas for odd lines the first
10862 // vertex is the same middle vertex.
10863 for (unsigned int i = 4; i < 12; ++i)
10864 if (lines[i]->vertex_index((i + 1) % 2) ==
10865 middle_vertex_index<dim, spacedim>(
10866 hex->face(1 + i / 4)))
10867 line_orientation[i] =
10869 else
10870 {
10871 // it must be the other way
10872 // round then
10873 Assert(lines[i]->vertex_index(i % 2) ==
10874 (middle_vertex_index<dim, spacedim>(
10875 hex->face(1 + i / 4))),
10877 line_orientation[i] =
10879 }
10880 // for the last line the line orientation is
10881 // always true, since it was just constructed
10882 // that way
10883 line_orientation[12] =
10885
10886 // set up the 4 quads, numbered as follows (left
10887 // quad numbering, right line numbering
10888 // extracted from above), the drawings denote
10889 // middle planes
10890 //
10891 // * *
10892 // /| /|
10893 // / | 3 9
10894 // y/ * / *
10895 // * 3/| * /|
10896 // | / |x 5 12|8
10897 // |/ * |/ *
10898 // * 2/ * /
10899 // | / 4 2
10900 // |/ |/
10901 // * *
10902 //
10903 // y
10904 // *----*----* *-10-*-11-*
10905 // / / / / / /
10906 // / 0 / 1 / 0 12 1
10907 // / / / / / /
10908 // *----*----*x *--6-*--7-*
10909
10910 new_quads[0]->set_bounding_object_indices(
10911 {line_indices[0],
10912 line_indices[12],
10913 line_indices[6],
10914 line_indices[10]});
10915 new_quads[1]->set_bounding_object_indices(
10916 {line_indices[12],
10917 line_indices[1],
10918 line_indices[7],
10919 line_indices[11]});
10920 new_quads[2]->set_bounding_object_indices(
10921 {line_indices[4],
10922 line_indices[8],
10923 line_indices[2],
10924 line_indices[12]});
10925 new_quads[3]->set_bounding_object_indices(
10926 {line_indices[5],
10927 line_indices[9],
10928 line_indices[12],
10929 line_indices[3]});
10930
10931 new_quads[0]->set_line_orientation(
10932 0, line_orientation[0]);
10933 new_quads[0]->set_line_orientation(
10934 2, line_orientation[6]);
10935 new_quads[0]->set_line_orientation(
10936 3, line_orientation[10]);
10937
10938 new_quads[1]->set_line_orientation(
10939 1, line_orientation[1]);
10940 new_quads[1]->set_line_orientation(
10941 2, line_orientation[7]);
10942 new_quads[1]->set_line_orientation(
10943 3, line_orientation[11]);
10944
10945 new_quads[2]->set_line_orientation(
10946 0, line_orientation[4]);
10947 new_quads[2]->set_line_orientation(
10948 1, line_orientation[8]);
10949 new_quads[2]->set_line_orientation(
10950 2, line_orientation[2]);
10951
10952 new_quads[3]->set_line_orientation(
10953 0, line_orientation[5]);
10954 new_quads[3]->set_line_orientation(
10955 1, line_orientation[9]);
10956 new_quads[3]->set_line_orientation(
10957 3, line_orientation[3]);
10958
10959 // the quads are numbered as follows:
10960 //
10961 // planes in the interior of the old hex:
10962 //
10963 // *
10964 // /|
10965 // / | x
10966 // /3 * *-------* *----*----*
10967 // * /| | | / / /
10968 // | / | | | / 0 / 1 /
10969 // |/ * | | / / /
10970 // * 2/ *-------*y *----*----*x
10971 // | /
10972 // |/
10973 // *
10974 //
10975 // children of the faces
10976 // of the old hex
10977 // *---*---* *---*---*
10978 // /|13 | 15| / / /|
10979 // / | | | /18 / 19/ |
10980 // / *---*---* / / / *
10981 // * 5/| | | *---*---* 7/|
10982 // | / |12 | 14| | 9 | 11| / |
10983 // |/4 *---*---* | | |/6 *
10984 // * / / / *---*---* /
10985 // | /16 / 17/ | | | /
10986 // |/ / / | 8 | 10|/
10987 // *---*---* *---*---*
10988 //
10989 // note that we have to take care of the
10990 // orientation of faces.
10991 const int quad_indices[20] = {
10992 new_quads[0]->index(), // 0
10993 new_quads[1]->index(),
10994 new_quads[2]->index(),
10995 new_quads[3]->index(),
10996
10997 hex->face(0)->child_index(
10998 child_at_origin[hex->face(0)->refinement_case() -
10999 1][f_fl[0]][f_ro[0]]), // 4
11000 hex->face(0)->child_index(
11001 1 -
11002 child_at_origin[hex->face(0)->refinement_case() -
11003 1][f_fl[0]][f_ro[0]]),
11004
11005 hex->face(1)->child_index(
11006 child_at_origin[hex->face(1)->refinement_case() -
11007 1][f_fl[1]][f_ro[1]]), // 6
11008 hex->face(1)->child_index(
11009 1 -
11010 child_at_origin[hex->face(1)->refinement_case() -
11011 1][f_fl[1]][f_ro[1]]),
11012
11013 hex->face(2)->isotropic_child_index(
11015 0, f_or[2], f_fl[2], f_ro[2])), // 8
11016 hex->face(2)->isotropic_child_index(
11018 1, f_or[2], f_fl[2], f_ro[2])),
11019 hex->face(2)->isotropic_child_index(
11021 2, f_or[2], f_fl[2], f_ro[2])),
11022 hex->face(2)->isotropic_child_index(
11024 3, f_or[2], f_fl[2], f_ro[2])),
11025
11026 hex->face(3)->isotropic_child_index(
11028 0, f_or[3], f_fl[3], f_ro[3])), // 12
11029 hex->face(3)->isotropic_child_index(
11031 1, f_or[3], f_fl[3], f_ro[3])),
11032 hex->face(3)->isotropic_child_index(
11034 2, f_or[3], f_fl[3], f_ro[3])),
11035 hex->face(3)->isotropic_child_index(
11037 3, f_or[3], f_fl[3], f_ro[3])),
11038
11039 hex->face(4)->child_index(
11040 child_at_origin[hex->face(4)->refinement_case() -
11041 1][f_fl[4]][f_ro[4]]), // 16
11042 hex->face(4)->child_index(
11043 1 -
11044 child_at_origin[hex->face(4)->refinement_case() -
11045 1][f_fl[4]][f_ro[4]]),
11046
11047 hex->face(5)->child_index(
11048 child_at_origin[hex->face(5)->refinement_case() -
11049 1][f_fl[5]][f_ro[5]]), // 18
11050 hex->face(5)->child_index(
11051 1 -
11052 child_at_origin[hex->face(5)->refinement_case() -
11053 1][f_fl[5]][f_ro[5]])};
11054
11055 // due to the exchange of x and y for the front
11056 // and back face, we order the children
11057 // according to
11058 //
11059 // *---*---*
11060 // | 1 | 3 |
11061 // *---*---*
11062 // | 0 | 2 |
11063 // *---*---*
11064 new_hexes[0]->set_bounding_object_indices(
11065 {quad_indices[4],
11066 quad_indices[2],
11067 quad_indices[8],
11068 quad_indices[12],
11069 quad_indices[16],
11070 quad_indices[0]});
11071 new_hexes[1]->set_bounding_object_indices(
11072 {quad_indices[5],
11073 quad_indices[3],
11074 quad_indices[9],
11075 quad_indices[13],
11076 quad_indices[0],
11077 quad_indices[18]});
11078 new_hexes[2]->set_bounding_object_indices(
11079 {quad_indices[2],
11080 quad_indices[6],
11081 quad_indices[10],
11082 quad_indices[14],
11083 quad_indices[17],
11084 quad_indices[1]});
11085 new_hexes[3]->set_bounding_object_indices(
11086 {quad_indices[3],
11087 quad_indices[7],
11088 quad_indices[11],
11089 quad_indices[15],
11090 quad_indices[1],
11091 quad_indices[19]});
11092 break;
11093 }
11094
11096 {
11097 //----------------------------
11098 //
11099 // RefinementCase<dim>::cut_yz
11100 //
11101 // the refined cube will look like this:
11102 //
11103 // *---------*
11104 // / /|
11105 // *---------* |
11106 // / /| |
11107 // *---------* |/|
11108 // | | * |
11109 // | |/| *
11110 // *---------* |/
11111 // | | *
11112 // | |/
11113 // *---------*
11114 //
11115
11116 // first, create the new
11117 // internal line
11118 new_lines[0]->set_bounding_object_indices(
11119
11120 {middle_vertex_index<dim, spacedim>(hex->face(0)),
11121 middle_vertex_index<dim, spacedim>(hex->face(1))});
11122
11123 // again, first collect some data about the
11124 // indices of the lines, with the following
11125 // numbering: (note that face 0 and 1 each are
11126 // shown twice for better readability)
11127
11128 // face 0: left plane
11129 // * *
11130 // /| /|
11131 // * | * |
11132 // /| * /| *
11133 // * 5/| * |7|
11134 // | * | | * |
11135 // |/| * |6| *
11136 // * 4/ * |/
11137 // | * | *
11138 // |/ |/
11139 // * *
11140 // face 1: right plane
11141 // * *
11142 // /| /|
11143 // * | * |
11144 // /| * /| *
11145 // * 9/| * |11
11146 // | * | | * |
11147 // |/| * |10 *
11148 // * 8/ * |/
11149 // | * | *
11150 // |/ |/
11151 // * *
11152 // face 2: front plane
11153 // (note: x,y exchanged)
11154 // *-------*
11155 // | |
11156 // *---0---*
11157 // | |
11158 // *-------*
11159 // face 3: back plane
11160 // (note: x,y exchanged)
11161 // *-------*
11162 // | |
11163 // *---1---*
11164 // | |
11165 // *-------*
11166 // face 4: bottom plane
11167 // *-------*
11168 // / /
11169 // *---2---*
11170 // / /
11171 // *-------*
11172 // face 5: top plane
11173 // *-------*
11174 // / /
11175 // *---3---*
11176 // / /
11177 // *-------*
11178 // middle planes
11179 // *-------* *-------*
11180 // / / | |
11181 // *---12--* | |
11182 // / / | |
11183 // *-------* *-------*
11184
11185 // set up a list of line iterators first. from
11186 // this, construct lists of line_indices and
11187 // line orientations later on
11188 const typename Triangulation<
11189 dim,
11190 spacedim>::raw_line_iterator lines[13] = {
11191 hex->face(2)->child(0)->line(
11192 (hex->face(2)->refinement_case() ==
11194 1 :
11195 3), // 0
11196 hex->face(3)->child(0)->line(
11197 (hex->face(3)->refinement_case() ==
11199 1 :
11200 3), // 1
11201 hex->face(4)->child(0)->line(
11202 (hex->face(4)->refinement_case() ==
11204 1 :
11205 3), // 2
11206 hex->face(5)->child(0)->line(
11207 (hex->face(5)->refinement_case() ==
11209 1 :
11210 3), // 3
11211
11212 hex->face(0)
11213 ->isotropic_child(
11215 0, f_or[0], f_fl[0], f_ro[0]))
11216 ->line(
11218 1, f_or[0], f_fl[0], f_ro[0])), // 4
11219 hex->face(0)
11220 ->isotropic_child(
11222 3, f_or[0], f_fl[0], f_ro[0]))
11223 ->line(
11225 0, f_or[0], f_fl[0], f_ro[0])), // 5
11226 hex->face(0)
11227 ->isotropic_child(
11229 0, f_or[0], f_fl[0], f_ro[0]))
11230 ->line(
11232 3, f_or[0], f_fl[0], f_ro[0])), // 6
11233 hex->face(0)
11234 ->isotropic_child(
11236 3, f_or[0], f_fl[0], f_ro[0]))
11237 ->line(
11239 2, f_or[0], f_fl[0], f_ro[0])), // 7
11240
11241 hex->face(1)
11242 ->isotropic_child(
11244 0, f_or[1], f_fl[1], f_ro[1]))
11245 ->line(
11247 1, f_or[1], f_fl[1], f_ro[1])), // 8
11248 hex->face(1)
11249 ->isotropic_child(
11251 3, f_or[1], f_fl[1], f_ro[1]))
11252 ->line(
11254 0, f_or[1], f_fl[1], f_ro[1])), // 9
11255 hex->face(1)
11256 ->isotropic_child(
11258 0, f_or[1], f_fl[1], f_ro[1]))
11259 ->line(
11261 3, f_or[1], f_fl[1], f_ro[1])), // 10
11262 hex->face(1)
11263 ->isotropic_child(
11265 3, f_or[1], f_fl[1], f_ro[1]))
11266 ->line(
11268 2, f_or[1], f_fl[1], f_ro[1])), // 11
11269
11270 new_lines[0] // 12
11271 };
11272
11273 unsigned int line_indices[13];
11274
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(
11605 {vertex_indices[2], vertex_indices[6]});
11606 new_lines[1]->set_bounding_object_indices(
11607 {vertex_indices[6], vertex_indices[3]});
11608 new_lines[2]->set_bounding_object_indices(
11609 {vertex_indices[0], vertex_indices[6]});
11610 new_lines[3]->set_bounding_object_indices(
11611 {vertex_indices[6], vertex_indices[1]});
11612 new_lines[4]->set_bounding_object_indices(
11613 {vertex_indices[4], vertex_indices[6]});
11614 new_lines[5]->set_bounding_object_indices(
11615 {vertex_indices[6], vertex_indices[5]});
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 unsigned 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()
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 =
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>
12742 {
12743 std::vector<std::pair<unsigned int, unsigned int>> adjacent_cells(
12744 2 * triangulation.n_raw_faces(),
12745 {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int});
12746
12747 const auto set_entry = [&](const auto &face_index, const auto &cell) {
12748 const std::pair<unsigned int, unsigned int> cell_pair = {
12749 cell->level(), cell->index()};
12750 unsigned int index;
12751
12752 if (adjacent_cells[2 * face_index].first ==
12754 adjacent_cells[2 * face_index].second ==
12756 {
12757 index = 2 * face_index + 0;
12758 }
12759 else
12760 {
12761 Assert(((adjacent_cells[2 * face_index + 1].first ==
12763 (adjacent_cells[2 * face_index + 1].second ==
12766 index = 2 * face_index + 1;
12767 }
12768
12769 adjacent_cells[index] = cell_pair;
12770 };
12771
12772 const auto get_entry =
12773 [&](const auto &face_index,
12774 const auto &cell) -> TriaIterator<CellAccessor<dim, spacedim>> {
12775 auto test = adjacent_cells[2 * face_index];
12776
12777 if (test == std::pair<unsigned int, unsigned int>(cell->level(),
12778 cell->index()))
12779 test = adjacent_cells[2 * face_index + 1];
12780
12781 if ((test.first != numbers::invalid_unsigned_int) &&
12782 (test.second != numbers::invalid_unsigned_int))
12783 return TriaIterator<CellAccessor<dim, spacedim>>(&triangulation,
12784 test.first,
12785 test.second);
12786 else
12788 };
12789
12790 for (const auto &cell : triangulation.cell_iterators())
12791 for (const auto &face : cell->face_iterators())
12792 {
12793 set_entry(face->index(), cell);
12794
12795 if (cell->is_active() && face->has_children())
12796 for (unsigned int c = 0; c < face->n_children(); ++c)
12797 set_entry(face->child(c)->index(), cell);
12798 }
12799
12800 for (const auto &cell : triangulation.cell_iterators())
12801 for (auto f : cell->face_indices())
12802 cell->set_neighbor(f, get_entry(cell->face(f)->index(), cell));
12803 }
12804
12805 template <int dim, int spacedim>
12806 static void
12808 Triangulation<dim, spacedim> & /*triangulation*/,
12810 std::vector<unsigned int> & /*line_cell_count*/,
12811 std::vector<unsigned int> & /*quad_cell_count*/)
12812 {
12814 }
12815
12816 template <int dim, int spacedim>
12819 const bool check_for_distorted_cells)
12820 {
12822 triangulation, check_for_distorted_cells);
12823 }
12824
12825 template <int dim, int spacedim>
12826 static void
12828 Triangulation<dim, spacedim> & /*triangulation*/)
12829 {
12830 // nothing to do since anisotropy is not supported
12831 }
12832
12833 template <int dim, int spacedim>
12834 static void
12840
12841 template <int dim, int spacedim>
12842 static bool
12845 {
12847
12848 return false;
12849 }
12850 };
12851 } // namespace TriangulationImplementation
12852} // namespace internal
12853
12854#ifndef DOXYGEN
12855
12856template <int dim, int spacedim>
12859
12860
12861
12862template <int dim, int spacedim>
12865 const MeshSmoothing smooth_grid,
12866 const bool check_for_distorted_cells)
12867 : cell_attached_data({0, 0, {}, {}})
12868 , smooth_grid(smooth_grid)
12869 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12870 , anisotropic_refinement(false)
12871 , check_for_distorted_cells(check_for_distorted_cells)
12872{
12873 if (dim == 1)
12874 {
12875 vertex_to_boundary_id_map_1d =
12876 std::make_unique<std::map<unsigned int, types::boundary_id>>();
12877 vertex_to_manifold_id_map_1d =
12878 std::make_unique<std::map<unsigned int, types::manifold_id>>();
12879 }
12880
12881 // connect the any_change signal to the other top level signals
12882 signals.create.connect(signals.any_change);
12883 signals.post_refinement.connect(signals.any_change);
12884 signals.clear.connect(signals.any_change);
12885 signals.mesh_movement.connect(signals.any_change);
12886}
12887
12888
12889
12890template <int dim, int spacedim>
12891DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
12893 Triangulation<dim, spacedim> &&tria) noexcept
12894 : EnableObserverPointer(std::move(tria))
12895 , cell_attached_data(std::move(tria.cell_attached_data))
12896 , smooth_grid(tria.smooth_grid)
12897 , reference_cells(std::move(tria.reference_cells))
12898 , strides(tria.strides)
12899 , periodic_face_pairs_level_0(std::move(tria.periodic_face_pairs_level_0))
12900 , periodic_face_map(std::move(tria.periodic_face_map))
12901 , levels(std::move(tria.levels))
12902 , faces(std::move(tria.faces))
12903 , vertices(std::move(tria.vertices))
12904 , vertices_used(std::move(tria.vertices_used))
12905 , manifolds(std::move(tria.manifolds))
12906 , default_flat_manifold(std::make_unique<const FlatManifold<dim, spacedim>>())
12907 , anisotropic_refinement(tria.anisotropic_refinement)
12908 , check_for_distorted_cells(tria.check_for_distorted_cells)
12909 , number_cache(std::move(tria.number_cache))
12910 , vertex_to_boundary_id_map_1d(std::move(tria.vertex_to_boundary_id_map_1d))
12911 , vertex_to_manifold_id_map_1d(std::move(tria.vertex_to_manifold_id_map_1d))
12912{
12913 tria.number_cache = internal::TriangulationImplementation::NumberCache<dim>();
12914 tria.strides = {};
12915
12916 if (tria.policy)
12917 this->policy = tria.policy->clone();
12918}
12919
12920
12921template <int dim, int spacedim>
12922DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
12924 Triangulation<dim, spacedim> &&tria) noexcept
12925{
12926 EnableObserverPointer::operator=(std::move(tria));
12927
12928 cell_attached_data = std::move(tria.cell_attached_data);
12929 smooth_grid = tria.smooth_grid;
12930 reference_cells = std::move(tria.reference_cells);
12931 strides = tria.strides;
12932 periodic_face_pairs_level_0 = std::move(tria.periodic_face_pairs_level_0);
12933 periodic_face_map = std::move(tria.periodic_face_map);
12934 levels = std::move(tria.levels);
12935 faces = std::move(tria.faces);
12936 vertices = std::move(tria.vertices);
12937 vertices_used = std::move(tria.vertices_used);
12938 manifolds = std::move(tria.manifolds);
12939 anisotropic_refinement = tria.anisotropic_refinement;
12940 number_cache = tria.number_cache;
12941 vertex_to_boundary_id_map_1d = std::move(tria.vertex_to_boundary_id_map_1d);
12942 vertex_to_manifold_id_map_1d = std::move(tria.vertex_to_manifold_id_map_1d);
12943
12944 tria.number_cache = internal::TriangulationImplementation::NumberCache<dim>();
12945 tria.strides = {};
12946
12947 if (tria.policy)
12948 this->policy = tria.policy->clone();
12949
12950 return *this;
12951}
12952
12953
12954
12955template <int dim, int spacedim>
12956DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
12958{
12959 // notify listeners that the triangulation is going down...
12960 try
12961 {
12962 signals.clear();
12963 }
12964 catch (...)
12965 {}
12966
12967 levels.clear();
12968
12969 // the vertex_to_boundary_id_map_1d field should be unused except in
12970 // 1d. double check this here, as destruction is a good place to
12971 // ensure that what we've done over the course of the lifetime of
12972 // this object makes sense
12973 AssertNothrow((dim == 1) || (vertex_to_boundary_id_map_1d == nullptr),
12975
12976 // the vertex_to_manifold_id_map_1d field should be also unused
12977 // except in 1d. check this as well
12978 AssertNothrow((dim == 1) || (vertex_to_manifold_id_map_1d == nullptr),
12980}
12981
12982
12983
12984template <int dim, int spacedim>
12985DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
12987{
12988 // notify listeners that the triangulation is going down...
12989 signals.clear();
12990
12991 // ...and then actually clear all content of it
12992 clear_despite_subscriptions();
12993 periodic_face_pairs_level_0.clear();
12994 periodic_face_map.clear();
12995 reference_cells.clear();
12996
12997 cell_attached_data = {0, 0, {}, {}};
12998 data_serializer.clear();
12999}
13000
13001template <int dim, int spacedim>
13002DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13004{
13005 return MPI_COMM_SELF;
13006}
13007
13008
13009
13010template <int dim, int spacedim>
13011DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13013{
13014 return get_mpi_communicator();
13015}
13016
13017
13018
13019template <int dim, int spacedim>
13020DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13021std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13023{
13024 return number_cache.active_cell_index_partitioner;
13025}
13026
13027
13028
13029template <int dim, int spacedim>
13030DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13031std::weak_ptr<const Utilities::MPI::Partitioner> Triangulation<dim, spacedim>::
13032 global_level_cell_index_partitioner(const unsigned int level) const
13033{
13034 AssertIndexRange(level, this->n_levels());
13035
13036 return number_cache.level_cell_index_partitioners[level];
13037}
13038
13039
13040
13041template <int dim, int spacedim>
13042DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13044 const MeshSmoothing mesh_smoothing)
13045{
13046 smooth_grid = mesh_smoothing;
13047}
13048
13049
13050
13051template <int dim, int spacedim>
13052DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13055{
13056 return smooth_grid;
13057}
13058
13059
13060
13061template <int dim, int spacedim>
13062DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13064 const types::manifold_id m_number,
13065 const Manifold<dim, spacedim> &manifold_object)
13066{
13068
13069 manifolds[m_number] = manifold_object.clone();
13070}
13071
13072
13073
13074template <int dim, int spacedim>
13075DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13077 const types::manifold_id m_number)
13078{
13080
13081 // delete the entry located at number.
13082 manifolds[m_number] = default_flat_manifold->clone();
13083}
13084
13085
13086template <int dim, int spacedim>
13087DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13089{
13090 for (auto &m : manifolds)
13091 m.second = default_flat_manifold->clone();
13092}
13093
13094
13095template <int dim, int spacedim>
13096DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13098 const types::manifold_id m_number)
13099{
13100 Assert(
13101 n_cells() > 0,
13102 ExcMessage(
13103 "Error: set_all_manifold_ids() can not be called on an empty Triangulation."));
13104
13105 for (const auto &cell : this->active_cell_iterators())
13106 cell->set_all_manifold_ids(m_number);
13107}
13108
13109
13110template <int dim, int spacedim>
13111DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13113 const types::manifold_id m_number)
13114{
13115 Assert(
13116 n_cells() > 0,
13117 ExcMessage(
13118 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13119
13120 for (const auto &cell : this->active_cell_iterators())
13121 for (auto f : GeometryInfo<dim>::face_indices())
13122 if (cell->face(f)->at_boundary())
13123 cell->face(f)->set_all_manifold_ids(m_number);
13124}
13125
13126
13127template <int dim, int spacedim>
13128DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13130 const types::boundary_id b_id,
13131 const types::manifold_id m_number)
13132{
13133 Assert(
13134 n_cells() > 0,
13135 ExcMessage(
13136 "Error: set_all_manifold_ids_on_boundary() can not be called on an empty Triangulation."));
13137
13138 bool boundary_found = false;
13139 for (const auto &cell : this->active_cell_iterators())
13140 {
13141 // loop on faces
13142 for (auto f : GeometryInfo<dim>::face_indices())
13143 if (cell->face(f)->at_boundary() &&
13144 cell->face(f)->boundary_id() == b_id)
13145 {
13146 boundary_found = true;
13147 cell->face(f)->set_manifold_id(m_number);
13148 }
13149
13150 // loop on edges if dim >= 3
13151 if (dim >= 3)
13152 for (unsigned int e = 0; e < GeometryInfo<dim>::lines_per_cell; ++e)
13153 if (cell->line(e)->at_boundary() &&
13154 cell->line(e)->boundary_id() == b_id)
13155 {
13156 boundary_found = true;
13157 cell->line(e)->set_manifold_id(m_number);
13158 }
13159 }
13160
13161 Assert(boundary_found, ExcBoundaryIdNotFound(b_id));
13162}
13163
13164
13165
13166template <int dim, int spacedim>
13167DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13168const Manifold<dim, spacedim> &Triangulation<dim, spacedim>::get_manifold(
13169 const types::manifold_id m_number) const
13170{
13171 // check if flat manifold has been queried
13172 if (m_number == numbers::flat_manifold_id)
13173 return *default_flat_manifold;
13174
13175 // look, if there is a manifold stored at
13176 // manifold_id number.
13177 const auto it = manifolds.find(m_number);
13178
13179 if (it != manifolds.end())
13180 {
13181 // if we have found an entry, return it
13182 return *(it->second);
13183 }
13184
13185 Assert(
13186 false,
13187 ExcMessage(
13188 "No manifold of the manifold id " + std::to_string(m_number) +
13189 " has been attached to the triangulation. "
13190 "Please attach the right manifold with Triangulation::set_manifold()."));
13191
13192 return *default_flat_manifold; // never reached
13193}
13194
13195
13196
13197template <int dim, int spacedim>
13198DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13199std::vector<types::boundary_id> Triangulation<dim, spacedim>::get_boundary_ids()
13200 const
13201{
13202 std::set<types::boundary_id> boundary_ids;
13203 for (const auto &cell : active_cell_iterators())
13204 if (cell->is_locally_owned())
13205 for (const auto &face : cell->face_indices())
13206 if (cell->at_boundary(face))
13207 boundary_ids.insert(cell->face(face)->boundary_id());
13208
13209 return {boundary_ids.begin(), boundary_ids.end()};
13210}
13211
13212
13213
13214template <int dim, int spacedim>
13215DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13216std::vector<types::manifold_id> Triangulation<dim, spacedim>::get_manifold_ids()
13217 const
13218{
13219 std::set<types::manifold_id> m_ids;
13220 for (const auto &cell : active_cell_iterators())
13221 if (cell->is_locally_owned())
13222 {
13223 m_ids.insert(cell->manifold_id());
13224 for (const auto &face : cell->face_iterators())
13225 m_ids.insert(face->manifold_id());
13226 if (dim == 3)
13227 {
13228 const auto line_indices = internal::TriaAccessorImplementation::
13229 Implementation::get_line_indices_of_cell(*cell);
13230 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13231 {
13232 raw_line_iterator line(this, 0, line_indices[l]);
13233 m_ids.insert(line->manifold_id());
13234 }
13235 }
13236 }
13237 return {m_ids.begin(), m_ids.end()};
13238}
13239
13240#endif
13241/*-----------------------------------------------------------------*/
13242
13243#ifndef DOXYGEN
13244
13245template <int dim, int spacedim>
13246DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13248 const Triangulation<dim, spacedim> &other_tria)
13249{
13250 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13251 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13252 Assert((other_tria.levels.size() != 0) && (other_tria.vertices.size() != 0) &&
13253 (dim == 1 || other_tria.faces != nullptr),
13254 ExcMessage(
13255 "When calling Triangulation::copy_triangulation(), "
13256 "the target triangulation must be empty but the source "
13257 "triangulation (the argument to this function) must contain "
13258 "something. Here, it seems like the source does not "
13259 "contain anything at all."));
13260
13261
13262 // copy normal elements
13263 vertices = other_tria.vertices;
13264 vertices_used = other_tria.vertices_used;
13265 anisotropic_refinement = other_tria.anisotropic_refinement;
13266 smooth_grid = other_tria.smooth_grid;
13267 reference_cells = other_tria.reference_cells;
13268 strides = other_tria.strides;
13269
13270 if (dim > 1)
13271 faces =
13272 std::make_unique<internal::TriangulationImplementation::TriaFaces<dim>>(
13273 *other_tria.faces);
13274
13275 for (const auto &p : other_tria.manifolds)
13276 set_manifold(p.first, *p.second);
13277
13278
13279 Assert(other_tria.levels.size() <= numbers::max_n_levels, ExcInternalError());
13280 levels.reserve(other_tria.levels.size());
13281 for (const auto &level : other_tria.levels)
13282 levels.push_back(
13283 std::make_unique<
13284 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>(
13285 *level));
13286
13287 number_cache = other_tria.number_cache;
13288
13289 if (dim == 1)
13290 {
13291 vertex_to_boundary_id_map_1d =
13292 std::make_unique<std::map<unsigned int, types::boundary_id>>(
13293 *other_tria.vertex_to_boundary_id_map_1d);
13294
13295 vertex_to_manifold_id_map_1d =
13296 std::make_unique<std::map<unsigned int, types::manifold_id>>(
13297 *other_tria.vertex_to_manifold_id_map_1d);
13298 }
13299
13300 if (other_tria.policy)
13301 this->policy = other_tria.policy->clone();
13302
13303 // periodic faces
13304 this->periodic_face_pairs_level_0.reserve(
13305 other_tria.periodic_face_pairs_level_0.size());
13306
13307 for (const auto &other_entry : other_tria.periodic_face_pairs_level_0)
13308 {
13309 auto entry = other_entry;
13310 entry.cell[0] =
13311 cell_iterator(this, entry.cell[0]->level(), entry.cell[0]->index());
13312 entry.cell[1] =
13313 cell_iterator(this, entry.cell[1]->level(), entry.cell[1]->index());
13314 periodic_face_pairs_level_0.emplace_back(entry);
13315 }
13316
13317 for (auto [first_cell_, second_cell_and_orientation] :
13318 other_tria.periodic_face_map)
13319 {
13320 auto first_cell = first_cell_; // make copy since key is const
13321 first_cell.first = cell_iterator(this,
13322 first_cell.first->level(),
13323 first_cell.first->index());
13324 second_cell_and_orientation.first.first =
13325 cell_iterator(this,
13326 second_cell_and_orientation.first.first->level(),
13327 second_cell_and_orientation.first.first->index());
13328
13329 this->periodic_face_map[first_cell] = second_cell_and_orientation;
13330 }
13331
13332 // inform those who are listening on other_tria of the copy operation
13333 other_tria.signals.copy(*this);
13334 // also inform all listeners of the current triangulation that the
13335 // triangulation has been created
13336 signals.create();
13337
13338 // note that we need not copy the
13339 // subscriptor!
13340}
13341
13342
13343
13344template <int dim, int spacedim>
13345DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13347{
13348 if (this->all_reference_cells_are_hyper_cube())
13349 {
13350 this->policy =
13351 std::make_unique<internal::TriangulationImplementation::PolicyWrapper<
13352 dim,
13353 spacedim,
13354 internal::TriangulationImplementation::Implementation>>();
13355 }
13356 else
13357 {
13358 this->policy =
13359 std::make_unique<internal::TriangulationImplementation::PolicyWrapper<
13360 dim,
13361 spacedim,
13362 internal::TriangulationImplementation::ImplementationMixedMesh>>();
13363 }
13364}
13365
13366
13367
13368template <int dim, int spacedim>
13369DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13371 const std::vector<Point<spacedim>> &v,
13372 const std::vector<CellData<dim>> &cells,
13373 const SubCellData &subcelldata)
13374{
13375 Assert((vertices.empty()) && (levels.empty()) && (faces == nullptr),
13376 ExcTriangulationNotEmpty(vertices.size(), levels.size()));
13377 // check that no forbidden arrays
13378 // are used
13379 Assert(subcelldata.check_consistency(dim), ExcInternalError());
13380
13381 // try to create a triangulation; if this fails, we still want to
13382 // throw an exception but if we just do so we'll get into trouble
13383 // because sometimes other objects are already attached to it:
13384 try
13385 {
13387 create_triangulation(v, cells, subcelldata, *this);
13388 }
13389 catch (...)
13390 {
13391 clear_despite_subscriptions();
13392 throw;
13393 }
13394
13395 reset_policy();
13396
13397 // update our counts of the various elements of a triangulation, and set
13398 // active_cell_indices of all cells
13399 reset_cell_vertex_indices_cache();
13401 *this, levels.size(), number_cache);
13402 reset_active_cell_indices();
13403 reset_global_cell_indices();
13404
13405 // now verify that there are indeed no distorted cells. as per the
13406 // documentation of this class, we first collect all distorted cells
13407 // and then throw an exception if there are any
13408 if (check_for_distorted_cells)
13409 {
13410 DistortedCellList distorted_cells = collect_distorted_coarse_cells(*this);
13411 // throw the array (and fill the various location fields) if
13412 // there are distorted cells. otherwise, just fall off the end
13413 // of the function
13414 AssertThrow(distorted_cells.distorted_cells.empty(), distorted_cells);
13415 }
13416
13417
13418 /*
13419 When the triangulation is a manifold (dim < spacedim) and made of
13420 quadrilaterals, the normal field provided from the map class depends on
13421 the order of the vertices. It may happen that this normal field is
13422 discontinuous. The following code takes care that this is not the case by
13423 setting the cell direction flag on those cell that produce the wrong
13424 orientation.
13425
13426 To determine if 2 neighbors have the same or opposite orientation we use
13427 a truth table. Its entries are indexed by the local indices of the
13428 common face. For example if two elements share a face, and this face is
13429 face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
13430 whether the orientation are the same (true) or opposite (false).
13431
13432 Even though there may be a combinatorial/graph theory argument to get this
13433 table in any dimension, I tested by hand all the different possible cases
13434 in 1D and 2D to generate the table.
13435
13436 Assuming that a surface respects the standard orientation for 2d meshes,
13437 the truth tables are symmetric and their true values are the following
13438
13439 - 1D curves: (0,1)
13440 - 2D surface: (0,1),(0,2),(1,3),(2,3)
13441
13442 We store this data using an n_faces x n_faces full matrix, which is
13443 actually much bigger than the minimal data required, but it makes the code
13444 more readable.
13445
13446 */
13447 if ((dim == spacedim - 1) && all_reference_cells_are_hyper_cube())
13448 {
13449 Table<2, bool> correct(GeometryInfo<dim>::faces_per_cell,
13451 switch (dim)
13452 {
13453 case 1:
13454 {
13455 const bool values[][2] = {{false, true}, {true, false}};
13456 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13457 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13458 correct(i, j) = values[i][j];
13459 break;
13460 }
13461 case 2:
13462 {
13463 const bool values[][4] = {{false, true, true, false},
13464 {true, false, false, true},
13465 {true, false, false, true},
13466 {false, true, true, false}};
13467 for (const unsigned int i : GeometryInfo<dim>::face_indices())
13468 for (const unsigned int j : GeometryInfo<dim>::face_indices())
13469 correct(i, j) = (values[i][j]);
13470 break;
13471 }
13472 default:
13474 }
13475
13476
13477 std::list<active_cell_iterator> this_round, next_round;
13478 active_cell_iterator neighbor;
13479
13480 // Start with the first cell and (arbitrarily) decide that its
13481 // direction flag should be 'true':
13482 this_round.push_back(begin_active());
13483 begin_active()->set_direction_flag(true);
13484 begin_active()->set_user_flag();
13485
13486 while (this_round.size() > 0)
13487 {
13488 for (const auto &cell : this_round)
13489 {
13490 for (const unsigned int i : cell->face_indices())
13491 {
13492 if (cell->face(i)->at_boundary() == false)
13493 {
13494 // Consider the i'th neighbor of a cell for
13495 // which we have already set the direction:
13496 neighbor = cell->neighbor(i);
13497
13498 const unsigned int nb_of_nb =
13499 cell->neighbor_of_neighbor(i);
13500
13501 // If we already saw this neighboring cell,
13502 // check that everything is fine:
13503 if (neighbor->user_flag_set())
13504 {
13505 Assert(
13506 !(correct(i, nb_of_nb) ^
13507 (neighbor->direction_flag() ==
13508 cell->direction_flag())),
13509 ExcMessage(
13510 "The triangulation you are trying to create is not orientable."));
13511 }
13512 else
13513 {
13514 // We had not seen this cell yet. Set its
13515 // orientation flag (if necessary), mark it
13516 // as treated via the user flag, and push it
13517 // onto the list of cells to start work from
13518 // the next time around:
13519 if (correct(i, nb_of_nb) ^
13520 (neighbor->direction_flag() ==
13521 cell->direction_flag()))
13522 neighbor->set_direction_flag(
13523 !neighbor->direction_flag());
13524 neighbor->set_user_flag();
13525 next_round.push_back(neighbor);
13526 }
13527 }
13528 }
13529 }
13530
13531 // Before we quit let's check that if the triangulation is
13532 // disconnected that we still get all cells by starting
13533 // again from the first cell we haven't treated yet -- that
13534 // is, the first cell of the next disconnected component we
13535 // had not yet touched.
13536 if (next_round.empty())
13537 for (const auto &cell : this->active_cell_iterators())
13538 if (cell->user_flag_set() == false)
13539 {
13540 next_round.push_back(cell);
13541 cell->set_direction_flag(true);
13542 cell->set_user_flag();
13543 break;
13544 }
13545
13546 // Go on to the next round:
13547 next_round.swap(this_round);
13548 next_round.clear();
13549 }
13550 clear_user_flags();
13551 }
13552
13553 this->update_cell_relations();
13554
13555 // inform all listeners that the triangulation has been created
13556 signals.create();
13557}
13558
13559
13560
13561template <int dim, int spacedim>
13562DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13564 const TriangulationDescription::Description<dim, spacedim> &construction_data)
13565{
13566 // 1) create coarse grid
13568 construction_data.coarse_cells,
13569 SubCellData());
13570
13571 // create a copy of cell_infos such that we can sort them
13572 auto cell_infos = construction_data.cell_infos;
13573
13574 // sort cell_infos on each level separately
13575 for (auto &cell_info : cell_infos)
13576 std::sort(
13577 cell_info.begin(),
13578 cell_info.end(),
13579 [&](const TriangulationDescription::CellData<dim> &a,
13580 const TriangulationDescription::CellData<dim> &b) {
13581 const CellId a_id(a.id);
13582 const CellId b_id(b.id);
13583
13584 const auto a_coarse_cell_index =
13585 this->coarse_cell_id_to_coarse_cell_index(a_id.get_coarse_cell_id());
13586 const auto b_coarse_cell_index =
13587 this->coarse_cell_id_to_coarse_cell_index(b_id.get_coarse_cell_id());
13588
13589 // according to their coarse-cell index and if that is
13590 // same according to their cell id (the result is that
13591 // cells on each level are sorted according to their
13592 // index on that level - what we need in the following
13593 // operations)
13594 if (a_coarse_cell_index != b_coarse_cell_index)
13595 return a_coarse_cell_index < b_coarse_cell_index;
13596 else
13597 return a_id < b_id;
13598 });
13599
13600 // 2) create all levels via a sequence of refinements. note that
13601 // we must make sure that we actually have cells on this level,
13602 // which is not clear in a parallel context for some processes
13603 for (unsigned int level = 0;
13604 level < cell_infos.size() && !cell_infos[level].empty();
13605 ++level)
13606 {
13607 // a) set material and manifold ids here (because new vertices
13608 // have to be positioned correctly during each refinement step)
13609 {
13610 auto cell = this->begin(level);
13611 auto cell_info = cell_infos[level].begin();
13612 for (; cell_info != cell_infos[level].end(); ++cell_info)
13613 {
13614 while (cell_info->id != cell->id().template to_binary<dim>())
13615 ++cell;
13616
13617 cell->set_material_id(cell_info->material_id);
13618 if (dim == 2)
13619 for (const auto face : cell->face_indices())
13620 cell->face(face)->set_manifold_id(
13621 cell_info->manifold_line_ids[face]);
13622 else if (dim == 3)
13623 {
13624 for (const auto face : cell->face_indices())
13625 cell->face(face)->set_manifold_id(
13626 cell_info->manifold_quad_ids[face]);
13627
13628 const auto line_indices = internal::TriaAccessorImplementation::
13629 Implementation::get_line_indices_of_cell(*cell);
13630 for (unsigned int l = 0; l < cell->n_lines(); ++l)
13631 {
13632 raw_line_iterator line(this, 0, line_indices[l]);
13633 line->set_manifold_id(cell_info->manifold_line_ids[l]);
13634 }
13635 }
13636
13637 cell->set_manifold_id(cell_info->manifold_id);
13638 }
13639 }
13640
13641 // b) perform refinement on all levels but on the finest
13642 if (level + 1 != cell_infos.size())
13643 {
13644 // find cells that should have children and mark them for
13645 // refinement
13646 auto coarse_cell = this->begin(level);
13647 auto fine_cell_info = cell_infos[level + 1].begin();
13648
13649 // loop over all cells on the next level
13650 for (; fine_cell_info != cell_infos[level + 1].end();
13651 ++fine_cell_info)
13652 {
13653 // find the parent of that cell
13654 while (
13655 !coarse_cell->id().is_parent_of(CellId(fine_cell_info->id)))
13656 ++coarse_cell;
13657
13658 // set parent for refinement
13659 coarse_cell->set_refine_flag();
13660 }
13661
13662 // execute refinement
13663 ::Triangulation<dim,
13664 spacedim>::execute_coarsening_and_refinement();
13665 }
13666 }
13667
13668 // 3) set boundary ids
13669 for (unsigned int level = 0;
13670 level < cell_infos.size() && !cell_infos[level].empty();
13671 ++level)
13672 {
13673 auto cell = this->begin(level);
13674 auto cell_info = cell_infos[level].begin();
13675 for (; cell_info != cell_infos[level].end(); ++cell_info)
13676 {
13677 // find cell that has the correct cell
13678 while (cell_info->id != cell->id().template to_binary<dim>())
13679 ++cell;
13680
13681 // boundary ids
13682 for (auto pair : cell_info->boundary_ids)
13683 if (cell->face(pair.first)->at_boundary())
13684 cell->face(pair.first)->set_boundary_id(pair.second);
13685 }
13686 }
13687
13688 // inform all listeners that the triangulation has been created
13689 signals.create();
13690}
13691
13692
13693template <int dim, int spacedim>
13694DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13696{
13697 AssertThrow(dim + 1 == spacedim,
13698 ExcMessage(
13699 "This function can only be called if dim == spacedim-1."));
13700 for (const auto &cell : this->active_cell_iterators())
13701 cell->set_direction_flag(!cell->direction_flag());
13702}
13703
13704
13705
13706template <int dim, int spacedim>
13707DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13709{
13710 if constexpr (dim == 3)
13711 {
13712 // Compute the vertex to cell map
13713 const std::vector<std::set<active_cell_iterator>> vertex_to_cell =
13715
13716 // Compute the line-neighbors
13717 if (this->line_to_adjacent_cells_map)
13718 // If the std::optional ready has a value attached to it, just change
13719 // the size of the table stored inside it.
13720 this->line_to_adjacent_cells_map->reinit(
13721 this->n_active_cells(),
13722 (is_mixed_mesh() ?
13723 GeometryInfo<dim>::lines_per_cell : // err on the safe side: choose
13724 // the largest number of lines
13725 // per cell
13726 get_reference_cells()[0]
13727 .n_lines()) // choose the right number of lines per cell for the
13728 // mesh type used
13729 );
13730 else
13731 // Else if the std::optional has no value attached to it, create a table
13732 // of the corresponding size and store it inside the std::optional.
13733 this->line_to_adjacent_cells_map =
13734 std::make_optional<Table<2, std::set<active_cell_iterator>>>(
13735 Table<2, std::set<active_cell_iterator>>(
13736 this->n_active_cells(),
13737 (is_mixed_mesh() ? GeometryInfo<dim>::lines_per_cell :
13738 get_reference_cells()[0].n_lines())));
13739
13740
13741 // Loop over all cells -> lines -> vertices
13742 for (const auto &cell : this->active_cell_iterators())
13743 for (unsigned int line : cell->line_indices())
13744 {
13745 const unsigned int vertex_0 = cell->vertex_index(
13747 const unsigned int vertex_1 = cell->vertex_index(
13749 const std::set<
13751 &adjacent_cells_to_vertex_0 = vertex_to_cell[vertex_0];
13752 const std::set<
13754 &adjacent_cells_to_vertex_1 = vertex_to_cell[vertex_1];
13755
13756 // add all cells that are adjacent to vertex_0 and vertex_1
13757 std::set_intersection(
13758 adjacent_cells_to_vertex_0.begin(),
13759 adjacent_cells_to_vertex_0.end(),
13760 adjacent_cells_to_vertex_1.begin(),
13761 adjacent_cells_to_vertex_1.end(),
13762 std::inserter(line_to_adjacent_cells_map
13763 .value()[cell->active_cell_index()][line],
13764 line_to_adjacent_cells_map
13765 .value()[cell->active_cell_index()][line]
13766 .begin()));
13767 }
13768 }
13769}
13770
13771
13772
13773template <int dim, int spacedim>
13774DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13776{
13777 Assert(n_cells() > 0,
13778 ExcMessage("Error: An empty Triangulation can not be refined."));
13779
13780 for (const auto &cell : this->active_cell_iterators())
13781 {
13782 cell->clear_coarsen_flag();
13783 cell->set_refine_flag();
13784 cell->set_refine_choice();
13785 }
13786}
13787
13788
13789
13790template <int dim, int spacedim>
13791DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13792void Triangulation<dim, spacedim>::refine_global(const unsigned int times)
13793{
13794 Assert(n_cells() > 0,
13795 ExcMessage("Error: An empty Triangulation can not be refined."));
13796
13797 for (unsigned int i = 0; i < times; ++i)
13798 {
13799 set_all_refine_flags();
13800 execute_coarsening_and_refinement();
13801 }
13802}
13803
13804
13805
13806template <int dim, int spacedim>
13807DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13808void Triangulation<dim, spacedim>::coarsen_global(const unsigned int times)
13809{
13810 for (unsigned int i = 0; i < times; ++i)
13811 {
13812 for (const auto &cell : this->active_cell_iterators())
13813 {
13814 cell->clear_refine_flag();
13815 cell->set_coarsen_flag();
13816 }
13817 execute_coarsening_and_refinement();
13818 }
13819}
13820
13821
13822#endif
13823/*-------------------- refine/coarsen flags -------------------------*/
13824
13825#ifndef DOXYGEN
13826
13827template <int dim, int spacedim>
13828DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13829void Triangulation<dim, spacedim>::save_refine_flags(std::vector<bool> &v) const
13830{
13831 v.resize(dim * n_active_cells(), false);
13832 std::vector<bool>::iterator i = v.begin();
13833
13834 for (const auto &cell : this->active_cell_iterators())
13835 for (unsigned int j = 0; j < dim; ++j, ++i)
13836 if (cell->refine_flag_set() & (1 << j))
13837 *i = true;
13838
13839 Assert(i == v.end(), ExcInternalError());
13840}
13841
13842
13843
13844template <int dim, int spacedim>
13845DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13846void Triangulation<dim, spacedim>::save_refine_flags(std::ostream &out) const
13847{
13848 std::vector<bool> v;
13849 save_refine_flags(v);
13850 write_bool_vector(mn_tria_refine_flags_begin,
13851 v,
13853 out);
13854}
13855
13856
13857
13858template <int dim, int spacedim>
13859DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13861{
13862 std::vector<bool> v;
13863 read_bool_vector(mn_tria_refine_flags_begin, v, mn_tria_refine_flags_end, in);
13864 load_refine_flags(v);
13865}
13866
13867
13868
13869template <int dim, int spacedim>
13870DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13871void Triangulation<dim, spacedim>::load_refine_flags(const std::vector<bool> &v)
13872{
13873 AssertThrow(v.size() == dim * n_active_cells(), ExcGridReadError());
13874
13875 std::vector<bool>::const_iterator i = v.begin();
13876 for (const auto &cell : this->active_cell_iterators())
13877 {
13878 unsigned int ref_case = 0;
13879
13880 for (unsigned int j = 0; j < dim; ++j, ++i)
13881 if (*i == true)
13882 ref_case += 1 << j;
13884 ExcGridReadError());
13885 if (ref_case > 0)
13886 cell->set_refine_flag(RefinementCase<dim>(ref_case));
13887 else
13888 cell->clear_refine_flag();
13889 }
13890
13891 Assert(i == v.end(), ExcInternalError());
13892}
13893
13894
13895
13896template <int dim, int spacedim>
13897DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13899 std::vector<bool> &v) const
13900{
13901 v.resize(n_active_cells(), false);
13902 std::vector<bool>::iterator i = v.begin();
13903 for (const auto &cell : this->active_cell_iterators())
13904 {
13905 *i = cell->coarsen_flag_set();
13906 ++i;
13907 }
13908
13909 Assert(i == v.end(), ExcInternalError());
13910}
13911
13912
13913
13914template <int dim, int spacedim>
13915DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13916void Triangulation<dim, spacedim>::save_coarsen_flags(std::ostream &out) const
13917{
13918 std::vector<bool> v;
13919 save_coarsen_flags(v);
13920 write_bool_vector(mn_tria_coarsen_flags_begin,
13921 v,
13923 out);
13924}
13925
13926
13927
13928template <int dim, int spacedim>
13929DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13931{
13932 std::vector<bool> v;
13933 read_bool_vector(mn_tria_coarsen_flags_begin,
13934 v,
13936 in);
13937 load_coarsen_flags(v);
13938}
13939
13940
13941
13942template <int dim, int spacedim>
13943DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13945 const std::vector<bool> &v)
13946{
13947 Assert(v.size() == n_active_cells(), ExcGridReadError());
13948
13949 std::vector<bool>::const_iterator i = v.begin();
13950 for (const auto &cell : this->active_cell_iterators())
13951 {
13952 if (*i == true)
13953 cell->set_coarsen_flag();
13954 else
13955 cell->clear_coarsen_flag();
13956 ++i;
13957 }
13958
13959 Assert(i == v.end(), ExcInternalError());
13960}
13961
13962
13963template <int dim, int spacedim>
13964DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
13966{
13967 return anisotropic_refinement;
13968}
13969
13970
13971#endif
13972
13973namespace internal
13974{
13975 namespace
13976 {
13977 template <int dim, int spacedim>
13978 std::vector<std::vector<bool>>
13979 extract_raw_coarsen_flags(
13980 const std::vector<
13981 std::unique_ptr<::internal::TriangulationImplementation::
13982 TriaLevel<dim, spacedim>>> &levels)
13983 {
13984 std::vector<std::vector<bool>> coarsen_flags(levels.size());
13985 for (unsigned int level = 0; level < levels.size(); ++level)
13986 coarsen_flags[level] = levels[level]->coarsen_flags;
13987 return coarsen_flags;
13988 }
13989
13990 template <int dim, int spacedim>
13991 std::vector<std::vector<std::uint8_t>>
13992 extract_raw_refine_flags(
13993 const std::vector<
13994 std::unique_ptr<::internal::TriangulationImplementation::
13995 TriaLevel<dim, spacedim>>> &levels)
13996 {
13997 std::vector<std::vector<std::uint8_t>> refine_flags(levels.size());
13998 for (unsigned int level = 0; level < levels.size(); ++level)
13999 refine_flags[level] = levels[level]->refine_flags;
14000 return refine_flags;
14001 }
14002 } // namespace
14003} // namespace internal
14004
14005
14006/*-------------------- user data/flags -------------------------*/
14007
14008
14009namespace
14010{
14011 // clear user data of cells
14012 template <int dim, int spacedim>
14013 void
14014 clear_user_data(
14015 std::vector<std::unique_ptr<
14016 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>> &levels)
14017 {
14018 for (auto &level : levels)
14019 level->cells.clear_user_data();
14020 }
14021
14022
14023 // clear user data of faces
14024 template <int dim>
14025 void
14026 clear_user_data(internal::TriangulationImplementation::TriaFaces<dim> *faces)
14027 {
14028 if (dim == 2)
14029 {
14030 faces->lines.clear_user_data();
14031 }
14032
14033
14034 if (dim == 3)
14035 {
14036 faces->lines.clear_user_data();
14037 faces->quads.clear_user_data();
14038 }
14039 }
14040} // namespace
14041
14042#ifndef DOXYGEN
14043
14044template <int dim, int spacedim>
14045DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14047{
14048 // let functions in anonymous namespace do their work
14049 ::clear_user_data(levels);
14050 if (dim > 1)
14051 ::clear_user_data(faces.get());
14052}
14053
14054
14055
14056namespace
14057{
14058 template <int dim, int spacedim>
14059 void
14060 clear_user_flags_line(
14061 std::vector<std::unique_ptr<
14062 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>> &levels,
14063 internal::TriangulationImplementation::TriaFaces<dim> *faces)
14064 {
14065 if (dim == 1)
14066 {
14067 for (const auto &level : levels)
14068 level->cells.clear_user_flags();
14069 }
14070 else if (dim == 2 || dim == 3)
14071 {
14072 faces->lines.clear_user_flags();
14073 }
14074 else
14075 {
14077 }
14078 }
14079} // namespace
14080
14081
14082template <int dim, int spacedim>
14083DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14085{
14086 ::clear_user_flags_line(levels, faces.get());
14087}
14088
14089
14090
14091namespace
14092{
14093 template <int dim, int spacedim>
14094 void
14095 clear_user_flags_quad(
14096 std::vector<std::unique_ptr<
14097 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>> &levels,
14098 internal::TriangulationImplementation::TriaFaces<dim> *faces)
14099 {
14100 if (dim == 1)
14101 {
14102 // nothing to do in 1d
14103 }
14104 else if (dim == 2)
14105 {
14106 for (const auto &level : levels)
14107 level->cells.clear_user_flags();
14108 }
14109 else if (dim == 3)
14110 {
14111 faces->quads.clear_user_flags();
14112 }
14113 else
14114 {
14116 }
14117 }
14118} // namespace
14119
14120
14121template <int dim, int spacedim>
14122DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14124{
14125 ::clear_user_flags_quad(levels, faces.get());
14126}
14127
14128
14129
14130namespace
14131{
14132 template <int dim, int spacedim>
14133 void
14134 clear_user_flags_hex(
14135 std::vector<std::unique_ptr<
14136 internal::TriangulationImplementation::TriaLevel<dim, spacedim>>> &levels,
14137 internal::TriangulationImplementation::TriaFaces<dim> *)
14138 {
14139 if (dim == 1)
14140 {
14141 // nothing to do in 1d
14142 }
14143 else if (dim == 2)
14144 {
14145 // nothing to do in 2d
14146 }
14147 else if (dim == 3)
14148 {
14149 for (const auto &level : levels)
14150 level->cells.clear_user_flags();
14151 }
14152 else
14153 {
14155 }
14156 }
14157} // namespace
14158
14159
14160template <int dim, int spacedim>
14161DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14163{
14164 ::clear_user_flags_hex(levels, faces.get());
14165}
14166
14167
14168
14169template <int dim, int spacedim>
14170DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14172{
14173 clear_user_flags_line();
14174 clear_user_flags_quad();
14175 clear_user_flags_hex();
14176}
14177
14178
14179
14180template <int dim, int spacedim>
14181DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14182void Triangulation<dim, spacedim>::save_user_flags(std::ostream &out) const
14183{
14184 save_user_flags_line(out);
14185
14186 if (dim >= 2)
14187 save_user_flags_quad(out);
14188
14189 if (dim >= 3)
14190 save_user_flags_hex(out);
14191
14192 if (dim >= 4)
14194}
14195
14196
14197
14198template <int dim, int spacedim>
14199DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14200void Triangulation<dim, spacedim>::save_user_flags(std::vector<bool> &v) const
14201{
14202 // clear vector and append
14203 // all the stuff later on
14204 v.clear();
14205
14206 std::vector<bool> tmp;
14207
14208 save_user_flags_line(tmp);
14209 v.insert(v.end(), tmp.begin(), tmp.end());
14210
14211 if (dim >= 2)
14212 {
14213 save_user_flags_quad(tmp);
14214 v.insert(v.end(), tmp.begin(), tmp.end());
14215 }
14216
14217 if (dim >= 3)
14218 {
14219 save_user_flags_hex(tmp);
14220 v.insert(v.end(), tmp.begin(), tmp.end());
14221 }
14222
14223 if (dim >= 4)
14225}
14226
14227
14228
14229template <int dim, int spacedim>
14230DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14232{
14233 load_user_flags_line(in);
14234
14235 if (dim >= 2)
14236 load_user_flags_quad(in);
14237
14238 if (dim >= 3)
14239 load_user_flags_hex(in);
14240
14241 if (dim >= 4)
14243}
14244
14245
14246
14247template <int dim, int spacedim>
14248DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14249void Triangulation<dim, spacedim>::load_user_flags(const std::vector<bool> &v)
14250{
14251 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14252 std::vector<bool> tmp;
14253
14254 // first extract the flags
14255 // belonging to lines
14256 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14257 // and set the lines
14258 load_user_flags_line(tmp);
14259
14260 if (dim >= 2)
14261 {
14262 tmp.clear();
14263 tmp.insert(tmp.end(),
14264 v.begin() + n_lines(),
14265 v.begin() + n_lines() + n_quads());
14266 load_user_flags_quad(tmp);
14267 }
14268
14269 if (dim >= 3)
14270 {
14271 tmp.clear();
14272 tmp.insert(tmp.end(),
14273 v.begin() + n_lines() + n_quads(),
14274 v.begin() + n_lines() + n_quads() + n_hexs());
14275 load_user_flags_hex(tmp);
14276 }
14277
14278 if (dim >= 4)
14280}
14281
14282
14283
14284template <int dim, int spacedim>
14285DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14287 std::vector<bool> &v) const
14288{
14289 v.resize(n_lines(), false);
14290 std::vector<bool>::iterator i = v.begin();
14291 line_iterator line = begin_line(), endl = end_line();
14292 for (; line != endl; ++line, ++i)
14293 *i = line->user_flag_set();
14294
14295 Assert(i == v.end(), ExcInternalError());
14296}
14297
14298
14299
14300template <int dim, int spacedim>
14301DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14302void Triangulation<dim, spacedim>::save_user_flags_line(std::ostream &out) const
14303{
14304 std::vector<bool> v;
14305 save_user_flags_line(v);
14306 write_bool_vector(mn_tria_line_user_flags_begin,
14307 v,
14309 out);
14310}
14311
14312
14313
14314template <int dim, int spacedim>
14315DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14317{
14318 std::vector<bool> v;
14319 read_bool_vector(mn_tria_line_user_flags_begin,
14320 v,
14322 in);
14323 load_user_flags_line(v);
14324}
14325
14326
14327
14328template <int dim, int spacedim>
14329DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14331 const std::vector<bool> &v)
14332{
14333 Assert(v.size() == n_lines(), ExcGridReadError());
14334
14335 line_iterator line = begin_line(), endl = end_line();
14336 std::vector<bool>::const_iterator i = v.begin();
14337 for (; line != endl; ++line, ++i)
14338 if (*i == true)
14339 line->set_user_flag();
14340 else
14341 line->clear_user_flag();
14342
14343 Assert(i == v.end(), ExcInternalError());
14344}
14345
14346#endif
14347
14348namespace
14349{
14350 template <typename Iterator>
14351 bool
14352 get_user_flag(const Iterator &i)
14353 {
14354 return i->user_flag_set();
14355 }
14356
14357
14358
14359 template <int structdim, int dim, int spacedim>
14360 bool
14361 get_user_flag(const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
14362 {
14364 return false;
14365 }
14366
14367
14368
14369 template <typename Iterator>
14370 void
14371 set_user_flag(const Iterator &i)
14372 {
14373 i->set_user_flag();
14374 }
14375
14376
14377
14378 template <int structdim, int dim, int spacedim>
14379 void
14380 set_user_flag(const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
14381 {
14383 }
14384
14385
14386
14387 template <typename Iterator>
14388 void
14389 clear_user_flag(const Iterator &i)
14390 {
14391 i->clear_user_flag();
14392 }
14393
14394
14395
14396 template <int structdim, int dim, int spacedim>
14397 void
14398 clear_user_flag(
14399 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
14400 {
14402 }
14403} // namespace
14404
14405#ifndef DOXYGEN
14406
14407template <int dim, int spacedim>
14408DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14410 std::vector<bool> &v) const
14411{
14412 v.resize(n_quads(), false);
14413
14414 if (dim >= 2)
14415 {
14416 std::vector<bool>::iterator i = v.begin();
14417 quad_iterator quad = begin_quad(), endq = end_quad();
14418 for (; quad != endq; ++quad, ++i)
14419 *i = get_user_flag(quad);
14420
14421 Assert(i == v.end(), ExcInternalError());
14422 }
14423}
14424
14425
14426
14427template <int dim, int spacedim>
14428DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14429void Triangulation<dim, spacedim>::save_user_flags_quad(std::ostream &out) const
14430{
14431 std::vector<bool> v;
14432 save_user_flags_quad(v);
14433 write_bool_vector(mn_tria_quad_user_flags_begin,
14434 v,
14436 out);
14437}
14438
14439
14440
14441template <int dim, int spacedim>
14442DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14444{
14445 std::vector<bool> v;
14446 read_bool_vector(mn_tria_quad_user_flags_begin,
14447 v,
14449 in);
14450 load_user_flags_quad(v);
14451}
14452
14453
14454
14455template <int dim, int spacedim>
14456DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14458 const std::vector<bool> &v)
14459{
14460 Assert(v.size() == n_quads(), ExcGridReadError());
14461
14462 if (dim >= 2)
14463 {
14464 quad_iterator quad = begin_quad(), endq = end_quad();
14465 std::vector<bool>::const_iterator i = v.begin();
14466 for (; quad != endq; ++quad, ++i)
14467 if (*i == true)
14468 set_user_flag(quad);
14469 else
14470 clear_user_flag(quad);
14471
14472 Assert(i == v.end(), ExcInternalError());
14473 }
14474}
14475
14476
14477
14478template <int dim, int spacedim>
14479DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14481 std::vector<bool> &v) const
14482{
14483 v.resize(n_hexs(), false);
14484
14485 if (dim >= 3)
14486 {
14487 std::vector<bool>::iterator i = v.begin();
14488 hex_iterator hex = begin_hex(), endh = end_hex();
14489 for (; hex != endh; ++hex, ++i)
14490 *i = get_user_flag(hex);
14491
14492 Assert(i == v.end(), ExcInternalError());
14493 }
14494}
14495
14496
14497
14498template <int dim, int spacedim>
14499DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14500void Triangulation<dim, spacedim>::save_user_flags_hex(std::ostream &out) const
14501{
14502 std::vector<bool> v;
14503 save_user_flags_hex(v);
14504 write_bool_vector(mn_tria_hex_user_flags_begin,
14505 v,
14507 out);
14508}
14509
14510
14511
14512template <int dim, int spacedim>
14513DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14515{
14516 std::vector<bool> v;
14517 read_bool_vector(mn_tria_hex_user_flags_begin,
14518 v,
14520 in);
14521 load_user_flags_hex(v);
14522}
14523
14524
14525
14526template <int dim, int spacedim>
14527DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14529 const std::vector<bool> &v)
14530{
14531 Assert(v.size() == n_hexs(), ExcGridReadError());
14532
14533 if (dim >= 3)
14534 {
14535 hex_iterator hex = begin_hex(), endh = end_hex();
14536 std::vector<bool>::const_iterator i = v.begin();
14537 for (; hex != endh; ++hex, ++i)
14538 if (*i == true)
14539 set_user_flag(hex);
14540 else
14541 clear_user_flag(hex);
14542
14543 Assert(i == v.end(), ExcInternalError());
14544 }
14545}
14546
14547
14548
14549template <int dim, int spacedim>
14550DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14552 std::vector<unsigned int> &v) const
14553{
14554 // clear vector and append all the
14555 // stuff later on
14556 v.clear();
14557
14558 std::vector<unsigned int> tmp;
14559
14560 save_user_indices_line(tmp);
14561 v.insert(v.end(), tmp.begin(), tmp.end());
14562
14563 if (dim >= 2)
14564 {
14565 save_user_indices_quad(tmp);
14566 v.insert(v.end(), tmp.begin(), tmp.end());
14567 }
14568
14569 if (dim >= 3)
14570 {
14571 save_user_indices_hex(tmp);
14572 v.insert(v.end(), tmp.begin(), tmp.end());
14573 }
14574
14575 if (dim >= 4)
14577}
14578
14579
14580
14581template <int dim, int spacedim>
14582DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14584 const std::vector<unsigned int> &v)
14585{
14586 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14587 std::vector<unsigned int> tmp;
14588
14589 // first extract the indices
14590 // belonging to lines
14591 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14592 // and set the lines
14593 load_user_indices_line(tmp);
14594
14595 if (dim >= 2)
14596 {
14597 tmp.clear();
14598 tmp.insert(tmp.end(),
14599 v.begin() + n_lines(),
14600 v.begin() + n_lines() + n_quads());
14601 load_user_indices_quad(tmp);
14602 }
14603
14604 if (dim >= 3)
14605 {
14606 tmp.clear();
14607 tmp.insert(tmp.end(),
14608 v.begin() + n_lines() + n_quads(),
14609 v.begin() + n_lines() + n_quads() + n_hexs());
14610 load_user_indices_hex(tmp);
14611 }
14612
14613 if (dim >= 4)
14615}
14616
14617
14618
14619template <int dim, int spacedim>
14620DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14621void Triangulation<dim, spacedim>::save(const std::string &file_basename) const
14622{
14623 // Save triangulation information.
14624 {
14625 std::ofstream ofs_tria(file_basename + "_triangulation.data");
14626 AssertThrow(ofs_tria.fail() == false, ExcIO());
14627
14628 boost::archive::text_oarchive oa(ofs_tria, boost::archive::no_header);
14629 save(oa,
14630 internal::CellAttachedDataSerializer<dim, spacedim>::version_number);
14631 }
14632
14633 // Save attached data.
14634 {
14635 std::ofstream ofs_info(file_basename + ".info");
14636 ofs_info
14637 << "version nproc n_attached_fixed_size_objs n_attached_variable_size_objs n_active_cells"
14638 << std::endl
14639 << internal::CellAttachedDataSerializer<dim, spacedim>::version_number
14640 << " " << 1 << " " << this->cell_attached_data.pack_callbacks_fixed.size()
14641 << " " << this->cell_attached_data.pack_callbacks_variable.size() << " "
14642 << this->n_global_active_cells() << std::endl;
14643 }
14644
14645 this->save_attached_data(0, this->n_global_active_cells(), file_basename);
14646}
14647
14648
14649
14650template <int dim, int spacedim>
14651DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14652void Triangulation<dim, spacedim>::load(const std::string &file_basename)
14653{
14654 // It's probably prudent to first get rid of any all content of the
14655 // triangulation, rather than hope that the deserialization below
14656 // overwrites everything:
14657 clear();
14658
14659 // Load triangulation information.
14660 {
14661 std::ifstream ifs_tria(file_basename + "_triangulation.data");
14662 AssertThrow(ifs_tria.fail() == false, ExcIO());
14663
14664 boost::archive::text_iarchive ia(ifs_tria, boost::archive::no_header);
14665 load(ia,
14666 internal::CellAttachedDataSerializer<dim, spacedim>::version_number);
14667 }
14668
14669 // Load attached data.
14670 unsigned int version, numcpus, attached_count_fixed, attached_count_variable,
14671 n_global_active_cells;
14672 {
14673 std::ifstream ifs_info(std::string(file_basename) + ".info");
14674 AssertThrow(ifs_info.fail() == false, ExcIO());
14675 std::string firstline;
14676 std::getline(ifs_info, firstline);
14677 ifs_info >> version >> numcpus >> attached_count_fixed >>
14678 attached_count_variable >> n_global_active_cells;
14679 }
14680
14681 AssertThrow(numcpus == 1,
14682 ExcMessage("Incompatible number of CPUs found in .info file."));
14683
14684 const auto expected_version =
14685 ::internal::CellAttachedDataSerializer<dim,
14686 spacedim>::version_number;
14687 AssertThrow(version == expected_version,
14688 ExcMessage(
14689 "The information saved in the file you are trying "
14690 "to read the triangulation from was written with an "
14691 "incompatible file format version and cannot be read."));
14692 Assert(this->n_global_active_cells() == n_global_active_cells,
14693 ExcMessage("The number of cells of the triangulation differs "
14694 "from the number of cells written into the .info file."));
14695
14696 // Clear all of the callback data, as explained in the documentation of
14697 // register_data_attach().
14698 this->cell_attached_data.n_attached_data_sets = 0;
14699 this->cell_attached_data.n_attached_deserialize =
14700 attached_count_fixed + attached_count_variable;
14701
14702 this->load_attached_data(0,
14703 this->n_global_active_cells(),
14704 this->n_active_cells(),
14705 file_basename,
14706 attached_count_fixed,
14707 attached_count_variable);
14708
14709 this->update_cell_relations();
14710}
14711
14712#endif
14713namespace
14714{
14715 template <typename Iterator>
14716 unsigned int
14717 get_user_index(const Iterator &i)
14718 {
14719 return i->user_index();
14720 }
14721
14722
14723
14724 template <int structdim, int dim, int spacedim>
14725 unsigned int
14726 get_user_index(
14727 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
14728 {
14731 }
14732
14733
14734
14735 template <typename Iterator>
14736 void
14737 set_user_index(const Iterator &i, const unsigned int x)
14738 {
14739 i->set_user_index(x);
14740 }
14741
14742
14743
14744 template <int structdim, int dim, int spacedim>
14745 void
14746 set_user_index(
14747 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &,
14748 const unsigned int)
14749 {
14751 }
14752} // namespace
14753
14754#ifndef DOXYGEN
14755
14756template <int dim, int spacedim>
14757DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14759 std::vector<unsigned int> &v) const
14760{
14761 v.resize(n_lines(), 0);
14762 std::vector<unsigned int>::iterator i = v.begin();
14763 line_iterator line = begin_line(), endl = end_line();
14764 for (; line != endl; ++line, ++i)
14765 *i = line->user_index();
14766}
14767
14768
14769
14770template <int dim, int spacedim>
14771DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14773 const std::vector<unsigned int> &v)
14774{
14775 Assert(v.size() == n_lines(), ExcGridReadError());
14776
14777 line_iterator line = begin_line(), endl = end_line();
14778 std::vector<unsigned int>::const_iterator i = v.begin();
14779 for (; line != endl; ++line, ++i)
14780 line->set_user_index(*i);
14781}
14782
14783
14784template <int dim, int spacedim>
14785DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14787 std::vector<unsigned int> &v) const
14788{
14789 v.resize(n_quads(), 0);
14790
14791 if (dim >= 2)
14792 {
14793 std::vector<unsigned int>::iterator i = v.begin();
14794 quad_iterator quad = begin_quad(), endq = end_quad();
14795 for (; quad != endq; ++quad, ++i)
14796 *i = get_user_index(quad);
14797 }
14798}
14799
14800
14801
14802template <int dim, int spacedim>
14803DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14805 const std::vector<unsigned int> &v)
14806{
14807 Assert(v.size() == n_quads(), ExcGridReadError());
14808
14809 if (dim >= 2)
14810 {
14811 quad_iterator quad = begin_quad(), endq = end_quad();
14812 std::vector<unsigned int>::const_iterator i = v.begin();
14813 for (; quad != endq; ++quad, ++i)
14814 set_user_index(quad, *i);
14815 }
14816}
14817
14818
14819template <int dim, int spacedim>
14820DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14822 std::vector<unsigned int> &v) const
14823{
14824 v.resize(n_hexs(), 0);
14825
14826 if (dim >= 3)
14827 {
14828 std::vector<unsigned int>::iterator i = v.begin();
14829 hex_iterator hex = begin_hex(), endh = end_hex();
14830 for (; hex != endh; ++hex, ++i)
14831 *i = get_user_index(hex);
14832 }
14833}
14834
14835
14836
14837template <int dim, int spacedim>
14838DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14840 const std::vector<unsigned int> &v)
14841{
14842 Assert(v.size() == n_hexs(), ExcGridReadError());
14843
14844 if (dim >= 3)
14845 {
14846 hex_iterator hex = begin_hex(), endh = end_hex();
14847 std::vector<unsigned int>::const_iterator i = v.begin();
14848 for (; hex != endh; ++hex, ++i)
14849 set_user_index(hex, *i);
14850 }
14851}
14852
14853#endif
14854
14855
14856//---------------- user pointers ----------------------------------------//
14857
14858
14859namespace
14860{
14861 template <typename Iterator>
14862 void *
14863 get_user_pointer(const Iterator &i)
14864 {
14865 return i->user_pointer();
14866 }
14867
14868
14869
14870 template <int structdim, int dim, int spacedim>
14871 void *
14872 get_user_pointer(
14873 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &)
14874 {
14876 return nullptr;
14877 }
14878
14879
14880
14881 template <typename Iterator>
14882 void
14883 set_user_pointer(const Iterator &i, void *x)
14884 {
14885 i->set_user_pointer(x);
14886 }
14887
14888
14889
14890 template <int structdim, int dim, int spacedim>
14891 void
14892 set_user_pointer(
14893 const TriaIterator<InvalidAccessor<structdim, dim, spacedim>> &,
14894 void *)
14895 {
14897 }
14898} // namespace
14899
14900#ifndef DOXYGEN
14901
14902template <int dim, int spacedim>
14903DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14905 std::vector<void *> &v) const
14906{
14907 // clear vector and append all the
14908 // stuff later on
14909 v.clear();
14910
14911 std::vector<void *> tmp;
14912
14913 save_user_pointers_line(tmp);
14914 v.insert(v.end(), tmp.begin(), tmp.end());
14915
14916 if (dim >= 2)
14917 {
14918 save_user_pointers_quad(tmp);
14919 v.insert(v.end(), tmp.begin(), tmp.end());
14920 }
14921
14922 if (dim >= 3)
14923 {
14924 save_user_pointers_hex(tmp);
14925 v.insert(v.end(), tmp.begin(), tmp.end());
14926 }
14927
14928 if (dim >= 4)
14930}
14931
14932
14933
14934template <int dim, int spacedim>
14935DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14937 const std::vector<void *> &v)
14938{
14939 Assert(v.size() == n_lines() + n_quads() + n_hexs(), ExcInternalError());
14940 std::vector<void *> tmp;
14941
14942 // first extract the pointers
14943 // belonging to lines
14944 tmp.insert(tmp.end(), v.begin(), v.begin() + n_lines());
14945 // and set the lines
14946 load_user_pointers_line(tmp);
14947
14948 if (dim >= 2)
14949 {
14950 tmp.clear();
14951 tmp.insert(tmp.end(),
14952 v.begin() + n_lines(),
14953 v.begin() + n_lines() + n_quads());
14954 load_user_pointers_quad(tmp);
14955 }
14956
14957 if (dim >= 3)
14958 {
14959 tmp.clear();
14960 tmp.insert(tmp.end(),
14961 v.begin() + n_lines() + n_quads(),
14962 v.begin() + n_lines() + n_quads() + n_hexs());
14963 load_user_pointers_hex(tmp);
14964 }
14965
14966 if (dim >= 4)
14968}
14969
14970
14971
14972template <int dim, int spacedim>
14973DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14975 std::vector<void *> &v) const
14976{
14977 v.resize(n_lines(), nullptr);
14978 std::vector<void *>::iterator i = v.begin();
14979 line_iterator line = begin_line(), endl = end_line();
14980 for (; line != endl; ++line, ++i)
14981 *i = line->user_pointer();
14982}
14983
14984
14985
14986template <int dim, int spacedim>
14987DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
14989 const std::vector<void *> &v)
14990{
14991 Assert(v.size() == n_lines(), ExcGridReadError());
14992
14993 line_iterator line = begin_line(), endl = end_line();
14994 std::vector<void *>::const_iterator i = v.begin();
14995 for (; line != endl; ++line, ++i)
14996 line->set_user_pointer(*i);
14997}
14998
14999
15000
15001template <int dim, int spacedim>
15002DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15004 std::vector<void *> &v) const
15005{
15006 v.resize(n_quads(), nullptr);
15007
15008 if (dim >= 2)
15009 {
15010 std::vector<void *>::iterator i = v.begin();
15011 quad_iterator quad = begin_quad(), endq = end_quad();
15012 for (; quad != endq; ++quad, ++i)
15013 *i = get_user_pointer(quad);
15014 }
15015}
15016
15017
15018
15019template <int dim, int spacedim>
15020DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15022 const std::vector<void *> &v)
15023{
15024 Assert(v.size() == n_quads(), ExcGridReadError());
15025
15026 if (dim >= 2)
15027 {
15028 quad_iterator quad = begin_quad(), endq = end_quad();
15029 std::vector<void *>::const_iterator i = v.begin();
15030 for (; quad != endq; ++quad, ++i)
15031 set_user_pointer(quad, *i);
15032 }
15033}
15034
15035
15036template <int dim, int spacedim>
15037DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15039 std::vector<void *> &v) const
15040{
15041 v.resize(n_hexs(), nullptr);
15042
15043 if (dim >= 3)
15044 {
15045 std::vector<void *>::iterator i = v.begin();
15046 hex_iterator hex = begin_hex(), endh = end_hex();
15047 for (; hex != endh; ++hex, ++i)
15048 *i = get_user_pointer(hex);
15049 }
15050}
15051
15052
15053
15054template <int dim, int spacedim>
15055DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15057 const std::vector<void *> &v)
15058{
15059 Assert(v.size() == n_hexs(), ExcGridReadError());
15060
15061 if (dim >= 3)
15062 {
15063 hex_iterator hex = begin_hex(), endh = end_hex();
15064 std::vector<void *>::const_iterator i = v.begin();
15065 for (; hex != endh; ++hex, ++i)
15066 set_user_pointer(hex, *i);
15067 }
15068}
15069
15070#endif
15071
15072/*------------------------ Cell iterator functions ------------------------*/
15073
15074#ifndef DOXYGEN
15075
15076template <int dim, int spacedim>
15077DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15079 Triangulation<dim, spacedim>::begin_raw(const unsigned int level) const
15080{
15081 switch (dim)
15082 {
15083 case 1:
15084 return begin_raw_line(level);
15085 case 2:
15086 return begin_raw_quad(level);
15087 case 3:
15088 return begin_raw_hex(level);
15089 default:
15091 return raw_cell_iterator();
15092 }
15093}
15094
15095
15096
15097template <int dim, int spacedim>
15098DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15100 Triangulation<dim, spacedim>::begin(const unsigned int level) const
15101{
15102 switch (dim)
15103 {
15104 case 1:
15105 return begin_line(level);
15106 case 2:
15107 return begin_quad(level);
15108 case 3:
15109 return begin_hex(level);
15110 default:
15111 Assert(false, ExcImpossibleInDim(dim));
15112 return cell_iterator();
15113 }
15114}
15115
15116
15117
15118template <int dim, int spacedim>
15119DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15121 Triangulation<dim, spacedim>::begin_active(const unsigned int level) const
15122{
15123 switch (dim)
15124 {
15125 case 1:
15126 return begin_active_line(level);
15127 case 2:
15128 return begin_active_quad(level);
15129 case 3:
15130 return begin_active_hex(level);
15131 default:
15133 return active_cell_iterator();
15134 }
15135}
15136
15137
15138
15139template <int dim, int spacedim>
15140DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15143{
15144 const unsigned int level = levels.size() - 1;
15145 if (levels[level]->cells.n_objects() == 0)
15146 return end(level);
15147
15148 // find the last raw iterator on
15149 // this level
15150 raw_cell_iterator ri(const_cast<Triangulation<dim, spacedim> *>(this),
15151 level,
15152 levels[level]->cells.n_objects() - 1);
15153
15154 // then move to the last used one
15155 if (ri->used() == true)
15156 return ri;
15157 while ((--ri).state() == IteratorState::valid)
15158 if (ri->used() == true)
15159 return ri;
15160 return ri;
15161}
15162
15163
15164
15165template <int dim, int spacedim>
15166DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15169{
15170 // get the last used cell
15171 cell_iterator cell = last();
15172
15173 if (cell != end())
15174 {
15175 // then move to the last active one
15176 if (cell->is_active() == true)
15177 return cell;
15178 while ((--cell).state() == IteratorState::valid)
15179 if (cell->is_active() == true)
15180 return cell;
15181 }
15182 return cell;
15183}
15184
15185
15186
15187template <int dim, int spacedim>
15188DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15191 const CellId &cell_id) const
15192{
15193 Assert(
15194 this->contains_cell(cell_id),
15195 ExcMessage(
15196 "CellId is invalid for this triangulation.\n"
15197 "Either the provided CellId does not correspond to a cell in this "
15198 "triangulation object, or, in case you are using a parallel "
15199 "triangulation, may correspond to an artificial cell that is less "
15200 "refined on this processor. In the case of "
15201 "parallel::fullydistributed::Triangulation, the corresponding coarse "
15202 "cell might not be accessible by the current process."));
15203
15204 cell_iterator cell(
15205 this, 0, coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id()));
15206
15207 for (const auto &child_index : cell_id.get_child_indices())
15208 cell = cell->child(static_cast<unsigned int>(child_index));
15209
15210 return cell;
15211}
15212
15213
15214
15215template <int dim, int spacedim>
15216DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15217bool Triangulation<dim, spacedim>::contains_cell(const CellId &cell_id) const
15218{
15219 const auto coarse_cell_index =
15220 coarse_cell_id_to_coarse_cell_index(cell_id.get_coarse_cell_id());
15221
15222 if (coarse_cell_index == numbers::invalid_unsigned_int)
15223 return false;
15224
15225 cell_iterator cell(this, 0, coarse_cell_index);
15226
15227 for (const auto &child_index : cell_id.get_child_indices())
15228 {
15229 if (cell->has_children() == false)
15230 return false;
15231 cell = cell->child(static_cast<unsigned int>(child_index));
15232 }
15233
15234 return true;
15235}
15236
15237
15238
15239template <int dim, int spacedim>
15240DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15243{
15244 return cell_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15245 -1,
15246 -1);
15247}
15248
15249
15250
15251template <int dim, int spacedim>
15252DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15254 Triangulation<dim, spacedim>::end_raw(const unsigned int level) const
15255{
15256 // This function may be called on parallel triangulations on levels
15257 // that exist globally, but not on the local portion of the
15258 // triangulation. In that case, just return the end iterator.
15259 //
15260 // We need to use levels.size() instead of n_levels() because the
15261 // latter function uses the cache, but we need to be able to call
15262 // this function at a time when the cache is not currently up to
15263 // date.
15264 if (level >= levels.size())
15265 {
15266 Assert(level < n_global_levels(),
15267 ExcInvalidLevel(level, n_global_levels()));
15268 return end();
15269 }
15270
15271 // Query whether the given level is valid for the local portion of the
15272 // triangulation.
15273 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15274 if (level < levels.size() - 1)
15275 return begin_raw(level + 1);
15276 else
15277 return end();
15278}
15279
15280
15281template <int dim, int spacedim>
15282DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15284 Triangulation<dim, spacedim>::end(const unsigned int level) const
15285{
15286 // This function may be called on parallel triangulations on levels
15287 // that exist globally, but not on the local portion of the
15288 // triangulation. In that case, just return the end iterator.
15289 //
15290 // We need to use levels.size() instead of n_levels() because the
15291 // latter function uses the cache, but we need to be able to call
15292 // this function at a time when the cache is not currently up to
15293 // date.
15294 if (level >= levels.size())
15295 {
15296 Assert(level < n_global_levels(),
15297 ExcInvalidLevel(level, n_global_levels()));
15298 return end();
15299 }
15300
15301 // Query whether the given level is valid for the local portion of the
15302 // triangulation.
15303 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15304 if (level < levels.size() - 1)
15305 return begin(level + 1);
15306 else
15307 return end();
15308}
15309
15310
15311template <int dim, int spacedim>
15312DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15314 Triangulation<dim, spacedim>::end_active(const unsigned int level) const
15315{
15316 // This function may be called on parallel triangulations on levels
15317 // that exist globally, but not on the local portion of the
15318 // triangulation. In that case, just return the end iterator.
15319 //
15320 // We need to use levels.size() instead of n_levels() because the
15321 // latter function uses the cache, but we need to be able to call
15322 // this function at a time when the cache is not currently up to
15323 // date.
15324 if (level >= levels.size())
15325 {
15326 Assert(level < n_global_levels(),
15327 ExcInvalidLevel(level, n_global_levels()));
15328 return end();
15329 }
15330
15331 // Query whether the given level is valid for the local portion of the
15332 // triangulation.
15333 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15334 return (level >= levels.size() - 1 ? active_cell_iterator(end()) :
15335 begin_active(level + 1));
15336}
15337
15338
15339
15340template <int dim, int spacedim>
15341DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15342IteratorRange<typename Triangulation<dim, spacedim>::
15344 const
15345{
15346 return IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>(
15347 begin(), end());
15348}
15349
15350
15351template <int dim, int spacedim>
15352DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15353IteratorRange<typename Triangulation<dim, spacedim>::
15354 active_cell_iterator> Triangulation<dim, spacedim>::
15356{
15357 return IteratorRange<
15359 end());
15360}
15361
15362
15363
15364template <int dim, int spacedim>
15365DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15366IteratorRange<typename Triangulation<dim, spacedim>::
15367 cell_iterator> Triangulation<dim, spacedim>::
15368 cell_iterators_on_level(const unsigned int level) const
15369{
15370 return IteratorRange<typename Triangulation<dim, spacedim>::cell_iterator>(
15371 begin(level), end(level));
15372}
15373
15374
15375
15376template <int dim, int spacedim>
15377DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15378IteratorRange<typename Triangulation<dim, spacedim>::
15379 active_cell_iterator> Triangulation<dim, spacedim>::
15380 active_cell_iterators_on_level(const unsigned int level) const
15381{
15382 return IteratorRange<
15384 begin_active(level), end_active(level));
15385}
15386#endif
15387
15388/*------------------------ Face iterator functions ------------------------*/
15389
15390#ifndef DOXYGEN
15391
15392template <int dim, int spacedim>
15393DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15396{
15397 switch (dim)
15398 {
15399 case 1:
15400 Assert(false, ExcImpossibleInDim(1));
15401 return raw_face_iterator();
15402 case 2:
15403 return begin_line();
15404 case 3:
15405 return begin_quad();
15406 default:
15408 return face_iterator();
15409 }
15410}
15411
15412
15413
15414template <int dim, int spacedim>
15415DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15418{
15419 switch (dim)
15420 {
15421 case 1:
15422 Assert(false, ExcImpossibleInDim(1));
15423 return raw_face_iterator();
15424 case 2:
15425 return begin_active_line();
15426 case 3:
15427 return begin_active_quad();
15428 default:
15430 return active_face_iterator();
15431 }
15432}
15433
15434
15435
15436template <int dim, int spacedim>
15437DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15440{
15441 switch (dim)
15442 {
15443 case 1:
15444 Assert(false, ExcImpossibleInDim(1));
15445 return raw_face_iterator();
15446 case 2:
15447 return end_line();
15448 case 3:
15449 return end_quad();
15450 default:
15452 return raw_face_iterator();
15453 }
15454}
15455
15456
15457
15458template <int dim, int spacedim>
15459DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15460IteratorRange<typename Triangulation<dim, spacedim>::
15461 active_face_iterator> Triangulation<dim, spacedim>::
15463{
15464 return IteratorRange<
15466 begin_active_face(), end_face());
15467}
15468
15469/*------------------------ Vertex iterator functions ------------------------*/
15470
15471
15472template <int dim, int spacedim>
15473DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15476{
15477 vertex_iterator i =
15478 raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15479 if (i.state() != IteratorState::valid)
15480 return i;
15481 // This loop will end because every triangulation has used vertices.
15482 while (i->used() == false)
15483 if ((++i).state() != IteratorState::valid)
15484 return i;
15485 return i;
15486}
15487
15488
15489
15490template <int dim, int spacedim>
15491DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15494{
15495 // every vertex is active
15496 return begin_vertex();
15497}
15498
15499
15500
15501template <int dim, int spacedim>
15502DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15505{
15506 return raw_vertex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15507 -1,
15509}
15510
15511#endif
15512
15513
15514/*------------------------ Line iterator functions ------------------------*/
15515
15516#ifndef DOXYGEN
15517
15518template <int dim, int spacedim>
15519DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15521 Triangulation<dim, spacedim>::begin_raw_line(const unsigned int level) const
15522{
15523 // This function may be called on parallel triangulations on levels
15524 // that exist globally, but not on the local portion of the
15525 // triangulation. In that case, just return the end iterator.
15526 //
15527 // We need to use levels.size() instead of n_levels() because the
15528 // latter function uses the cache, but we need to be able to call
15529 // this function at a time when the cache is not currently up to
15530 // date.
15531 if (level >= levels.size())
15532 {
15533 Assert(level < n_global_levels(),
15534 ExcInvalidLevel(level, n_global_levels()));
15535 return end_line();
15536 }
15537
15538 switch (dim)
15539 {
15540 case 1:
15541 // Query whether the given level is valid for the local portion of the
15542 // triangulation.
15543 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15544
15545 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15546 return end_line();
15547
15548 return raw_line_iterator(
15549 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15550
15551 default:
15552 Assert(level == 0, ExcFacesHaveNoLevel());
15553 return raw_line_iterator(
15554 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15555 }
15556}
15557
15558
15559template <int dim, int spacedim>
15560DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15562 Triangulation<dim, spacedim>::begin_line(const unsigned int level) const
15563{
15564 // level is checked in begin_raw
15565 raw_line_iterator ri = begin_raw_line(level);
15566 if (ri.state() != IteratorState::valid)
15567 return ri;
15568 while (ri->used() == false)
15569 if ((++ri).state() != IteratorState::valid)
15570 return ri;
15571 return ri;
15572}
15573
15574
15575
15576template <int dim, int spacedim>
15577DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15580 const unsigned int level) const
15581{
15582 // level is checked in begin_raw
15583 line_iterator i = begin_line(level);
15584 if (i.state() != IteratorState::valid)
15585 return i;
15586 while (i->has_children())
15587 if ((++i).state() != IteratorState::valid)
15588 return i;
15589 return i;
15590}
15591
15592
15593
15594template <int dim, int spacedim>
15595DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15598{
15599 return raw_line_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15600 -1,
15601 -1);
15602}
15603
15604#endif
15605
15606/*------------------------ Quad iterator functions ------------------------*/
15607
15608#ifndef DOXYGEN
15609
15610template <int dim, int spacedim>
15611DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15613 Triangulation<dim, spacedim>::begin_raw_quad(const unsigned int level) const
15614{
15615 // This function may be called on parallel triangulations on levels
15616 // that exist globally, but not on the local portion of the
15617 // triangulation. In that case, just return the end iterator.
15618 //
15619 // We need to use levels.size() instead of n_levels() because the
15620 // latter function uses the cache, but we need to be able to call
15621 // this function at a time when the cache is not currently up to
15622 // date.
15623 if (level >= levels.size())
15624 {
15625 Assert(level < n_global_levels(),
15626 ExcInvalidLevel(level, n_global_levels()));
15627 return end_quad();
15628 }
15629
15630 switch (dim)
15631 {
15632 case 1:
15633 Assert(false, ExcImpossibleInDim(1));
15634 return raw_hex_iterator();
15635 case 2:
15636 {
15637 // Query whether the given level is valid for the local portion of the
15638 // triangulation.
15639 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15640
15641 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15642 return end_quad();
15643
15644 return raw_quad_iterator(
15645 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15646 }
15647
15648 case 3:
15649 {
15650 Assert(level == 0, ExcFacesHaveNoLevel());
15651
15652 return raw_quad_iterator(
15653 const_cast<Triangulation<dim, spacedim> *>(this), 0, 0);
15654 }
15655
15656
15657 default:
15659 return raw_hex_iterator();
15660 }
15661}
15662
15663
15664
15665template <int dim, int spacedim>
15666DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15668 Triangulation<dim, spacedim>::begin_quad(const unsigned int level) const
15669{
15670 // level is checked in begin_raw
15671 raw_quad_iterator ri = begin_raw_quad(level);
15672 if (ri.state() != IteratorState::valid)
15673 return ri;
15674 while (ri->used() == false)
15675 if ((++ri).state() != IteratorState::valid)
15676 return ri;
15677 return ri;
15678}
15679
15680
15681
15682template <int dim, int spacedim>
15683DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15686 const unsigned int level) const
15687{
15688 // level is checked in begin_raw
15689 quad_iterator i = begin_quad(level);
15690 if (i.state() != IteratorState::valid)
15691 return i;
15692 while (i->has_children())
15693 if ((++i).state() != IteratorState::valid)
15694 return i;
15695 return i;
15696}
15697
15698
15699
15700template <int dim, int spacedim>
15701DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15704{
15705 return raw_quad_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15706 -1,
15707 -1);
15708}
15709
15710#endif
15711
15712/*------------------------ Hex iterator functions ------------------------*/
15713
15714#ifndef DOXYGEN
15715
15716template <int dim, int spacedim>
15717DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15719 Triangulation<dim, spacedim>::begin_raw_hex(const unsigned int level) const
15720{
15721 // This function may be called on parallel triangulations on levels
15722 // that exist globally, but not on the local portion of the
15723 // triangulation. In that case, just return the end iterator.
15724 //
15725 // We need to use levels.size() instead of n_levels() because the
15726 // latter function uses the cache, but we need to be able to call
15727 // this function at a time when the cache is not currently up to
15728 // date.
15729 if (level >= levels.size())
15730 {
15731 Assert(level < n_global_levels(),
15732 ExcInvalidLevel(level, n_global_levels()));
15733 return end_hex();
15734 }
15735
15736 switch (dim)
15737 {
15738 case 1:
15739 case 2:
15740 Assert(false, ExcImpossibleInDim(1));
15741 return raw_hex_iterator();
15742 case 3:
15743 {
15744 // Query whether the given level is valid for the local portion of the
15745 // triangulation.
15746 Assert(level < levels.size(), ExcInvalidLevel(level, levels.size()));
15747
15748 if (level >= levels.size() || levels[level]->cells.n_objects() == 0)
15749 return end_hex();
15750
15751 return raw_hex_iterator(
15752 const_cast<Triangulation<dim, spacedim> *>(this), level, 0);
15753 }
15754
15755 default:
15757 return raw_hex_iterator();
15758 }
15759}
15760
15761
15762
15763template <int dim, int spacedim>
15764DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15766 Triangulation<dim, spacedim>::begin_hex(const unsigned int level) const
15767{
15768 // level is checked in begin_raw
15769 raw_hex_iterator ri = begin_raw_hex(level);
15770 if (ri.state() != IteratorState::valid)
15771 return ri;
15772 while (ri->used() == false)
15773 if ((++ri).state() != IteratorState::valid)
15774 return ri;
15775 return ri;
15776}
15777
15778
15779
15780template <int dim, int spacedim>
15781DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15783 Triangulation<dim, spacedim>::begin_active_hex(const unsigned int level) const
15784{
15785 // level is checked in begin_raw
15786 hex_iterator i = begin_hex(level);
15787 if (i.state() != IteratorState::valid)
15788 return i;
15789 while (i->has_children())
15790 if ((++i).state() != IteratorState::valid)
15791 return i;
15792 return i;
15793}
15794
15795
15796
15797template <int dim, int spacedim>
15798DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15801{
15802 return raw_hex_iterator(const_cast<Triangulation<dim, spacedim> *>(this),
15803 -1,
15804 -1);
15805}
15806
15807#endif
15808
15809// -------------------------------- number of cells etc ---------------
15810
15811
15812namespace internal
15813{
15814 namespace TriangulationImplementation
15815 {
15816 unsigned int
15818 {
15819 return c.n_lines;
15820 }
15821
15822
15823 unsigned int
15826 {
15827 return c.n_active_lines;
15828 }
15829
15830
15831 unsigned int
15833 {
15834 return c.n_quads;
15835 }
15836
15837
15838 unsigned int
15841 {
15842 return c.n_active_quads;
15843 }
15844
15845
15846 unsigned int
15848 {
15849 return c.n_hexes;
15850 }
15851
15852
15853 unsigned int
15856 {
15857 return c.n_active_hexes;
15858 }
15859 } // namespace TriangulationImplementation
15860} // namespace internal
15861
15862#ifndef DOXYGEN
15863
15864template <int dim, int spacedim>
15865DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15866unsigned int Triangulation<dim, spacedim>::n_cells() const
15867{
15869}
15870
15871
15872template <int dim, int spacedim>
15873DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15875{
15877}
15878
15879template <int dim, int spacedim>
15880DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15883{
15884 return n_active_cells();
15885}
15886
15887template <int dim, int spacedim>
15888DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15891{
15892 return n_cells(0);
15893}
15894
15895template <int dim, int spacedim>
15896DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15897unsigned int Triangulation<dim, spacedim>::n_faces() const
15898{
15899 switch (dim)
15900 {
15901 case 1:
15902 return n_used_vertices();
15903 case 2:
15904 return n_lines();
15905 case 3:
15906 return n_quads();
15907 default:
15909 }
15910 return 0;
15911}
15912
15913
15914template <int dim, int spacedim>
15915DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15917{
15918 switch (dim)
15919 {
15920 case 1:
15921 return n_vertices();
15922 case 2:
15923 return n_raw_lines();
15924 case 3:
15925 return n_raw_quads();
15926 default:
15928 }
15929 return 0;
15930}
15931
15932
15933template <int dim, int spacedim>
15934DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15936{
15937 switch (dim)
15938 {
15939 case 1:
15940 return n_used_vertices();
15941 case 2:
15942 return n_active_lines();
15943 case 3:
15944 return n_active_quads();
15945 default:
15947 }
15948 return 0;
15949}
15950
15951
15952template <int dim, int spacedim>
15953DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15955 const unsigned int level) const
15956{
15957 switch (dim)
15958 {
15959 case 1:
15960 return n_raw_lines(level);
15961 case 2:
15962 return n_raw_quads(level);
15963 case 3:
15964 return n_raw_hexs(level);
15965 default:
15967 }
15968 return 0;
15969}
15970
15971
15972
15973template <int dim, int spacedim>
15974DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15976 const unsigned int level) const
15977{
15978 switch (dim)
15979 {
15980 case 1:
15981 return n_lines(level);
15982 case 2:
15983 return n_quads(level);
15984 case 3:
15985 return n_hexs(level);
15986 default:
15988 }
15989 return 0;
15990}
15991
15992
15993
15994template <int dim, int spacedim>
15995DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
15997 const unsigned int level) const
15998{
15999 switch (dim)
16000 {
16001 case 1:
16002 return n_active_lines(level);
16003 case 2:
16004 return n_active_quads(level);
16005 case 3:
16006 return n_active_hexs(level);
16007 default:
16009 }
16010 return 0;
16011}
16012
16013
16014template <int dim, int spacedim>
16015DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16017{
16018 if (anisotropic_refinement == false)
16019 {
16020 for (unsigned int lvl = 0; lvl < n_global_levels() - 1; ++lvl)
16021 if (n_active_cells(lvl) != 0)
16022 return true;
16023 }
16024 else
16025 {
16026 for (const auto &cell : active_cell_iterators())
16027 for (const auto &i : cell->face_indices())
16028 if (cell->face(i)->has_children())
16029 return true;
16030 }
16031 return false;
16032}
16033
16034
16035template <int dim, int spacedim>
16036DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16037unsigned int Triangulation<dim, spacedim>::n_lines() const
16038{
16039 return number_cache.n_lines;
16040}
16041
16042
16043
16044template <int dim, int spacedim>
16045DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16047 const unsigned int level) const
16048{
16049 if (dim == 1)
16050 {
16051 AssertIndexRange(level, n_levels());
16052 return levels[level]->cells.n_objects();
16053 }
16054
16055 Assert(false, ExcFacesHaveNoLevel());
16056 return 0;
16057}
16058
16059
16060template <int dim, int spacedim>
16061DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16063{
16064 if (dim == 1)
16065 {
16067 return 0;
16068 }
16069
16070 return faces->lines.n_objects();
16071}
16072
16073
16074template <int dim, int spacedim>
16075DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16077 const unsigned int level) const
16078{
16079 AssertIndexRange(level, number_cache.n_lines_level.size());
16080 Assert(dim == 1, ExcFacesHaveNoLevel());
16081 return number_cache.n_lines_level[level];
16082}
16083
16084
16085template <int dim, int spacedim>
16086DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16088{
16089 return number_cache.n_active_lines;
16090}
16091
16092
16093template <int dim, int spacedim>
16094DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16096 const unsigned int level) const
16097{
16098 AssertIndexRange(level, number_cache.n_lines_level.size());
16099 Assert(dim == 1, ExcFacesHaveNoLevel());
16100
16101 return number_cache.n_active_lines_level[level];
16102}
16103
16104
16105
16106template <int dim, int spacedim>
16107DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16108unsigned int Triangulation<dim, spacedim>::n_quads() const
16109{
16110 if constexpr (dim == 1)
16111 return 0;
16112 else
16113 return number_cache.n_quads;
16114}
16115
16116
16117
16118template <int dim, int spacedim>
16119DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16121 const unsigned int level) const
16122{
16123 (void)level;
16124 if constexpr (dim == 1)
16125 return 0;
16126 else if constexpr (dim == 2)
16127 {
16128 AssertIndexRange(level, number_cache.n_quads_level.size());
16129 return number_cache.n_quads_level[level];
16130 }
16131 else if constexpr (dim == 3)
16132 Assert(dim < 3, ExcFacesHaveNoLevel());
16133 else
16135
16137}
16138
16139
16140
16141template <int dim, int spacedim>
16142DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16144{
16145 if constexpr (dim == 1)
16146 return 0;
16147 else if constexpr (dim == 2)
16149 else if constexpr (dim == 3)
16150 return faces->quads.n_objects();
16151 else
16153
16155}
16156
16157
16158
16159template <int dim, int spacedim>
16160DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16162 const unsigned int level) const
16163{
16164 (void)level;
16165 if constexpr (dim == 1)
16166 return 0;
16167 else if constexpr (dim == 2)
16168 {
16169 AssertIndexRange(level, n_levels());
16170 return levels[level]->cells.n_objects();
16171 }
16172 else if constexpr (dim == 3)
16173 Assert(dim < 3, ExcFacesHaveNoLevel());
16174 else
16176
16178}
16179
16180
16181
16182template <int dim, int spacedim>
16183DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16185{
16186 if constexpr (dim == 1)
16187 return 0;
16188 else
16189 return number_cache.n_active_quads;
16190}
16191
16192
16193
16194template <int dim, int spacedim>
16195DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16197 const unsigned int level) const
16198{
16199 (void)level;
16200 if constexpr (dim == 1)
16201 return 0;
16202 else if constexpr (dim == 2)
16203 {
16204 AssertIndexRange(level, number_cache.n_quads_level.size());
16205 return number_cache.n_active_quads_level[level];
16206 }
16207 else if constexpr (dim == 3)
16208 Assert(dim < 3, ExcFacesHaveNoLevel());
16209 else
16211
16213}
16214
16215
16216
16217template <int dim, int spacedim>
16218DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16219unsigned int Triangulation<dim, spacedim>::n_hexs() const
16220{
16221 if constexpr (dim == 3)
16222 return number_cache.n_hexes;
16223 else
16224 return 0;
16225}
16226
16227
16228
16229template <int dim, int spacedim>
16230DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16232 const unsigned int level) const
16233{
16234 (void)level;
16235 if constexpr (dim == 3)
16236 {
16237 AssertIndexRange(level, number_cache.n_hexes_level.size());
16238 return number_cache.n_hexes_level[level];
16239 }
16240 else
16241 return 0;
16242}
16243
16244
16245
16246template <int dim, int spacedim>
16247DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16249 const unsigned int level) const
16250{
16251 (void)level;
16252 if constexpr (dim == 3)
16253 {
16254 AssertIndexRange(level, n_levels());
16255 return levels[level]->cells.n_objects();
16256 }
16257 else
16258 return 0;
16259}
16260
16261
16262template <int dim, int spacedim>
16263DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16265{
16266 if constexpr (dim == 3)
16267 return number_cache.n_active_hexes;
16268 else
16269 return 0;
16270}
16271
16272
16273
16274template <int dim, int spacedim>
16275DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16277 const unsigned int level) const
16278{
16279 (void)level;
16280 if constexpr (dim == 3)
16281 {
16282 AssertIndexRange(level, number_cache.n_hexes_level.size());
16283 return number_cache.n_active_hexes_level[level];
16284 }
16285 else
16286 return 0;
16287}
16288
16289
16290
16291template <int dim, int spacedim>
16292DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16294{
16295 return std::count(vertices_used.begin(), vertices_used.end(), true);
16296}
16297
16298
16299
16300template <int dim, int spacedim>
16301DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16302const std::vector<bool> &Triangulation<dim, spacedim>::get_used_vertices() const
16303{
16304 return vertices_used;
16305}
16306
16307#endif
16308
16309template <>
16310unsigned int
16312{
16313 return 2;
16314}
16315
16316
16317
16318template <>
16319unsigned int
16321{
16322 return 2;
16323}
16324
16325
16326template <>
16327unsigned int
16329{
16330 return 2;
16331}
16332
16333#ifndef DOXYGEN
16334
16335template <int dim, int spacedim>
16338{
16339 cell_iterator cell = begin(0),
16340 endc = (n_levels() > 1 ? begin(1) : cell_iterator(end()));
16341 // store the largest index of the
16342 // vertices used on level 0
16343 unsigned int max_vertex_index = 0;
16344 for (; cell != endc; ++cell)
16345 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16346 if (cell->vertex_index(vertex) > max_vertex_index)
16347 max_vertex_index = cell->vertex_index(vertex);
16348
16349 // store the number of times a cell
16350 // touches a vertex. An unsigned
16351 // int should suffice, even for
16352 // larger dimensions
16353 std::vector<unsigned short int> usage_count(max_vertex_index + 1, 0);
16354 // touch a vertex's usage count
16355 // every time we find an adjacent
16356 // element
16357 for (cell = begin(); cell != endc; ++cell)
16358 for (const unsigned int vertex : GeometryInfo<dim>::vertex_indices())
16359 ++usage_count[cell->vertex_index(vertex)];
16360
16362 static_cast<unsigned int>(
16363 *std::max_element(usage_count.begin(), usage_count.end())));
16364}
16365
16366
16367
16368template <int dim, int spacedim>
16369DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16372{
16374}
16375
16376
16377
16378template <int dim, int spacedim>
16379DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16380Triangulation<dim, spacedim> &Triangulation<dim, spacedim>::get_triangulation()
16381{
16382 return *this;
16383}
16384
16385
16386
16387template <int dim, int spacedim>
16388DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16389const Triangulation<dim, spacedim>
16391{
16392 return *this;
16393}
16394
16395
16396
16397template <int dim, int spacedim>
16398DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16400 const std::vector<GridTools::PeriodicFacePair<cell_iterator>>
16401 &periodicity_vector)
16402{
16403 periodic_face_pairs_level_0.insert(periodic_face_pairs_level_0.end(),
16404 periodicity_vector.begin(),
16405 periodicity_vector.end());
16406
16407 // Now initialize periodic_face_map
16408 update_periodic_face_map();
16409}
16410
16411
16412
16413template <int dim, int spacedim>
16414DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16415const typename std::map<
16416 std::pair<typename Triangulation<dim, spacedim>::cell_iterator, unsigned int>,
16417 std::pair<std::pair<typename Triangulation<dim, spacedim>::cell_iterator,
16418 unsigned int>,
16421{
16422 return periodic_face_map;
16423}
16424
16425
16426template <int dim, int spacedim>
16427DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16429{
16430 // We only update the cell relations here for serial triangulations.
16431 // For other triangulations, this is done at other stages of
16432 // mesh creation and mesh refinement.
16433 if (dynamic_cast<parallel::DistributedTriangulationBase<dim, spacedim> *>(
16434 this))
16435 return;
16436
16437 this->local_cell_relations.clear();
16438 this->local_cell_relations.reserve(this->n_active_cells());
16439
16440 for (const auto &cell : this->active_cell_iterators())
16441 this->local_cell_relations.emplace_back(
16443}
16444
16445
16446
16447template <int dim, int spacedim>
16448DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16450{
16451 if (dynamic_cast<parallel::DistributedTriangulationBase<dim, spacedim> *>(
16452 this))
16453 return;
16454
16455 // pack data before triangulation gets updated
16456 if (this->cell_attached_data.n_attached_data_sets > 0)
16457 {
16458 this->local_cell_relations.clear();
16459
16460 for (const auto &cell : this->active_cell_iterators())
16461 {
16462 const bool children_will_be_coarsened =
16463 (cell->level() > 0) && (cell->coarsen_flag_set());
16464
16465 if (children_will_be_coarsened == false)
16466 {
16467 ::CellStatus status =
16468 cell->refine_flag_set() ?
16471
16472 local_cell_relations.emplace_back(cell, status);
16473 }
16474 else if (cell->parent()->child_iterator_to_index(cell) == 0)
16475 {
16476 local_cell_relations.emplace_back(
16477 cell->parent(),
16479
16480 for (unsigned int i = 1; i < cell->parent()->n_children(); ++i)
16481 local_cell_relations.emplace_back(
16482 cell->parent(), ::CellStatus::cell_invalid);
16483 }
16484 }
16485
16486 // pack data
16487 this->data_serializer.pack_data(
16488 this->local_cell_relations,
16489 this->cell_attached_data.pack_callbacks_fixed,
16490 this->cell_attached_data.pack_callbacks_variable,
16491 this->get_mpi_communicator());
16492
16493 // dummy copy of data
16494 this->data_serializer.dest_data_fixed =
16495 this->data_serializer.src_data_fixed;
16496 this->data_serializer.dest_data_variable =
16497 this->data_serializer.src_data_variable;
16498 this->data_serializer.dest_sizes_variable =
16499 this->data_serializer.src_sizes_variable;
16500 }
16501}
16502
16503
16504
16505template <int dim, int spacedim>
16506DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16508{
16509 if (dynamic_cast<parallel::DistributedTriangulationBase<dim, spacedim> *>(
16510 this))
16511 return;
16512
16513 // transfer data after triangulation got updated
16514 if (this->cell_attached_data.n_attached_data_sets > 0)
16515 {
16516 std::vector<typename internal::CellAttachedDataSerializer<dim, spacedim>::
16517 cell_relation_t>
16518 temp;
16519
16520 for (const auto &cell : local_cell_relations)
16521 {
16522 if (cell.first->has_children())
16523 {
16526
16527 temp.emplace_back(cell.first->child(0),
16529 }
16530 else
16531 temp.push_back(cell);
16532 }
16533
16534 this->local_cell_relations = std::move(temp);
16535 }
16536}
16537
16538
16539
16540template <int dim, int spacedim>
16541DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16543{
16544 // Call our version of prepare_coarsening_and_refinement() even if a derived
16545 // class like parallel::distributed::Triangulation overrides it. Their
16546 // function will be called in their execute_coarsening_and_refinement()
16547 // function. Even in a distributed computation our job here is to reconstruct
16548 // the local part of the mesh and as such checking our flags is enough.
16550
16551 // verify a case with which we have had
16552 // some difficulty in the past (see the
16553 // deal.II/coarsening_* tests)
16554 if (smooth_grid & limit_level_difference_at_vertices)
16555 Assert(satisfies_level1_at_vertex_rule(*this), ExcInternalError());
16556
16557 // Inform all listeners about beginning of refinement.
16558 signals.pre_refinement();
16559
16560 this->pack_data_serial();
16561
16562 execute_coarsening();
16563
16564 const DistortedCellList cells_with_distorted_children = execute_refinement();
16565
16566 // We need to update the cell relations in order to be able to
16567 // deserialize data. Later on, update_cell_relations is called to mark all
16568 // active cells with the cell_will_persist status.
16569 this->unpack_data_serial();
16570
16571 reset_cell_vertex_indices_cache();
16572
16573 // If the line_to_adjacent_cell_map is populated, clear it, as it must
16574 // be recomputed every time the mesh changes.
16575 line_to_adjacent_cells_map.reset();
16576
16577 // verify a case with which we have had
16578 // some difficulty in the past (see the
16579 // deal.II/coarsening_* tests)
16580 if (smooth_grid & limit_level_difference_at_vertices)
16581 Assert(satisfies_level1_at_vertex_rule(*this) == true, ExcInternalError());
16582
16583 // finally build up neighbor connectivity information, and set
16584 // active cell indices
16585 this->policy->update_neighbors(*this);
16586 reset_active_cell_indices();
16587
16588 reset_global_cell_indices(); // TODO: better place?
16589
16590 // Inform all listeners about end of refinement.
16591 signals.post_refinement();
16592
16593 AssertThrow(cells_with_distorted_children.distorted_cells.empty(),
16594 cells_with_distorted_children);
16595
16596 update_periodic_face_map();
16597
16598 if (this->cell_attached_data.n_attached_data_sets == 0)
16599 this->update_cell_relations();
16600
16601 if constexpr (running_in_debug_mode())
16602 {
16603 // In debug mode, we want to check for some consistency of the
16604 // result of this function. Because there are multiple exit
16605 // paths, put this check into a ScopeExit object that is
16606 // executed on each of the exit paths.
16607 //
16608 // Specifically, check on exit of this function that if a quad
16609 // cell has been refined, all of its children have neighbors
16610 // in all directions in which the parent cell has neighbors as
16611 // well. The children's neighbors are either the parent
16612 // neighbor or the parent neighbor's children, or simply one of
16613 // the other children of the current cell. This check is
16614 // useful because if one creates a triangulation with an
16615 // inconsistently ordered set of cells (e.g., because one has
16616 // forgotten to call GridTools::consistently_order_cells()),
16617 // then this relatively simple invariant is violated -- so the
16618 // check here can be used to catch that case, at least
16619 // sometimes.
16620 //
16621 // In 1d, this situation cannot happen. In 3d, we have explicit
16622 // orientation flags to ensure that it is not necessary to re-orient
16623 // cells at the beginning. But in both cases, the invariant should
16624 // still hold as long as the cell is a hypercube.
16625 for (const auto &cell : cell_iterators())
16626 {
16627 if (cell->has_children() && cell->reference_cell().is_hyper_cube())
16628 for (const unsigned int f : cell->face_indices())
16629 if (cell->at_boundary(f) == false)
16630 {
16631 for (const auto &child : cell->child_iterators())
16632 {
16633 Assert(
16634 child->at_boundary(f) == false,
16635 ExcMessage(
16636 "We ended up with a triangulation whose child cells "
16637 "are not connected to their neighbors as expected. "
16638 "When you created the triangulation, did you forget "
16639 "to call GridTools::consistently_order_cells() "
16640 "before calling Triangulation::create_triangulation()?"));
16641 }
16642 }
16643 }
16644 }
16645}
16646
16647
16648
16649template <int dim, int spacedim>
16650DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16652{
16653 unsigned int active_cell_index = 0;
16654 for (raw_cell_iterator cell = begin_raw(); cell != end(); ++cell)
16655 if ((cell->used() == false) || cell->has_children())
16656 cell->set_active_cell_index(numbers::invalid_unsigned_int);
16657 else
16658 {
16659 cell->set_active_cell_index(active_cell_index);
16660 ++active_cell_index;
16661 }
16662
16663 Assert(active_cell_index == n_active_cells(), ExcInternalError());
16664}
16665
16666
16667
16668template <int dim, int spacedim>
16669DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16671{
16672 types::global_cell_index active_cell_index = 0;
16673 for (unsigned int l = 0; l < levels.size(); ++l)
16674 {
16675 types::global_cell_index level_cell_index = 0;
16676 for (const auto &cell : cell_iterators_on_level(l))
16677 {
16678 cell->set_global_level_cell_index(level_cell_index++);
16679 if (cell->is_active())
16680 cell->set_global_active_cell_index(active_cell_index++);
16681 }
16682 }
16683 AssertDimension(active_cell_index, this->n_active_cells());
16684}
16685
16686
16687
16688template <int dim, int spacedim>
16689DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16691{
16692 std::array<unsigned int, ReferenceCells::max_n_vertices<dim>()>
16693 cell_vertices{};
16694 for (unsigned int l = 0; l < levels.size(); ++l)
16695 for (const auto &cell : cell_iterators_on_level(l))
16696 {
16697 if constexpr (running_in_debug_mode())
16698 cell_vertices.fill(numbers::invalid_unsigned_int);
16699
16700 const auto n_vertices = cell->n_vertices();
16701 Assert(n_vertices <= cell_vertices.size(), ExcInternalError());
16703 cell, ArrayView<unsigned int>(cell_vertices.data(), n_vertices));
16704 for (unsigned int vertex_no = 0; vertex_no < n_vertices; ++vertex_no)
16705 levels[l]->set_cached_vertex_index(cell->index(),
16706 vertex_no,
16707 cell_vertices[vertex_no]);
16708 }
16709}
16710
16711
16712
16713template <int dim, int spacedim>
16714DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16716{
16717 // first empty the currently stored objects
16718 periodic_face_map.clear();
16719
16720 typename std::vector<
16721 GridTools::PeriodicFacePair<cell_iterator>>::const_iterator it;
16722 for (it = periodic_face_pairs_level_0.begin();
16723 it != periodic_face_pairs_level_0.end();
16724 ++it)
16725 {
16726 update_periodic_face_map_recursively<dim, spacedim>(it->cell[0],
16727 it->cell[1],
16728 it->face_idx[0],
16729 it->face_idx[1],
16730 it->orientation,
16731 periodic_face_map);
16732
16733 const auto face_reference_cell =
16734 it->cell[0]->reference_cell().face_reference_cell(it->face_idx[0]);
16735 // for the other way, we need to invert the orientation
16736 update_periodic_face_map_recursively<dim, spacedim>(
16737 it->cell[1],
16738 it->cell[0],
16739 it->face_idx[1],
16740 it->face_idx[0],
16741 face_reference_cell.get_inverse_combined_orientation(it->orientation),
16742 periodic_face_map);
16743 }
16744
16745 // check consistency
16746 typename std::map<std::pair<cell_iterator, unsigned int>,
16747 std::pair<std::pair<cell_iterator, unsigned int>,
16749 it_test;
16750 for (it_test = periodic_face_map.begin(); it_test != periodic_face_map.end();
16751 ++it_test)
16752 {
16754 it_test->first.first;
16756 it_test->second.first.first;
16757 if (cell_1->level() == cell_2->level())
16758 {
16759 // if both cells have the same neighbor, then the same pair
16760 // order swapped has to be in the map
16761 Assert(periodic_face_map[it_test->second.first].first ==
16762 it_test->first,
16764 }
16765 }
16766}
16767
16768
16769
16770template <int dim, int spacedim>
16771DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16772const std::vector<ReferenceCell<dim>>
16774{
16775 return this->reference_cells;
16776}
16777
16778
16779
16780template <int dim, int spacedim>
16781DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16783{
16784 Assert(this->reference_cells.size() > 0,
16785 ExcMessage("You can't ask about the kinds of reference "
16786 "cells used by this triangulation if the "
16787 "triangulation doesn't yet have any cells in it."));
16788 return (this->reference_cells.size() == 1 &&
16789 this->reference_cells[0].is_hyper_cube());
16790}
16791
16792
16793
16794template <int dim, int spacedim>
16795DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16797{
16798 Assert(this->reference_cells.size() > 0,
16799 ExcMessage("You can't ask about the kinds of reference "
16800 "cells used by this triangulation if the "
16801 "triangulation doesn't yet have any cells in it."));
16802 return (this->reference_cells.size() == 1 &&
16803 this->reference_cells[0].is_simplex());
16804}
16805
16806
16807
16808template <int dim, int spacedim>
16809DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16811{
16812 Assert(this->reference_cells.size() > 0,
16813 ExcMessage("You can't ask about the kinds of reference "
16814 "cells used by this triangulation if the "
16815 "triangulation doesn't yet have any cells in it."));
16816 return reference_cells.size() > 1 ||
16817 ((reference_cells[0].is_hyper_cube() == false) &&
16818 (reference_cells[0].is_simplex() == false));
16819}
16820
16821
16822
16823template <int dim, int spacedim>
16824DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16826 const std::function<std::vector<char>(const cell_iterator &,
16827 const ::CellStatus)>
16828 &pack_callback,
16829 const bool returns_variable_size_data)
16830{
16831 unsigned int handle = numbers::invalid_unsigned_int;
16832
16833 // Add new callback function to the corresponding register.
16834 // Encode handles according to returns_variable_size_data.
16835 if (returns_variable_size_data)
16836 {
16837 handle = 2 * this->cell_attached_data.pack_callbacks_variable.size();
16838 this->cell_attached_data.pack_callbacks_variable.push_back(pack_callback);
16839 }
16840 else
16841 {
16842 handle = 2 * this->cell_attached_data.pack_callbacks_fixed.size() + 1;
16843 this->cell_attached_data.pack_callbacks_fixed.push_back(pack_callback);
16844 }
16845
16846 // Increase overall counter.
16847 ++this->cell_attached_data.n_attached_data_sets;
16848
16849 return handle;
16850}
16851
16852
16853
16854template <int dim, int spacedim>
16855DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16857 const unsigned int handle,
16858 const std::function<
16859 void(const cell_iterator &,
16860 const ::CellStatus,
16861 const boost::iterator_range<std::vector<char>::const_iterator> &)>
16862 &unpack_callback)
16863{
16864 // perform unpacking
16865 this->data_serializer.unpack_data(this->local_cell_relations,
16866 handle,
16867 unpack_callback);
16868
16869 // decrease counters
16870 --this->cell_attached_data.n_attached_data_sets;
16871 if (this->cell_attached_data.n_attached_deserialize > 0)
16872 --this->cell_attached_data.n_attached_deserialize;
16873
16874 // important: only remove data if we are not in the deserialization
16875 // process. There, each SolutionTransfer registers and unpacks before
16876 // the next one does this, so n_attached_data_sets is only 1 here. This
16877 // would destroy the saved data before the second SolutionTransfer can
16878 // get it. This created a bug that is documented in
16879 // tests/mpi/p4est_save_03 with more than one SolutionTransfer.
16880
16881 if (this->cell_attached_data.n_attached_data_sets == 0 &&
16882 this->cell_attached_data.n_attached_deserialize == 0)
16883 {
16884 // everybody got their data, time for cleanup!
16885 this->cell_attached_data.pack_callbacks_fixed.clear();
16886 this->cell_attached_data.pack_callbacks_variable.clear();
16887 this->data_serializer.clear();
16888
16889 // reset all cell_status entries after coarsening/refinement
16890 for (auto &cell_rel : this->local_cell_relations)
16891 cell_rel.second = ::CellStatus::cell_will_persist;
16892 }
16893}
16894
16895
16896
16897template <int dim, int spacedim>
16898DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16900 const unsigned int global_first_cell,
16901 const unsigned int global_num_cells,
16902 const std::string &file_basename) const
16903{
16904 // cast away constness
16905 auto tria = const_cast<Triangulation<dim, spacedim> *>(this);
16906
16907 // each cell should have been flagged `CellStatus::cell_will_persist`
16908 for (const auto &cell_rel : this->local_cell_relations)
16909 {
16910 (void)cell_rel;
16911 Assert((cell_rel.second == // cell_status
16914 }
16915
16916 if (this->cell_attached_data.n_attached_data_sets > 0)
16917 {
16918 // pack attached data first
16919 tria->data_serializer.pack_data(
16920 tria->local_cell_relations,
16921 tria->cell_attached_data.pack_callbacks_fixed,
16922 tria->cell_attached_data.pack_callbacks_variable,
16923 this->get_mpi_communicator());
16924
16925 // then store buffers in file
16926 tria->data_serializer.save(global_first_cell,
16927 global_num_cells,
16928 file_basename,
16929 this->get_mpi_communicator());
16930
16931 // and release the memory afterwards
16932 tria->data_serializer.clear();
16933 }
16934
16935 // clear all of the callback data, as explained in the documentation of
16936 // register_data_attach()
16937 {
16938 tria->cell_attached_data.n_attached_data_sets = 0;
16939 tria->cell_attached_data.pack_callbacks_fixed.clear();
16940 tria->cell_attached_data.pack_callbacks_variable.clear();
16941 }
16942}
16943
16944
16945template <int dim, int spacedim>
16946DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16948 const unsigned int global_first_cell,
16949 const unsigned int global_num_cells,
16950 const unsigned int local_num_cells,
16951 const std::string &file_basename,
16952 const unsigned int n_attached_deserialize_fixed,
16953 const unsigned int n_attached_deserialize_variable)
16954{
16955 // load saved data, if any was stored
16956 if (this->cell_attached_data.n_attached_deserialize > 0)
16957 {
16958 this->data_serializer.load(global_first_cell,
16959 global_num_cells,
16960 local_num_cells,
16961 file_basename,
16962 n_attached_deserialize_fixed,
16963 n_attached_deserialize_variable,
16964 this->get_mpi_communicator());
16965
16966 this->data_serializer.unpack_cell_status(this->local_cell_relations);
16967
16968 if constexpr (running_in_debug_mode())
16969 {
16970 // the CellStatus of all stored cells should always be
16971 // CellStatus::cell_will_persist.
16972 for (const auto &cell_rel : this->local_cell_relations)
16973 {
16974 Assert((cell_rel.second == // cell_status
16977 }
16978 }
16979 }
16980}
16981
16982
16983template <int dim, int spacedim>
16984DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
16986{
16987 levels.clear();
16988 faces.reset();
16989
16990 vertices.clear();
16991 vertices_used.clear();
16992
16993 manifolds.clear();
16994
16995 // In 1d, also reset vertex-to-(boundary|manifold) maps to empty maps
16996 if (dim == 1)
16997 {
16998 Assert(vertex_to_boundary_id_map_1d != nullptr, ExcInternalError());
16999 vertex_to_boundary_id_map_1d->clear();
17000
17001 Assert(vertex_to_manifold_id_map_1d != nullptr, ExcInternalError());
17002 vertex_to_manifold_id_map_1d->clear();
17003 }
17004 else
17005 {
17006 // For dim>1, these maps should simply not exist.
17007 Assert(vertex_to_boundary_id_map_1d == nullptr, ExcInternalError());
17008 Assert(vertex_to_manifold_id_map_1d == nullptr, ExcInternalError());
17009 }
17010
17011
17012 number_cache = internal::TriangulationImplementation::NumberCache<dim>();
17013}
17014
17015
17016
17017template <int dim, int spacedim>
17018DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
17019typename Triangulation<dim, spacedim>::DistortedCellList
17021{
17022 const DistortedCellList cells_with_distorted_children =
17023 this->policy->execute_refinement(*this, check_for_distorted_cells);
17024
17025
17026
17027 // re-compute number of lines
17029 *this, levels.size(), number_cache);
17030
17031 if constexpr (running_in_debug_mode())
17032 {
17033 for (const auto &level : levels)
17034 monitor_memory(level->cells, dim);
17035
17036 // check whether really all refinement flags are reset (also of
17037 // previously non-active cells which we may not have touched. If the
17038 // refinement flag of a non-active cell is set, something went wrong
17039 // since the cell-accessors should have caught this)
17040 for (const auto &cell : this->cell_iterators())
17041 Assert(!cell->refine_flag_set(), ExcInternalError());
17042 }
17043
17044 return cells_with_distorted_children;
17045}
17046
17047
17048
17049template <int dim, int spacedim>
17050DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
17052{
17053 // first find out if there are any cells at all to be coarsened in the
17054 // loop below
17055 const cell_iterator endc = end();
17056 bool do_coarsen = false;
17057 if (levels.size() >= 2)
17058 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17059 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17060 {
17061 do_coarsen = true;
17062 break;
17063 }
17064
17065 if (!do_coarsen)
17066 return;
17067
17068 // create a vector counting for each line and quads how many cells contain
17069 // the respective object. this is used later to decide which lines can be
17070 // deleted after coarsening a cell.
17071 std::vector<unsigned int> line_cell_count(dim > 1 ? this->n_raw_lines() : 0);
17072 std::vector<unsigned int> quad_cell_count(dim > 2 ? this->n_raw_quads() : 0);
17073 if (dim > 1)
17074 for (const auto &cell : this->cell_iterators())
17075 {
17076 if (dim > 2)
17077 {
17078 const auto line_indices = internal::TriaAccessorImplementation::
17079 Implementation::get_line_indices_of_cell(*cell);
17080 // avoid a compiler warning by fixing the max number of
17081 // loop iterations to 12
17082 const unsigned int n_lines = std::min(cell->n_lines(), 12u);
17083 for (unsigned int l = 0; l < n_lines; ++l)
17084 ++line_cell_count[line_indices[l]];
17085 for (const unsigned int q : cell->face_indices())
17086 ++quad_cell_count[cell->face_index(q)];
17087 }
17088 else
17089 for (unsigned int l = 0; l < cell->n_lines(); ++l)
17090 ++line_cell_count[cell->line(l)->index()];
17091 }
17092
17093 // Since the loop goes over used cells we only need not worry about
17094 // deleting some cells since the ++operator will then just hop over them
17095 // if we should hit one. Do the loop in the reverse way since we may
17096 // only delete some cells if their neighbors have already been deleted
17097 // (if the latter are on a higher level for example). In effect, only
17098 // those cells are deleted of which originally all children were flagged
17099 // and for which all children are on the same refinement level. Note
17100 // that because of the effects of
17101 // @p{fix_coarsen_flags}, of a cell either all or no children must be
17102 // flagged for coarsening, so it is ok to only check the first child
17103 //
17104 // since we delete the *children* of cells, we can ignore cells on the
17105 // highest level, i.e., level must be less than or equal to
17106 // n_levels()-2.
17107 if (levels.size() >= 2)
17108 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17109 if (!cell->is_active() && cell->child(0)->coarsen_flag_set())
17110 {
17111 for (unsigned int child = 0; child < cell->n_children(); ++child)
17112 {
17113 Assert(cell->child(child)->coarsen_flag_set(),
17115 cell->child(child)->clear_coarsen_flag();
17116 }
17117 // inform all listeners that cell coarsening is going to happen
17118 signals.pre_coarsening_on_cell(cell);
17119 // use a separate function, since this is dimension specific
17120 this->policy->delete_children(*this,
17121 cell,
17122 line_cell_count,
17123 quad_cell_count);
17124 }
17125
17126 // re-compute number of lines and quads
17128 *this, levels.size(), number_cache);
17129}
17130
17131
17132
17133template <int dim, int spacedim>
17134DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
17136{
17137 // copy a piece of code from prepare_coarsening_and_refinement that
17138 // ensures that the level difference at vertices is limited if so
17139 // desired. we need this code here since at least in 1d we don't
17140 // call the dimension-independent version of
17141 // prepare_coarsening_and_refinement function. in 2d and 3d, having
17142 // this hunk here makes our lives a bit easier as well as it takes
17143 // care of these cases earlier than it would otherwise happen.
17144 //
17145 // the main difference to the code in p_c_and_r is that here we
17146 // absolutely have to make sure that we get things right, i.e. that
17147 // in particular we set flags right if
17148 // limit_level_difference_at_vertices is set. to do so we iterate
17149 // until the flags don't change any more
17150 auto previous_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17151
17152 bool continue_iterating = true;
17153
17154 do
17155 {
17156 if (smooth_grid & limit_level_difference_at_vertices)
17157 {
17158 Assert(!anisotropic_refinement,
17159 ExcMessage("In case of anisotropic refinement the "
17160 "limit_level_difference_at_vertices flag for "
17161 "mesh smoothing must not be set!"));
17162
17163 // store highest level one of the cells adjacent to a vertex
17164 // belongs to
17165 std::vector<int> vertex_level(vertices.size(), 0);
17166 for (const auto &cell : this->active_cell_iterators())
17167 {
17168 if (cell->refine_flag_set())
17169 for (const unsigned int vertex : cell->vertex_indices())
17170 vertex_level[cell->vertex_index(vertex)] =
17171 std::max(vertex_level[cell->vertex_index(vertex)],
17172 cell->level() + 1);
17173 else if (!cell->coarsen_flag_set())
17174 for (const unsigned int vertex : cell->vertex_indices())
17175 vertex_level[cell->vertex_index(vertex)] =
17176 std::max(vertex_level[cell->vertex_index(vertex)],
17177 cell->level());
17178 else
17179 {
17180 // if coarsen flag is set then tentatively assume
17181 // that the cell will be coarsened. this isn't
17182 // always true (the coarsen flag could be removed
17183 // again) and so we may make an error here. we try
17184 // to correct this by iterating over the entire
17185 // process until we are converged
17186 Assert(cell->coarsen_flag_set(), ExcInternalError());
17187 for (const unsigned int vertex : cell->vertex_indices())
17188 vertex_level[cell->vertex_index(vertex)] =
17189 std::max(vertex_level[cell->vertex_index(vertex)],
17190 cell->level() - 1);
17191 }
17192 }
17193
17194
17195 // loop over all cells in reverse order. do so because we
17196 // can then update the vertex levels on the adjacent
17197 // vertices and maybe already flag additional cells in this
17198 // loop
17199 //
17200 // note that not only may we have to add additional
17201 // refinement flags, but we will also have to remove
17202 // coarsening flags on cells adjacent to vertices that will
17203 // see refinement
17204 active_cell_iterator endc = end();
17205 for (active_cell_iterator cell = last_active(); cell != endc; --cell)
17206 if (cell->refine_flag_set() == false)
17207 {
17208 for (const unsigned int vertex : cell->vertex_indices())
17209 if (vertex_level[cell->vertex_index(vertex)] >=
17210 cell->level() + 1)
17211 {
17212 // remove coarsen flag...
17213 cell->clear_coarsen_flag();
17214
17215 // ...and if necessary also refine the current
17216 // cell, at the same time updating the level
17217 // information about vertices
17218 if (vertex_level[cell->vertex_index(vertex)] >
17219 cell->level() + 1)
17220 {
17221 cell->set_refine_flag();
17222
17223 for (const unsigned int v : cell->vertex_indices())
17224 vertex_level[cell->vertex_index(v)] =
17225 std::max(vertex_level[cell->vertex_index(v)],
17226 cell->level() + 1);
17227 }
17228
17229 // continue and see whether we may, for example,
17230 // go into the inner 'if' above based on a
17231 // different vertex
17232 }
17233 }
17234 }
17235
17236 // loop over all cells and remove the coarsen flags for those cells that
17237 // have sister cells not marked for coarsening, or where some neighbors
17238 // are more refined.
17239
17240 // Coarsen flags of cells with no mother cell, i.e. on the
17241 // coarsest level, are deleted explicitly.
17242 for (const auto &acell : this->active_cell_iterators_on_level(0))
17243 acell->clear_coarsen_flag();
17244
17245 const cell_iterator endc = end();
17246 for (cell_iterator cell = begin(n_levels() - 1); cell != endc; --cell)
17247 {
17248 // nothing to do if we are already on the finest level
17249 if (cell->is_active())
17250 continue;
17251
17252 const unsigned int n_children = cell->n_children();
17253 unsigned int flagged_children = 0;
17254 for (unsigned int child = 0; child < n_children; ++child)
17255 {
17256 const auto child_cell = cell->child(child);
17257 if (child_cell->is_active() && child_cell->coarsen_flag_set())
17258 {
17259 ++flagged_children;
17260 // clear flag since we don't need it anymore
17261 child_cell->clear_coarsen_flag();
17262 }
17263 }
17264
17265 // flag the children for coarsening again if all children were
17266 // flagged and if the policy allows it
17267 if (flagged_children == n_children &&
17268 this->policy->coarsening_allowed(cell))
17269 for (unsigned int c = 0; c < n_children; ++c)
17270 {
17271 Assert(cell->child(c)->refine_flag_set() == false,
17273
17274 cell->child(c)->set_coarsen_flag();
17275 }
17276 }
17277
17278 // now see if anything has changed in the last iteration of this
17279 // function
17280 auto current_coarsen_flags = internal::extract_raw_coarsen_flags(levels);
17281
17282 continue_iterating = (current_coarsen_flags != previous_coarsen_flags);
17283 previous_coarsen_flags.swap(current_coarsen_flags);
17284 }
17285 while (continue_iterating == true);
17286}
17287
17288#endif
17289
17290// TODO: merge the following 3 functions since they are the same
17291template <>
17292bool
17294{
17295 // save the flags to determine whether something was changed in the
17296 // course of this function
17297 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17298
17299 // do nothing in 1d, except setting the coarsening flags correctly
17301
17302 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17303
17304 return (flags_before != flags_after);
17305}
17306
17307
17308
17309template <>
17310bool
17312{
17313 // save the flags to determine whether something was changed in the
17314 // course of this function
17315 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17316
17317 // do nothing in 1d, except setting the coarsening flags correctly
17319
17320 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17321
17322 return (flags_before != flags_after);
17323}
17324
17325
17326
17327template <>
17328bool
17330{
17331 // save the flags to determine whether something was changed in the
17332 // course of this function
17333 const auto flags_before = internal::extract_raw_coarsen_flags(levels);
17334
17335 // do nothing in 1d, except setting the coarsening flags correctly
17337
17338 const auto flags_after = internal::extract_raw_coarsen_flags(levels);
17339
17340 return (flags_before != flags_after);
17341}
17342
17343
17344
17345namespace
17346{
17347 // check if the given @param cell marked for coarsening would
17348 // produce an unrefined island. To break up long chains of these
17349 // cells we recursively check our neighbors in case we change this
17350 // cell. This reduces the number of outer iterations dramatically.
17351 template <int dim, int spacedim>
17352 void
17353 possibly_do_not_produce_unrefined_islands(
17355 {
17357
17358 unsigned int n_neighbors = 0;
17359 // count all neighbors that will be refined along the face of our
17360 // cell after the next step
17361 unsigned int count = 0;
17362 for (const unsigned int n : GeometryInfo<dim>::face_indices())
17363 {
17364 const typename Triangulation<dim, spacedim>::cell_iterator neighbor =
17365 cell->neighbor(n);
17366 if (neighbor.state() == IteratorState::valid)
17367 {
17368 ++n_neighbors;
17369 if (face_will_be_refined_by_neighbor(cell, n))
17370 ++count;
17371 }
17372 }
17373 // clear coarsen flags if either all existing neighbors will be
17374 // refined or all but one will be and the cell is in the interior
17375 // of the domain
17376 if (count == n_neighbors ||
17377 (count >= n_neighbors - 1 &&
17378 n_neighbors == GeometryInfo<dim>::faces_per_cell))
17379 {
17380 for (unsigned int c = 0; c < cell->n_children(); ++c)
17381 cell->child(c)->clear_coarsen_flag();
17382
17383 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17384 if (!cell->at_boundary(face) &&
17385 (!cell->neighbor(face)->is_active()) &&
17386 (cell_will_be_coarsened(cell->neighbor(face))))
17387 possibly_do_not_produce_unrefined_islands<dim, spacedim>(
17388 cell->neighbor(face));
17389 }
17390 }
17391
17392
17393 // see if the current cell needs to be refined to avoid unrefined
17394 // islands.
17395 //
17396 // there are sometimes chains of cells that induce refinement of
17397 // each other. to avoid running the loop in
17398 // prepare_coarsening_and_refinement over and over again for each
17399 // one of them, at least for the isotropic refinement case we seek
17400 // to flag neighboring elements as well as necessary. this takes
17401 // care of (slightly pathological) cases like
17402 // deal.II/mesh_smoothing_03
17403 template <int dim, int spacedim>
17404 void
17405 possibly_refine_unrefined_island(
17407 const bool allow_anisotropic_smoothing)
17408 {
17409 Assert(cell->is_active(), ExcInternalError());
17410
17411 if constexpr (running_in_debug_mode())
17412 {
17413 // If this is not a parallel::distributed::Triangulation, then we really
17414 // should only get here if the cell is marked for refinement:
17415 if (dynamic_cast<
17416 const parallel::distributed::Triangulation<dim, spacedim> *>(
17417 &cell->get_triangulation()) == nullptr)
17418 Assert(cell->refine_flag_set() == false, ExcInternalError());
17419 else
17420 // But if this is a p::d::Triangulation, then we don't have that
17421 // much control and we can get here because mesh smoothing is
17422 // requested but can not be honored because p4est controls
17423 // what gets refined. In that case, we can at least provide
17424 // a better error message.
17425 Assert(
17426 cell->refine_flag_set() == false,
17427 ExcMessage(
17428 "The triangulation is trying to avoid unrefined islands "
17429 "during mesh refinement/coarsening, as you had requested "
17430 " by passing the appropriate 'smoothing flags' to the "
17431 "constructor of the triangulation. However, for objects "
17432 "of type parallel::distributed::Triangulation, control "
17433 "over which cells get refined rests with p4est, not the "
17434 "deal.II triangulation, and consequently it is not "
17435 "always possible to avoid unrefined islands in the mesh. "
17436 "Please remove the constructor argument to the triangulation "
17437 "object that requests mesh smoothing."));
17438 }
17439
17440 // now we provide two algorithms. the first one is the standard
17441 // one, coming from the time, where only isotropic refinement was
17442 // possible. it simply counts the neighbors that are or will be
17443 // refined and compares to the number of other ones. the second
17444 // one does this check independently for each direction: if all
17445 // neighbors in one direction (normally two, at the boundary only
17446 // one) are refined, the current cell is flagged to be refined in
17447 // an according direction.
17448
17449 if (allow_anisotropic_smoothing == false)
17450 {
17451 // use first algorithm
17452 unsigned int refined_neighbors = 0, unrefined_neighbors = 0;
17453 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17454 if (!cell->at_boundary(face))
17455 {
17456 if (face_will_be_refined_by_neighbor(cell, face))
17457 ++refined_neighbors;
17458 else
17459 ++unrefined_neighbors;
17460 }
17461
17462 if (unrefined_neighbors < refined_neighbors)
17463 {
17464 cell->clear_coarsen_flag();
17465 cell->set_refine_flag();
17466
17467 // ok, so now we have flagged this cell. if we know that
17468 // there were any unrefined neighbors at all, see if any
17469 // of those will have to be refined as well
17470 if (unrefined_neighbors > 0)
17471 for (const unsigned int face : GeometryInfo<dim>::face_indices())
17472 if (!cell->at_boundary(face) &&
17473 (face_will_be_refined_by_neighbor(cell, face) == false) &&
17474 (cell->neighbor(face)->has_children() == false) &&
17475 (cell->neighbor(face)->refine_flag_set() == false))
17476 possibly_refine_unrefined_island<dim, spacedim>(
17477 cell->neighbor(face), allow_anisotropic_smoothing);
17478 }
17479 }
17480 else
17481 {
17482 // variable to store the cell refine case needed to fulfill
17483 // all smoothing requirements
17484 RefinementCase<dim> smoothing_cell_refinement_case =
17486
17487 // use second algorithm, do the check individually for each
17488 // direction
17489 for (unsigned int face_pair = 0;
17490 face_pair < GeometryInfo<dim>::faces_per_cell / 2;
17491 ++face_pair)
17492 {
17493 // variable to store the cell refine case needed to refine
17494 // at the current face pair in the same way as the
17495 // neighbors do...
17496 RefinementCase<dim> directional_cell_refinement_case =
17498
17499 for (unsigned int face_index = 0; face_index < 2; ++face_index)
17500 {
17501 unsigned int face = 2 * face_pair + face_index;
17502 // variable to store the refine case (to come) of the
17503 // face under consideration
17504 RefinementCase<dim - 1> expected_face_ref_case =
17505 RefinementCase<dim - 1>::no_refinement;
17506
17507 if (cell->neighbor(face).state() == IteratorState::valid)
17508 face_will_be_refined_by_neighbor<dim, spacedim>(
17509 cell, face, expected_face_ref_case);
17510 // now extract which refine case would be necessary to
17511 // achieve the same face refinement. set the
17512 // intersection with other requirements for the same
17513 // direction.
17514
17515 // note: using the intersection is not an obvious
17516 // decision, we could also argue that it is more
17517 // natural to use the union. however, intersection is
17518 // the less aggressive tactic and favours a smaller
17519 // number of refined cells over an intensive
17520 // smoothing. this way we try not to lose too much of
17521 // the effort we put in anisotropic refinement
17522 // indicators due to overly aggressive smoothing...
17523 directional_cell_refinement_case =
17524 (directional_cell_refinement_case &
17527 expected_face_ref_case,
17528 face,
17529 cell->face_orientation(face),
17530 cell->face_flip(face),
17531 cell->face_rotation(face)));
17532 } // for both face indices
17533 // if both requirements sum up to something useful, add
17534 // this to the refine case for smoothing. note: if
17535 // directional_cell_refinement_case is isotropic still,
17536 // then something went wrong...
17537 Assert(directional_cell_refinement_case <
17540 smoothing_cell_refinement_case =
17541 smoothing_cell_refinement_case | directional_cell_refinement_case;
17542 } // for all face_pairs
17543 // no we collected contributions from all directions. combine
17544 // the new flags with the existing refine case, but only if
17545 // smoothing is required
17546 if (smoothing_cell_refinement_case)
17547 {
17548 cell->clear_coarsen_flag();
17549 cell->set_refine_flag(cell->refine_flag_set() |
17550 smoothing_cell_refinement_case);
17551 }
17552 }
17553 }
17554} // namespace
17555
17556#ifndef DOXYGEN
17557template <int dim, int spacedim>
17558DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
17560{
17561 // save the flags to determine whether something was changed in the
17562 // course of this function
17563 const auto coarsen_flags_before = internal::extract_raw_coarsen_flags(levels);
17564 const auto refine_flags_before = internal::extract_raw_refine_flags(levels);
17565
17566 // save the flags at the outset of each loop. we do so in order to
17567 // find out whether something was changed in the present loop, in
17568 // which case we would have to re-run the loop. the other
17569 // possibility to find this out would be to set a flag
17570 // @p{something_changed} to true each time we change something.
17571 // however, sometimes one change in one of the parts of the loop is
17572 // undone by another one, so we might end up in an endless loop. we
17573 // could be tempted to break this loop at an arbitrary number of
17574 // runs, but that would not be a clean solution, since we would
17575 // either have to 1/ break the loop too early, in which case the
17576 // promise that a second call to this function immediately after the
17577 // first one does not change anything, would be broken, or 2/ we do
17578 // as many loops as there are levels. we know that information is
17579 // transported over one level in each run of the loop, so this is
17580 // enough. Unfortunately, each loop is rather expensive, so we chose
17581 // the way presented here
17582 auto coarsen_flags_before_loop = coarsen_flags_before;
17583 auto refine_flags_before_loop = refine_flags_before;
17584
17585 // now for what is done in each loop: we have to fulfill several
17586 // tasks at the same time, namely several mesh smoothing algorithms
17587 // and mesh regularization, by which we mean that the next mesh
17588 // fulfills several requirements such as no double refinement at
17589 // each face or line, etc.
17590 //
17591 // since doing these things at once seems almost impossible (in the
17592 // first year of this library, they were done in two functions, one
17593 // for refinement and one for coarsening, and most things within
17594 // these were done at once, so the code was rather impossible to
17595 // join into this, only, function), we do them one after each
17596 // other. the order in which we do them is such that the important
17597 // tasks, namely regularization, are done last and the least
17598 // important things are done the first. the following order is
17599 // chosen:
17600 //
17601 // 0/ Only if coarsest_level_1 or patch_level_1 is set: clear all
17602 // coarsen flags on level 1 to avoid level 0 cells being created
17603 // by coarsening. As coarsen flags will never be added, this can
17604 // be done once and for all before the actual loop starts.
17605 //
17606 // 1/ do not coarsen a cell if 'most of the neighbors' will be
17607 // refined after the step. This is to prevent occurrence of
17608 // unrefined islands.
17609 //
17610 // 2/ eliminate refined islands in the interior and at the
17611 // boundary. since they don't do much harm besides increasing the
17612 // number of degrees of freedom, doing this has a rather low
17613 // priority.
17614 //
17615 // 3/ limit the level difference of neighboring cells at each
17616 // vertex.
17617 //
17618 // 4/ eliminate unrefined islands. this has higher priority since
17619 // this diminishes the approximation properties not only of the
17620 // unrefined island, but also of the surrounding patch.
17621 //
17622 // 5/ ensure patch level 1. Then the triangulation consists of
17623 // patches, i.e. of cells that are refined once. It follows that
17624 // if at least one of the children of a cell is or will be
17625 // refined than all children need to be refined. This step only
17626 // sets refinement flags and does not set coarsening flags. If
17627 // the patch_level_1 flag is set, then
17628 // eliminate_unrefined_islands, eliminate_refined_inner_islands
17629 // and eliminate_refined_boundary_islands will be fulfilled
17630 // automatically and do not need to be enforced separately.
17631 //
17632 // 6/ take care of the requirement that no double refinement is done
17633 // at each face
17634 //
17635 // 7/ take care that no double refinement is done at each line in 3d
17636 // or higher dimensions.
17637 //
17638 // 8/ make sure that all children of each cell are either flagged
17639 // for coarsening or none of the children is
17640 //
17641 // For some of these steps, it is known that they interact. Namely,
17642 // it is not possible to guarantee that after step 6 another step 5
17643 // would have no effect; the same holds for the opposite order and
17644 // also when taking into account step 7. however, it is important to
17645 // guarantee that step five or six do not undo something that step 5
17646 // did, and step 7 not something of step 6, otherwise the
17647 // requirements will not be satisfied even if the loop
17648 // terminates. this is accomplished by the fact that steps 5 and 6
17649 // only *add* refinement flags and delete coarsening flags
17650 // (therefore, step 6 can't undo something that step 4 already did),
17651 // and step 7 only deletes coarsening flags, never adds some. step 7
17652 // needs also take care that it won't tag cells for refinement for
17653 // which some neighbors are more refined or will be refined.
17654
17655 //------------------------------------
17656 // STEP 0:
17657 // Only if coarsest_level_1 or patch_level_1 is set: clear all
17658 // coarsen flags on level 1 to avoid level 0 cells being created
17659 // by coarsening.
17660 if (((smooth_grid & coarsest_level_1) || (smooth_grid & patch_level_1)) &&
17661 n_levels() >= 2)
17662 {
17663 for (const auto &cell : active_cell_iterators_on_level(1))
17664 cell->clear_coarsen_flag();
17665 }
17666
17667 bool mesh_changed_in_this_loop = false;
17668 do
17669 {
17670 //------------------------------------
17671 // STEP 1:
17672 // do not coarsen a cell if 'most of the neighbors' will be
17673 // refined after the step. This is to prevent the occurrence
17674 // of unrefined islands. If patch_level_1 is set, this will
17675 // be automatically fulfilled.
17676 if (smooth_grid & do_not_produce_unrefined_islands &&
17677 !(smooth_grid & patch_level_1))
17678 {
17679 for (const auto &cell : cell_iterators())
17680 {
17681 // only do something if this
17682 // cell will be coarsened
17683 if (!cell->is_active() && cell_will_be_coarsened(cell))
17684 possibly_do_not_produce_unrefined_islands<dim, spacedim>(cell);
17685 }
17686 }
17687
17688
17689 //------------------------------------
17690 // STEP 2:
17691 // eliminate refined islands in the interior and at the
17692 // boundary. since they don't do much harm besides increasing
17693 // the number of degrees of freedom, doing this has a rather
17694 // low priority. If patch_level_1 is set, this will be
17695 // automatically fulfilled.
17696 //
17697 // there is one corner case to consider: if this is a
17698 // distributed triangulation, there may be refined islands on
17699 // the boundary of which we own only part (e.g. a single cell
17700 // in the corner of a domain). the rest of the island is
17701 // ghost cells and it *looks* like the area around it
17702 // (artificial cells) are coarser but this is only because
17703 // they may actually be equally fine on other
17704 // processors. it's hard to detect this case but we can do
17705 // the following: only set coarsen flags to remove this
17706 // refined island if all cells we want to set flags on are
17707 // locally owned
17708 if (smooth_grid & (eliminate_refined_inner_islands |
17709 eliminate_refined_boundary_islands) &&
17710 !(smooth_grid & patch_level_1))
17711 {
17712 for (const auto &cell : cell_iterators())
17713 if (!cell->is_active() ||
17714 (cell->is_active() && cell->refine_flag_set() &&
17715 cell->is_locally_owned()))
17716 {
17717 // check whether all children are active, i.e. not
17718 // refined themselves. This is a precondition that the
17719 // children may be coarsened away. If the cell is only
17720 // flagged for refinement, then all future children
17721 // will be active
17722 bool all_children_active = true;
17723 if (!cell->is_active())
17724 for (unsigned int c = 0; c < cell->n_children(); ++c)
17725 if (!cell->child(c)->is_active() ||
17726 cell->child(c)->is_ghost() ||
17727 cell->child(c)->is_artificial())
17728 {
17729 all_children_active = false;
17730 break;
17731 }
17732
17733 if (all_children_active)
17734 {
17735 // count number of refined and unrefined neighbors
17736 // of cell. neighbors on lower levels are counted
17737 // as unrefined since they can only get to the
17738 // same level as this cell by the next refinement
17739 // cycle
17740 unsigned int unrefined_neighbors = 0, total_neighbors = 0;
17741
17742 // Keep track if this cell is at a periodic
17743 // boundary or not. TODO: We do not currently run
17744 // the algorithm for inner islands at a periodic
17745 // boundary (remains to be implemented), but we
17746 // also don't want to consider them
17747 // boundary_island cells as this can interfere
17748 // with 2:1 refinement across periodic faces.
17749 // Instead: just ignore those cells for this
17750 // smoothing operation below.
17751 bool at_periodic_boundary = false;
17752
17753 for (const unsigned int n : cell->face_indices())
17754 {
17755 const cell_iterator neighbor = cell->neighbor(n);
17756 if (neighbor.state() == IteratorState::valid)
17757 {
17758 ++total_neighbors;
17759
17760 if (!face_will_be_refined_by_neighbor(cell, n))
17761 ++unrefined_neighbors;
17762 }
17763 else if (cell->has_periodic_neighbor(n))
17764 {
17765 ++total_neighbors;
17766 at_periodic_boundary = true;
17767 }
17768 }
17769
17770 // if all neighbors unrefined: mark this cell for
17771 // coarsening or don't refine if marked for that
17772 //
17773 // also do the distinction between the two
17774 // versions of the eliminate_refined_*_islands
17775 // flag
17776 //
17777 // the last check is whether there are any
17778 // neighbors at all. if not so, then we are (e.g.)
17779 // on the coarsest grid with one cell, for which,
17780 // of course, we do not remove the refine flag.
17781 if ((unrefined_neighbors == total_neighbors) &&
17782 ((!cell->at_boundary() &&
17783 (smooth_grid & eliminate_refined_inner_islands)) ||
17784 (cell->at_boundary() && !at_periodic_boundary &&
17785 (smooth_grid &
17786 eliminate_refined_boundary_islands))) &&
17787 (total_neighbors != 0))
17788 {
17789 if (!cell->is_active())
17790 for (unsigned int c = 0; c < cell->n_children(); ++c)
17791 {
17792 cell->child(c)->clear_refine_flag();
17793 cell->child(c)->set_coarsen_flag();
17794 }
17795 else
17796 cell->clear_refine_flag();
17797 }
17798 }
17799 }
17800 }
17801
17802 //------------------------------------
17803 // STEP 3:
17804 // limit the level difference of neighboring cells at each
17805 // vertex.
17806 //
17807 // in case of anisotropic refinement this does not make
17808 // sense. as soon as one cell is anisotropically refined, an
17809 // Assertion is thrown. therefore we can ignore this problem
17810 // later on
17811 if (smooth_grid & limit_level_difference_at_vertices)
17812 {
17813 Assert(!anisotropic_refinement,
17814 ExcMessage("In case of anisotropic refinement the "
17815 "limit_level_difference_at_vertices flag for "
17816 "mesh smoothing must not be set!"));
17817
17818 // store highest level one of the cells adjacent to a vertex
17819 // belongs to
17820 std::vector<int> vertex_level(vertices.size(), 0);
17821 for (const auto &cell : active_cell_iterators())
17822 {
17823 if (cell->refine_flag_set())
17824 for (const unsigned int vertex : cell->vertex_indices())
17825 vertex_level[cell->vertex_index(vertex)] =
17826 std::max(vertex_level[cell->vertex_index(vertex)],
17827 cell->level() + 1);
17828 else if (!cell->coarsen_flag_set())
17829 for (const unsigned int vertex : cell->vertex_indices())
17830 vertex_level[cell->vertex_index(vertex)] =
17831 std::max(vertex_level[cell->vertex_index(vertex)],
17832 cell->level());
17833 else
17834 {
17835 // if coarsen flag is set then tentatively assume
17836 // that the cell will be coarsened. this isn't
17837 // always true (the coarsen flag could be removed
17838 // again) and so we may make an error here
17840 for (const unsigned int vertex : cell->vertex_indices())
17841 vertex_level[cell->vertex_index(vertex)] =
17842 std::max(vertex_level[cell->vertex_index(vertex)],
17843 cell->level() - 1);
17844 }
17845 }
17846
17847
17848 // loop over all cells in reverse order. do so because we
17849 // can then update the vertex levels on the adjacent
17850 // vertices and maybe already flag additional cells in this
17851 // loop
17852 //
17853 // note that not only may we have to add additional
17854 // refinement flags, but we will also have to remove
17855 // coarsening flags on cells adjacent to vertices that will
17856 // see refinement
17857 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17858 if (cell->refine_flag_set() == false)
17859 {
17860 for (const unsigned int vertex : cell->vertex_indices())
17861 if (vertex_level[cell->vertex_index(vertex)] >=
17862 cell->level() + 1)
17863 {
17864 // remove coarsen flag...
17865 cell->clear_coarsen_flag();
17866
17867 // ...and if necessary also refine the current
17868 // cell, at the same time updating the level
17869 // information about vertices
17870 if (vertex_level[cell->vertex_index(vertex)] >
17871 cell->level() + 1)
17872 {
17873 cell->set_refine_flag();
17874
17875 for (const unsigned int v : cell->vertex_indices())
17876 vertex_level[cell->vertex_index(v)] =
17877 std::max(vertex_level[cell->vertex_index(v)],
17878 cell->level() + 1);
17879 }
17880
17881 // continue and see whether we may, for example,
17882 // go into the inner'if'
17883 // above based on a
17884 // different vertex
17885 }
17886 }
17887 }
17888
17889 //-----------------------------------
17890 // STEP 4:
17891 // eliminate unrefined islands. this has higher priority
17892 // since this diminishes the approximation properties not
17893 // only of the unrefined island, but also of the surrounding
17894 // patch.
17895 //
17896 // do the loop from finest to coarsest cells since we may
17897 // trigger a cascade by marking cells for refinement which
17898 // may trigger more cells further down below
17899 if (smooth_grid & eliminate_unrefined_islands)
17900 {
17901 for (active_cell_iterator cell = last_active(); cell != end(); --cell)
17902 // only do something if cell is not already flagged for
17903 // (isotropic) refinement
17904 if (cell->refine_flag_set() !=
17906 possibly_refine_unrefined_island<dim, spacedim>(
17907 cell, (smooth_grid & allow_anisotropic_smoothing) != 0);
17908 }
17909
17910 //-------------------------------
17911 // STEP 5:
17912 // ensure patch level 1.
17913 //
17914 // Introduce some terminology:
17915 // - a cell that is refined
17916 // once is a patch of
17917 // level 1 simply called patch.
17918 // - a cell that is globally
17919 // refined twice is called
17920 // a patch of level 2.
17921 // - patch level n says that
17922 // the triangulation consists
17923 // of patches of level n.
17924 // This makes sense only
17925 // if the grid is already at
17926 // least n times globally
17927 // refined.
17928 //
17929 // E.g. from patch level 1 follows: if at least one of the
17930 // children of a cell is or will be refined than enforce all
17931 // children to be refined.
17932
17933 // This step 4 only sets refinement flags and does not set
17934 // coarsening flags.
17935 if (smooth_grid & patch_level_1)
17936 {
17937 // An important assumption (A) is that before calling this
17938 // function the grid was already of patch level 1.
17939
17940 // loop over all cells whose children are all active. (By
17941 // assumption (A) either all or none of the children are
17942 // active). If the refine flag of at least one of the
17943 // children is set then set_refine_flag and
17944 // clear_coarsen_flag of all children.
17945 for (const auto &cell : cell_iterators())
17946 if (!cell->is_active())
17947 {
17948 // ensure the invariant. we can then check whether all
17949 // of its children are further refined or not by
17950 // simply looking at the first child
17951 Assert(cell_is_patch_level_1(cell), ExcInternalError());
17952 if (cell->child(0)->has_children() == true)
17953 continue;
17954
17955 // cell is found to be a patch. combine the refine
17956 // cases of all children
17957 RefinementCase<dim> combined_ref_case =
17959 for (unsigned int i = 0; i < cell->n_children(); ++i)
17960 combined_ref_case =
17961 combined_ref_case | cell->child(i)->refine_flag_set();
17962 if (combined_ref_case != RefinementCase<dim>::no_refinement)
17963 for (unsigned int i = 0; i < cell->n_children(); ++i)
17964 {
17965 cell_iterator child = cell->child(i);
17966
17967 child->clear_coarsen_flag();
17968 child->set_refine_flag(combined_ref_case);
17969 }
17970 }
17971
17972 // The code above dealt with the case where we may get a
17973 // non-patch_level_1 mesh from refinement. Now also deal
17974 // with the case where we could get such a mesh by
17975 // coarsening. Coarsen the children (and remove the
17976 // grandchildren) only if all cell->grandchild(i)
17977 // ->coarsen_flag_set() are set.
17978 //
17979 // for a case where this is a bit tricky, take a look at the
17980 // mesh_smoothing_0[12] testcases
17981 for (const auto &cell : cell_iterators())
17982 {
17983 // check if this cell has active grandchildren. note
17984 // that we know that it is patch_level_1, i.e. if one of
17985 // its children is active then so are all, and it isn't
17986 // going to have any grandchildren at all:
17987 if (cell->is_active() || cell->child(0)->is_active())
17988 continue;
17989
17990 // cell is not active, and so are none of its
17991 // children. check the grandchildren. note that the
17992 // children are also patch_level_1, and so we only ever
17993 // need to check their first child
17994 const unsigned int n_children = cell->n_children();
17995 bool has_active_grandchildren = false;
17996
17997 for (unsigned int i = 0; i < n_children; ++i)
17998 if (cell->child(i)->child(0)->is_active())
17999 {
18000 has_active_grandchildren = true;
18001 break;
18002 }
18003
18004 if (has_active_grandchildren == false)
18005 continue;
18006
18007
18008 // ok, there are active grandchildren. see if either all
18009 // or none of them are flagged for coarsening
18010 unsigned int n_grandchildren = 0;
18011
18012 // count all coarsen flags of the grandchildren.
18013 unsigned int n_coarsen_flags = 0;
18014
18015 // cell is not a patch (of level 1) as it has a
18016 // grandchild. Is cell a patch of level 2?? Therefore:
18017 // find out whether all cell->child(i) are patches
18018 for (unsigned int c = 0; c < n_children; ++c)
18019 {
18020 // get at the child. by assumption (A), and the
18021 // check by which we got here, the child is not
18022 // active
18023 cell_iterator child = cell->child(c);
18024
18025 const unsigned int nn_children = child->n_children();
18026 n_grandchildren += nn_children;
18027
18028 // if child is found to be a patch of active cells
18029 // itself, then add up how many of its children are
18030 // supposed to be coarsened
18031 if (child->child(0)->is_active())
18032 for (unsigned int cc = 0; cc < nn_children; ++cc)
18033 if (child->child(cc)->coarsen_flag_set())
18034 ++n_coarsen_flags;
18035 }
18036
18037 // if not all grandchildren are supposed to be coarsened
18038 // (e.g. because some simply don't have the flag set, or
18039 // because they are not active and therefore cannot
18040 // carry the flag), then remove the coarsen flag from
18041 // all of the active grandchildren. note that there may
18042 // be coarsen flags on the grandgrandchildren -- we
18043 // don't clear them here, but we'll get to them in later
18044 // iterations if necessary
18045 //
18046 // there is nothing we have to do if no coarsen flags
18047 // have been set at all
18048 if ((n_coarsen_flags != n_grandchildren) && (n_coarsen_flags > 0))
18049 for (unsigned int c = 0; c < n_children; ++c)
18050 {
18051 const cell_iterator child = cell->child(c);
18052 if (child->child(0)->is_active())
18053 for (unsigned int cc = 0; cc < child->n_children(); ++cc)
18054 child->child(cc)->clear_coarsen_flag();
18055 }
18056 }
18057 }
18058
18059 //--------------------------------
18060 //
18061 // at the boundary we could end up with cells with negative
18062 // volume or at least with a part, that is negative, if the
18063 // cell is refined anisotropically. we have to check, whether
18064 // that can happen
18065 this->policy->prevent_distorted_boundary_cells(*this);
18066
18067 //-------------------------------
18068 // STEP 6:
18069 // take care of the requirement that no
18070 // double refinement is done at each face
18071 //
18072 // in case of anisotropic refinement it is only likely, but
18073 // not sure, that the cells, which are more refined along a
18074 // certain face common to two cells are on a higher
18075 // level. therefore we cannot be sure, that the requirement
18076 // of no double refinement is fulfilled after a single pass
18077 // of the following actions. We could just wait for the next
18078 // global loop. when this function terminates, the
18079 // requirement will be fulfilled. However, it might be faster
18080 // to insert an inner loop here.
18081 bool changed = true;
18082 while (changed)
18083 {
18084 changed = false;
18085 active_cell_iterator cell = last_active(), endc = end();
18086
18087 for (; cell != endc; --cell)
18088 if (cell->refine_flag_set())
18089 {
18090 // loop over neighbors of cell
18091 for (const auto i : cell->face_indices())
18092 {
18093 // only do something if the face is not at the
18094 // boundary and if the face will be refined with
18095 // the RefineCase currently flagged for
18096 const bool has_periodic_neighbor =
18097 cell->has_periodic_neighbor(i);
18098 const bool has_neighbor_or_periodic_neighbor =
18099 !cell->at_boundary(i) || has_periodic_neighbor;
18100 if (has_neighbor_or_periodic_neighbor &&
18102 cell->refine_flag_set(), i) !=
18104 {
18105 // 1) if the neighbor has children: nothing to
18106 // worry about. 2) if the neighbor is active
18107 // and a coarser one, ensure, that its
18108 // refine_flag is set 3) if the neighbor is
18109 // active and as refined along the face as our
18110 // current cell, make sure, that no
18111 // coarsen_flag is set. if we remove the
18112 // coarsen flag of our neighbor,
18113 // fix_coarsen_flags() makes sure, that the
18114 // mother cell will not be coarsened
18115 if (cell->neighbor_or_periodic_neighbor(i)->is_active())
18116 {
18117 if ((!has_periodic_neighbor &&
18118 cell->neighbor_is_coarser(i)) ||
18119 (has_periodic_neighbor &&
18120 cell->periodic_neighbor_is_coarser(i)))
18121 {
18122 if (cell->neighbor_or_periodic_neighbor(i)
18123 ->coarsen_flag_set())
18124 cell->neighbor_or_periodic_neighbor(i)
18125 ->clear_coarsen_flag();
18126 // we'll set the refine flag for this
18127 // neighbor below. we note, that we
18128 // have changed something by setting
18129 // the changed flag to true. We do not
18130 // need to do so, if we just removed
18131 // the coarsen flag, as the changed
18132 // flag only indicates the need to
18133 // re-run the inner loop. however, we
18134 // only loop over cells flagged for
18135 // refinement here, so nothing to
18136 // worry about if we remove coarsen
18137 // flags
18138
18139 if (dim == 2)
18140 {
18141 if (smooth_grid &
18142 allow_anisotropic_smoothing)
18143 changed =
18144 has_periodic_neighbor ?
18145 cell->periodic_neighbor(i)
18146 ->flag_for_face_refinement(
18147 cell
18148 ->periodic_neighbor_of_coarser_periodic_neighbor(
18149 i)
18150 .first,
18151 RefinementCase<dim - 1>::cut_x) :
18152 cell->neighbor(i)
18153 ->flag_for_face_refinement(
18154 cell
18155 ->neighbor_of_coarser_neighbor(
18156 i)
18157 .first,
18158 RefinementCase<dim - 1>::cut_x);
18159 else
18160 {
18161 if (!cell
18162 ->neighbor_or_periodic_neighbor(
18163 i)
18164 ->refine_flag_set())
18165 changed = true;
18166 cell->neighbor_or_periodic_neighbor(i)
18167 ->set_refine_flag();
18168 }
18169 }
18170 else // i.e. if (dim==3)
18171 {
18172 // ugly situations might arise here,
18173 // consider the following situation, which
18174 // shows neighboring cells at the common
18175 // face, where the upper right element is
18176 // coarser at the given face. Now the upper
18177 // child element of the lower left wants to
18178 // refine according to cut_z, such that
18179 // there is a 'horizontal' refinement of the
18180 // face marked with #####
18181 //
18182 // / /
18183 // / /
18184 // *---------------*
18185 // | |
18186 // | |
18187 // | |
18188 // | |
18189 // | |
18190 // | | /
18191 // | |/
18192 // *---------------*
18193 //
18194 //
18195 // *---------------*
18196 // /| /|
18197 // / | ##### / |
18198 // | |
18199 // *---------------*
18200 // /| /|
18201 // / | / |
18202 // | |
18203 // *---------------*
18204 // / /
18205 // / /
18206 //
18207 // this introduces too many hanging nodes
18208 // and the neighboring (coarser) cell (upper
18209 // right) has to be refined. If it is only
18210 // refined according to cut_z, then
18211 // everything is ok:
18212 //
18213 // / /
18214 // / /
18215 // *---------------*
18216 // | |
18217 // | | /
18218 // | |/
18219 // *---------------*
18220 // | |
18221 // | | /
18222 // | |/
18223 // *---------------*
18224 //
18225 //
18226 // *---------------*
18227 // /| /|
18228 // / *---------------*
18229 // /| /|
18230 // *---------------*
18231 // /| /|
18232 // / | / |
18233 // | |
18234 // *---------------*
18235 // / /
18236 // / /
18237 //
18238 // if however the cell wants to refine
18239 // itself in an other way, or if we disallow
18240 // anisotropic smoothing, then simply
18241 // refining the neighbor isotropically is
18242 // not going to work, since this introduces
18243 // a refinement of face ##### with both
18244 // cut_x and cut_y, which is not possible:
18245 //
18246 // / / /
18247 // / / /
18248 // *-------*-------*
18249 // | | |
18250 // | | | /
18251 // | | |/
18252 // *-------*-------*
18253 // | | |
18254 // | | | /
18255 // | | |/
18256 // *-------*-------*
18257 //
18258 //
18259 // *---------------*
18260 // /| /|
18261 // / *---------------*
18262 // /| /|
18263 // *---------------*
18264 // /| /|
18265 // / | / |
18266 // | |
18267 // *---------------*
18268 // / /
18269 // / /
18270 //
18271 // thus, in this case we also need to refine
18272 // our current cell in the new direction:
18273 //
18274 // / / /
18275 // / / /
18276 // *-------*-------*
18277 // | | |
18278 // | | | /
18279 // | | |/
18280 // *-------*-------*
18281 // | | |
18282 // | | | /
18283 // | | |/
18284 // *-------*-------*
18285 //
18286 //
18287 // *-------*-------*
18288 // /| /| /|
18289 // / *-------*-------*
18290 // /| /| /|
18291 // *-------*-------*
18292 // /| / /|
18293 // / | / |
18294 // | |
18295 // *---------------*
18296 // / /
18297 // / /
18298
18299 std::pair<unsigned int, unsigned int>
18300 nb_indices =
18301 has_periodic_neighbor ?
18302 cell
18303 ->periodic_neighbor_of_coarser_periodic_neighbor(
18304 i) :
18305 cell->neighbor_of_coarser_neighbor(i);
18306 unsigned int refined_along_x = 0,
18307 refined_along_y = 0,
18308 to_be_refined_along_x = 0,
18309 to_be_refined_along_y = 0;
18310
18311 const int this_face_index =
18312 cell->face_index(i);
18313
18314 // step 1: detect, along which axis the face
18315 // is currently refined
18316
18317 // first, we need an iterator pointing to
18318 // the parent face. This requires a slight
18319 // detour in case the neighbor is behind a
18320 // periodic face.
18321 const auto parent_face = [&]() {
18322 if (has_periodic_neighbor)
18323 {
18324 const auto neighbor =
18325 cell->periodic_neighbor(i);
18326 const auto parent_face_no =
18327 neighbor
18328 ->periodic_neighbor_of_periodic_neighbor(
18329 nb_indices.first);
18330 auto parent =
18331 neighbor->periodic_neighbor(
18332 nb_indices.first);
18333 return parent->face(parent_face_no);
18334 }
18335 else
18336 return cell->neighbor(i)->face(
18337 nb_indices.first);
18338 }();
18339
18340 if ((this_face_index ==
18341 parent_face->child_index(0)) ||
18342 (this_face_index ==
18343 parent_face->child_index(1)))
18344 {
18345 // this might be an
18346 // anisotropic child. get the
18347 // face refine case of the
18348 // neighbors face and count
18349 // refinements in x and y
18350 // direction.
18351 RefinementCase<dim - 1> frc =
18352 parent_face->refinement_case();
18353 if (frc & RefinementCase<dim>::cut_x)
18354 ++refined_along_x;
18355 if (frc & RefinementCase<dim>::cut_y)
18356 ++refined_along_y;
18357 }
18358 else
18359 // this has to be an isotropic
18360 // child
18361 {
18362 ++refined_along_x;
18363 ++refined_along_y;
18364 }
18365 // step 2: detect, along which axis the face
18366 // has to be refined given the current
18367 // refine flag
18368 RefinementCase<dim - 1> flagged_frc =
18370 cell->refine_flag_set(),
18371 i,
18372 cell->face_orientation(i),
18373 cell->face_flip(i),
18374 cell->face_rotation(i));
18375 if (flagged_frc &
18376 RefinementCase<dim>::cut_x)
18377 ++to_be_refined_along_x;
18378 if (flagged_frc &
18379 RefinementCase<dim>::cut_y)
18380 ++to_be_refined_along_y;
18381
18382 // step 3: set the refine flag of the
18383 // (coarser and active) neighbor.
18384 if ((smooth_grid &
18385 allow_anisotropic_smoothing) ||
18386 cell->neighbor_or_periodic_neighbor(i)
18387 ->refine_flag_set())
18388 {
18389 if (refined_along_x +
18390 to_be_refined_along_x >
18391 1)
18392 changed |=
18393 cell
18394 ->neighbor_or_periodic_neighbor(i)
18395 ->flag_for_face_refinement(
18396 nb_indices.first,
18397 RefinementCase<dim -
18398 1>::cut_axis(0));
18399 if (refined_along_y +
18400 to_be_refined_along_y >
18401 1)
18402 changed |=
18403 cell
18404 ->neighbor_or_periodic_neighbor(i)
18405 ->flag_for_face_refinement(
18406 nb_indices.first,
18407 RefinementCase<dim -
18408 1>::cut_axis(1));
18409 }
18410 else
18411 {
18412 if (cell
18413 ->neighbor_or_periodic_neighbor(i)
18414 ->refine_flag_set() !=
18415 RefinementCase<
18417 changed = true;
18418 cell->neighbor_or_periodic_neighbor(i)
18419 ->set_refine_flag();
18420 }
18421
18422 // step 4: if necessary (see above) add to
18423 // the refine flag of the current cell
18424 cell_iterator nb =
18425 cell->neighbor_or_periodic_neighbor(i);
18426 RefinementCase<dim - 1> nb_frc =
18428 nb->refine_flag_set(),
18429 nb_indices.first,
18430 nb->face_orientation(nb_indices.first),
18431 nb->face_flip(nb_indices.first),
18432 nb->face_rotation(nb_indices.first));
18433 if ((nb_frc & RefinementCase<dim>::cut_x) &&
18434 !((refined_along_x != 0u) ||
18435 (to_be_refined_along_x != 0u)))
18436 changed |= cell->flag_for_face_refinement(
18437 i,
18439 if ((nb_frc & RefinementCase<dim>::cut_y) &&
18440 !((refined_along_y != 0u) ||
18441 (to_be_refined_along_y != 0u)))
18442 changed |= cell->flag_for_face_refinement(
18443 i,
18445 }
18446 } // if neighbor is coarser
18447 else // -> now the neighbor is not coarser
18448 {
18449 cell->neighbor_or_periodic_neighbor(i)
18450 ->clear_coarsen_flag();
18451 const unsigned int nb_nb =
18452 has_periodic_neighbor ?
18453 cell
18454 ->periodic_neighbor_of_periodic_neighbor(
18455 i) :
18456 cell->neighbor_of_neighbor(i);
18457 const cell_iterator neighbor =
18458 cell->neighbor_or_periodic_neighbor(i);
18459 RefinementCase<dim - 1> face_ref_case =
18461 neighbor->refine_flag_set(),
18462 nb_nb,
18463 neighbor->face_orientation(nb_nb),
18464 neighbor->face_flip(nb_nb),
18465 neighbor->face_rotation(nb_nb));
18466 RefinementCase<dim - 1> needed_face_ref_case =
18468 cell->refine_flag_set(),
18469 i,
18470 cell->face_orientation(i),
18471 cell->face_flip(i),
18472 cell->face_rotation(i));
18473 // if the neighbor wants to refine the
18474 // face with cut_x and we want cut_y
18475 // or vice versa, we have to refine
18476 // isotropically at the given face
18477 if ((face_ref_case ==
18478 RefinementCase<dim>::cut_x &&
18479 needed_face_ref_case ==
18480 RefinementCase<dim>::cut_y) ||
18481 (face_ref_case ==
18482 RefinementCase<dim>::cut_y &&
18483 needed_face_ref_case ==
18484 RefinementCase<dim>::cut_x))
18485 {
18486 changed = cell->flag_for_face_refinement(
18487 i, face_ref_case);
18488 neighbor->flag_for_face_refinement(
18489 nb_nb, needed_face_ref_case);
18490 }
18491 }
18492 }
18493 else //-> the neighbor is not active
18494 {
18495 RefinementCase<dim - 1>
18496 face_ref_case = cell->face(i)->refinement_case(),
18497 needed_face_ref_case =
18499 cell->refine_flag_set(),
18500 i,
18501 cell->face_orientation(i),
18502 cell->face_flip(i),
18503 cell->face_rotation(i));
18504 // if the face is refined with cut_x and
18505 // we want cut_y or vice versa, we have to
18506 // refine isotropically at the given face
18507 if ((face_ref_case == RefinementCase<dim>::cut_x &&
18508 needed_face_ref_case ==
18509 RefinementCase<dim>::cut_y) ||
18510 (face_ref_case == RefinementCase<dim>::cut_y &&
18511 needed_face_ref_case ==
18512 RefinementCase<dim>::cut_x))
18513 changed =
18514 cell->flag_for_face_refinement(i,
18515 face_ref_case);
18516 }
18517 }
18518 }
18519 }
18520 }
18521
18522 //------------------------------------
18523 // STEP 7:
18524 // take care that no double refinement is done at each line in 3d or
18525 // higher dimensions.
18526 this->policy->prepare_refinement_dim_dependent(*this);
18527
18528 //------------------------------------
18529 // STEP 8:
18530 // make sure that all children of each cell are either flagged for
18531 // coarsening or none of the children is
18532 fix_coarsen_flags();
18533
18534 // get the refinement and coarsening flags
18535 auto coarsen_flags_after_loop =
18536 internal::extract_raw_coarsen_flags(levels);
18537 auto refine_flags_after_loop = internal::extract_raw_refine_flags(levels);
18538
18539 // find out whether something was changed in this loop
18540 mesh_changed_in_this_loop =
18541 ((coarsen_flags_before_loop != coarsen_flags_after_loop) ||
18542 (refine_flags_before_loop != refine_flags_after_loop));
18543
18544 // set the flags for the next loop already
18545 coarsen_flags_before_loop.swap(coarsen_flags_after_loop);
18546 refine_flags_before_loop.swap(refine_flags_after_loop);
18547 }
18548 while (mesh_changed_in_this_loop);
18549
18550
18551 // find out whether something was really changed in this
18552 // function. Note that @p{..._flags_before_loop} represents the state
18553 // after the last loop, i.e., the present state
18554 return ((coarsen_flags_before != coarsen_flags_before_loop) ||
18555 (refine_flags_before != refine_flags_before_loop));
18556}
18557
18558
18559
18560template <int dim, int spacedim>
18561DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
18563 const unsigned int magic_number1,
18564 const std::vector<bool> &v,
18565 const unsigned int magic_number2,
18566 std::ostream &out)
18567{
18568 const unsigned int N = v.size();
18569 unsigned char *flags = new unsigned char[N / 8 + 1];
18570 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18571 flags[i] = 0;
18572
18573 for (unsigned int position = 0; position < N; ++position)
18574 flags[position / 8] |= (v[position] ? (1 << (position % 8)) : 0);
18575
18576 AssertThrow(out.fail() == false, ExcIO());
18577
18578 // format:
18579 // 0. magic number
18580 // 1. number of flags
18581 // 2. the flags
18582 // 3. magic number
18583 out << magic_number1 << ' ' << N << std::endl;
18584 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18585 out << static_cast<unsigned int>(flags[i]) << ' ';
18586
18587 out << std::endl << magic_number2 << std::endl;
18588
18589 delete[] flags;
18590
18591 AssertThrow(out.fail() == false, ExcIO());
18592}
18593
18594
18595template <int dim, int spacedim>
18596DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
18598 const unsigned int magic_number1,
18599 std::vector<bool> &v,
18600 const unsigned int magic_number2,
18601 std::istream &in)
18602{
18603 AssertThrow(in.fail() == false, ExcIO());
18604
18605 unsigned int magic_number;
18606 in >> magic_number;
18607 AssertThrow(magic_number == magic_number1, ExcGridReadError());
18608
18609 unsigned int N;
18610 in >> N;
18611 v.resize(N);
18612
18613 unsigned char *flags = new unsigned char[N / 8 + 1];
18614 unsigned short int tmp;
18615 for (unsigned int i = 0; i < N / 8 + 1; ++i)
18616 {
18617 in >> tmp;
18618 flags[i] = tmp;
18619 }
18620
18621 for (unsigned int position = 0; position != N; ++position)
18622 v[position] = ((flags[position / 8] & (1 << (position % 8))) != 0);
18623
18624 in >> magic_number;
18625 AssertThrow(magic_number == magic_number2, ExcGridReadError());
18626
18627 delete[] flags;
18628
18629 AssertThrow(in.fail() == false, ExcIO());
18630}
18631
18632
18633
18634template <int dim, int spacedim>
18635DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
18637{
18638 std::size_t mem = 0;
18639 mem += sizeof(MeshSmoothing);
18640 mem += MemoryConsumption::memory_consumption(reference_cells);
18641 mem += MemoryConsumption::memory_consumption(periodic_face_pairs_level_0);
18643 for (const auto &level : levels)
18646 mem += MemoryConsumption::memory_consumption(vertices_used);
18647 mem += sizeof(default_flat_manifold) + sizeof(*default_flat_manifold);
18648 mem += sizeof(manifolds);
18649 mem += sizeof(smooth_grid);
18650 mem += MemoryConsumption::memory_consumption(number_cache);
18651 mem += sizeof(faces);
18652 if (faces)
18654
18655 return mem;
18656}
18657
18658
18659
18660template <int dim, int spacedim>
18661DEAL_II_CXX20_REQUIRES((concepts::is_valid_dim_spacedim<dim, spacedim>))
18663 default;
18664
18665#endif
18666
18667// explicit instantiations
18668#include "grid/tria.inst"
18669
*  iterator end()
*  *  const_iterator()=default
*  *  for(const auto &cell :triangulation.active_cell_iterators())
*  *  iterator begin()
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
Definition cell_status.h:38
@ children_will_be_coarsened
Definition cell_status.h:42
@ cell_will_persist
Definition cell_status.h:34
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
void set_neighbor(const unsigned int i, const TriaIterator< CellAccessor< dim, spacedim > > &pointer) const
TriaIterator< CellAccessor< dim, spacedim > > neighbor(const unsigned int face_no) const
boost::container::small_vector< TriaIterator< TriaAccessor< dim - 1, dim, spacedim > >, ReferenceCells::max_n_faces< dim >() > face_iterators() const
void set_direction_flag(const bool new_direction_flag) const
std::uint8_t refine_choice() const
RefinementCase< dim > refine_flag_set() const
bool flag_for_face_refinement(const unsigned int face_no, const RefinementCase< dim - 1 > &face_refinement_case=RefinementCase< dim - 1 >::isotropic_refinement) const
double diameter(const Mapping< dim, spacedim > &mapping) const
bool at_boundary(const unsigned int i) const
bool is_active() const
bool is_ghost() const
void set_subdomain_id(const types::subdomain_id new_subdomain_id) const
bool neighbor_is_coarser(const unsigned int face_no) const
TriaIterator< CellAccessor< dim, spacedim > > child(const unsigned int i) const
bool has_periodic_neighbor(const unsigned int i) const
void set_coarsen_flag() const
TriaIterator< TriaAccessor< dim - 1, dim, spacedim > > face(const unsigned int i) const
unsigned int neighbor_of_neighbor(const unsigned int face_no) const
void set_material_id(const types::material_id new_material_id) const
bool is_locally_owned() const
void set_refine_flag(const RefinementCase< dim > ref_case=RefinementCase< dim >::isotropic_refinement) const
void clear_coarsen_flag() const
void set_refine_choice(const std::uint8_t refinement_choice=static_cast< char >(IsotropicRefinementChoice::isotropic_refinement)) const
void set_parent(const unsigned int parent_index)
unsigned int active_cell_index() const
void clear_refine_flag() const
types::subdomain_id subdomain_id() const
bool direction_flag() const
types::material_id material_id() const
bool coarsen_flag_set() const
bool flag_for_line_refinement(const unsigned int line_no) const
CellId id() const
bool is_artificial() const
ArrayView< const std::uint8_t > get_child_indices() const
Definition cell_id.h:393
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
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) 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 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
static constexpr RefinementCase cut_axis(const unsigned int i)
constexpr void clear()
void join() const
const Triangulation< dim, spacedim > & get_triangulation() const
std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_indices() const
unsigned int line_index(const unsigned int i) const
unsigned int n_lines() const
unsigned int n_vertices() const
std_cxx20::ranges::iota_view< unsigned int, unsigned int > line_indices() const
void set_all_manifold_ids(const types::manifold_id manifold_ind) const
unsigned int n_children() const
std_cxx20::ranges::iota_view< unsigned int, unsigned int > face_indices() const
types::manifold_id manifold_id() const
unsigned int vertex_index(const unsigned int i) const
Point< spacedim > center(const bool respect_manifold=false, const bool interpolate_from_surrounding=false) const
ReferenceCell< structdim > reference_cell() const
void set_refinement_case(const RefinementCase< structdim > &ref_case) const
void set_bounding_object_indices(const std::initializer_list< int > &new_indices) const
Point< spacedim > & vertex(const unsigned int i) const
unsigned int quad_index(const unsigned int i) const
RefinementCase< structdim > refinement_case() const
typename::internal::TriangulationImplementation::Iterators< dim, spacedim >::line_iterator line(const unsigned int i) const
void set_children(const unsigned int i, const int index) const
IteratorState::IteratorStates state() const
virtual void add_periodicity(const std::vector< GridTools::PeriodicFacePair< cell_iterator > > &)
virtual types::global_cell_index n_global_active_cells() const
static constexpr unsigned int dimension
Definition tria.h:1811
quad_iterator begin_quad(const unsigned int level=0) const
active_vertex_iterator begin_active_vertex() const
void load_user_indices_quad(const std::vector< unsigned int > &v)
unsigned int n_quads() const
void load_user_indices(const std::vector< unsigned int > &v)
std::vector< bool > vertices_used
Definition tria.h:4613
bool anisotropic_refinement
Definition tria.h:4632
active_quad_iterator begin_active_quad(const unsigned int level=0) const
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:4690
void save_user_pointers_quad(std::vector< void * > &v) const
void save_user_flags_hex(std::ostream &out) const
void clear_user_flags_quad()
unsigned int n_faces() const
active_hex_iterator begin_active_hex(const unsigned int level=0) const
static void read_bool_vector(const unsigned int magic_number1, std::vector< bool > &v, const unsigned int magic_number2, std::istream &in)
bool all_reference_cells_are_hyper_cube() const
void load_user_flags_line(std::istream &in)
void clear_user_data()
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
void save_user_flags_line(std::ostream &out) const
active_cell_iterator last_active() const
void save(Archive &ar, const unsigned int version) const
void reset_global_cell_indices()
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces< dim > > faces
Definition tria.h:4602
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()
void save_user_pointers_line(std::vector< void * > &v) const
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
unsigned int n_raw_lines() const
virtual std::size_t memory_consumption() const
std::vector< Point< spacedim > > vertices
Definition tria.h:4608
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
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:4667
void load_user_flags_quad(std::istream &in)
unsigned int n_active_cells() const
void update_periodic_face_map()
void clear_despite_subscriptions()
Triangulation(const MeshSmoothing smooth_grid=none, const bool check_for_distorted_cells=false)
std::vector< ReferenceCell< dim > > reference_cells
Definition tria.h:4141
void save_user_flags(std::ostream &out) const
std::vector< std::unique_ptr< ::internal::TriangulationImplementation::TriaLevel< dim, spacedim > > > levels
Definition tria.h:4594
void load_user_flags_hex(std::istream &in)
void load_user_pointers_quad(const std::vector< void * > &v)
unsigned int n_used_vertices() const
void reset_cell_vertex_indices_cache()
unsigned int n_active_lines() const
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
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:4650
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:4213
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)
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
std::map< types::manifold_id, std::unique_ptr< const Manifold< dim, spacedim > > > manifolds
Definition tria.h:4619
MeshSmoothing smooth_grid
Definition tria.h:4135
std::unique_ptr< ::internal::TriangulationImplementation::Policy< dim, spacedim > > policy
Definition tria.h:4204
Triangulation< dim, spacedim > & get_triangulation()
void save_user_flags_quad(std::ostream &out) const
Signals signals
Definition tria.h:2602
std::map< std::pair< cell_iterator, unsigned int >, std::pair< std::pair< cell_iterator, unsigned int >, types::geometric_orientation > > periodic_face_map
Definition tria.h:4222
internal::TriangulationImplementation::Strides< dim > strides
Definition tria.h:4146
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
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
const std::vector< ReferenceCell< dim > > & get_reference_cells() const
void load_user_flags(std::istream &in)
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)
active_cell_iterator begin_active(const unsigned int level=0) const
void execute_coarsening()
void unpack_data(const std::vector< cell_relation_t > &cell_relations, const unsigned int handle, const std::function< void(const cell_iterator &, const CellStatus &, const boost::iterator_range< std::vector< char >::const_iterator > &)> &unpack_callback) const
Definition tria.cc:556
std::vector< char > dest_data_variable
Definition tria.h:603
std::vector< char > src_data_fixed
Definition tria.h:593
std::vector< char > dest_data_fixed
Definition tria.h:594
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:448
void pack_data(const std::vector< cell_relation_t > &cell_relations, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_fixed, const std::vector< typename internal::CellAttachedData< dim, spacedim >::pack_callback_t > &pack_callbacks_variable, const MPI_Comm &mpi_communicator)
Definition tria.cc:194
void load(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, const MPI_Comm &mpi_communicator)
Definition tria.cc:954
std::vector< int > src_sizes_variable
Definition tria.h:600
std::vector< unsigned int > sizes_fixed_cumulative
Definition tria.h:587
typename std::pair< cell_iterator, CellStatus > cell_relation_t
Definition tria.h:461
std::vector< int > dest_sizes_variable
Definition tria.h:601
std::vector< char > src_data_variable
Definition tria.h:602
void unpack_cell_status(std::vector< cell_relation_t > &cell_relations) const
Definition tria.cc:520
void save(const unsigned int global_first_cell, const unsigned int global_num_cells, const std::string &file_basename, const MPI_Comm &mpi_communicator) const
Definition tria.cc:723
void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2227
void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation) override
Definition tria.cc:2234
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:2210
void update_neighbors(Triangulation< dim, spacedim > &tria) override
Definition tria.cc:2204
bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell) override
Definition tria.cc:2241
Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells) override
Definition tria.cc:2220
std::unique_ptr< Policy< dim, spacedim > > clone() override
Definition tria.cc:2249
virtual std::unique_ptr< Policy< dim, spacedim > > clone()=0
virtual void update_neighbors(Triangulation< dim, spacedim > &tria)=0
virtual void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)=0
virtual void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &triangulation)=0
virtual Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)=0
virtual bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &cell)=0
virtual void delete_children(Triangulation< dim, spacedim > &triangulation, typename Triangulation< dim, spacedim >::cell_iterator &cell, std::vector< unsigned int > &line_cell_count, std::vector< unsigned int > &quad_cell_count)=0
std::vector< types::manifold_id > manifold_id
std::vector< BoundaryOrMaterialId > boundary_or_material_id
quad_iterator begin_quad(const unsigned int level=0) const
typename IteratorSelector::raw_line_iterator raw_line_iterator
Definition tria.h:4237
Triangulation & operator=(Triangulation< dim, spacedim > &&tria) noexcept
virtual const MeshSmoothing & get_mesh_smoothing() const
virtual void copy_triangulation(const Triangulation< dim, spacedim > &other_tria)
std::unique_ptr< std::map< unsigned int, types::manifold_id > > vertex_to_manifold_id_map_1d
Definition tria.h:4690
active_hex_iterator begin_active_hex(const unsigned int level=0) const
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_active_cell_index_partitioner() const
raw_hex_iterator begin_raw_hex(const unsigned int level=0) const
std::unique_ptr<::internal::TriangulationImplementation::TriaFaces< dim > > faces
Definition tria.h:4602
cell_iterator begin(const unsigned int level=0) const
TriaRawIterator< CellAccessor< dim, spacedim > > raw_cell_iterator
Definition tria.h:4232
raw_cell_iterator begin_raw(const unsigned int level=0) const
virtual void set_mesh_smoothing(const MeshSmoothing mesh_smoothing)
std::vector< Point< spacedim > > vertices
Definition tria.h:4608
raw_quad_iterator begin_raw_quad(const unsigned int level=0) const
virtual void create_triangulation(const std::vector< Point< spacedim > > &vertices, const std::vector< CellData< dim > > &cells, const SubCellData &subcelldata)
std::unique_ptr< std::map< unsigned int, types::boundary_id > > vertex_to_boundary_id_map_1d
Definition tria.h:4667
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:4141
void refine_global(const unsigned int times=1)
std::vector< std::unique_ptr< ::internal::TriangulationImplementation::TriaLevel< dim, spacedim > > > levels
Definition tria.h:4594
virtual std::weak_ptr< const Utilities::MPI::Partitioner > global_level_cell_index_partitioner(const unsigned int level) const
const std::vector< Point< spacedim > > & get_vertices() const
typename IteratorSelector::raw_quad_iterator raw_quad_iterator
Definition tria.h:4238
active_line_iterator begin_active_line(const unsigned int level=0) const
line_iterator begin_line(const unsigned int level=0) const
hex_iterator begin_hex(const unsigned int level=0) const
typename IteratorSelector::raw_hex_iterator raw_hex_iterator
Definition tria.h:4239
internal::TriangulationImplementation::Strides< dim > strides
Definition tria.h:4146
virtual std::vector< types::boundary_id > get_boundary_ids() const
void save_coarsen_flags(std::ostream &out) const
raw_line_iterator begin_raw_line(const unsigned int level=0) const
active_cell_iterator begin_active(const unsigned int level=0) const
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:246
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define AssertIsNotUsed(obj)
#define DEAL_II_ASSERT_UNREACHABLE()
#define DEAL_II_NOT_IMPLEMENTED()
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:1759
TriaIterator<::TriaAccessor< 0, dim, spacedim > > vertex_iterator
Definition tria.h:1687
typename IteratorSelector::active_quad_iterator active_quad_iterator
Definition tria.h:1750
TriaActiveIterator< TriaAccessor< dim - 1, dim, spacedim > > active_face_iterator
Definition tria.h:1676
TriaActiveIterator< CellAccessor< dim, spacedim > > active_cell_iterator
Definition tria.h:1648
typename IteratorSelector::active_hex_iterator active_hex_iterator
Definition tria.h:1770
typename IteratorSelector::quad_iterator quad_iterator
Definition tria.h:1735
typename IteratorSelector::line_iterator line_iterator
Definition tria.h:1711
typename IteratorSelector::active_line_iterator active_line_iterator
Definition tria.h:1726
TriaIterator< TriaAccessor< dim - 1, dim, spacedim > > face_iterator
Definition tria.h:1663
TriaActiveIterator<::TriaAccessor< 0, dim, spacedim > > active_vertex_iterator
Definition tria.h:1701
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
Definition tria.h:1624
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 set_all_manifold_ids(const types::manifold_id number)
void set_manifold_id(const types::manifold_id) const
bool face_rotation(const unsigned int face) const
bool face_orientation(const unsigned int face) const
types::geometric_orientation combined_face_orientation(const unsigned int face) const
void set_combined_face_orientation(const unsigned int face_no, const types::geometric_orientation combined_orientation) const
bool face_flip(const unsigned int face) const
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
const Mapping< dim, spacedim > & get_default_linear_mapping(const Triangulation< dim, spacedim > &triangulation)
Definition mapping.cc:314
void create_triangulation(Triangulation< dim, dim > &tria, const AdditionalData &additional_data=AdditionalData())
void reference_cell(Triangulation< dim, spacedim > &tria, const ReferenceCell< dim > &reference_cell)
void extract_vertices_without_cache(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const ArrayView< unsigned int > &vertex_indices)
std::vector< std::set< typename Triangulation< dim, spacedim >::active_cell_iterator > > vertex_to_cell_map(const Triangulation< dim, spacedim > &triangulation)
double cell_measure(const std::vector< Point< dim > > &all_vertices, const ArrayView< const unsigned int > &vertex_indices)
@ valid
Iterator points to a valid object.
constexpr char N
std::enable_if_t< std::is_fundamental_v< T >, std::size_t > memory_consumption(const T &t)
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
Tensor< 2, dim, Number > l(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
constexpr unsigned int max_n_children()
constexpr ReferenceCell< 3 > Hexahedron
constexpr ReferenceCell< 2 > Quadrilateral
ReferenceCell< dim > n_vertices_to_reference_cell(const unsigned int n_vertices)
constexpr ReferenceCell< 1 > Line
constexpr ReferenceCell< 2 > Triangle
constexpr unsigned int max_n_vertices()
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
T unpack(const std::vector< char > &buffer, const bool allow_compression=true)
Definition utilities.h:1509
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:2589
ArrayOfArrays determine_neighbors(const ArrayOfArrays &cells_to_faces)
Definition tria.cc:2514
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:2980
unsigned int n_active_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:15824
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:2805
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:2865
unsigned int n_cells(const internal::TriangulationImplementation::NumberCache< 1 > &c)
Definition tria.cc:15817
void monitor_memory(const TriaLevel< dim, spacedim > &tria_level, const unsigned int true_dimension)
Definition tria.cc:2073
std::tuple< bool, bool, bool > split_face_orientation(const types::geometric_orientation combined_orientation)
constexpr std::uint8_t max_n_levels
Definition types.h:423
constexpr unsigned int invalid_unsigned_int
Definition types.h:236
constexpr types::boundary_id internal_face_boundary_id
Definition types.h:327
constexpr types::manifold_id flat_manifold_id
Definition types.h:340
constexpr types::geometric_orientation reverse_line_orientation
Definition types.h:363
constexpr types::subdomain_id invalid_subdomain_id
Definition types.h:393
constexpr types::geometric_orientation default_geometric_orientation
Definition types.h:350
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 boundary_id
Definition types.h:159
unsigned int subdomain_id
Definition types.h:50
global_cell_index coarse_cell_id
Definition types.h:145
unsigned int manifold_id
Definition types.h:171
std::uint8_t geometric_orientation
Definition types.h:38
unsigned int global_cell_index
Definition types.h:136
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 unsigned int standard_to_real_face_vertex(const unsigned int vertex, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false)
static constexpr unsigned int max_children_per_face
static constexpr unsigned int vertices_per_cell
static constexpr unsigned int lines_per_cell
static constexpr unsigned int faces_per_cell
static unsigned int standard_to_real_face_line(const unsigned int line, 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< 1 > line_refinement_case(const RefinementCase< dim > &cell_refinement_case, const unsigned int line_no)
static unsigned int line_to_cell_vertices(const unsigned int line, const unsigned int vertex)
static std_cxx20::ranges::iota_view< unsigned int, unsigned int > vertex_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:1805
boost::signals2::signal< void(const Triangulation< dim, spacedim > &destination_tria)> copy
Definition tria.h:2448
ArrayView< const unsigned int > operator[](const unsigned int i) const
Definition tria.cc:2322
ArrayOfArrays & operator=(ArrayOfArrays &&)=default
ArrayOfArrays(const std::vector< std::size_t > &offsets, const std::vector< unsigned int > &columns)
Definition tria.cc:2281
ArrayOfArrays & operator=(const ArrayOfArrays &)=default
ArrayOfArrays(std::vector< std::size_t > &&offsets, std::vector< unsigned int > &&columns)
Definition tria.cc:2291
const ArrayOfArrays & entity_to_entities(const unsigned int from, const unsigned int to) const
Definition tria.cc:2466
Connectivity(const std::vector< ReferenceCell< dim > > &cell_types, const std::set< ReferenceCell< dim > > &all_reference_cells)
Definition tria.cc:2375
std::vector< ReferenceCell< structdim > > & entity_types()
Definition tria.cc:2416
std::set< ReferenceCell< dim > > all_reference_cells_
Definition tria.cc:2487
std::vector< types::geometric_orientation > line_orientation
Definition tria.cc:2491
const std::vector< ReferenceCell< structdim > > & entity_types() const
Definition tria.cc:2432
std::vector< ReferenceCell< 2 > > quad_types
Definition tria.cc:2501
ArrayOfArrays & entity_to_entities(const unsigned int from, const unsigned int to)
Definition tria.cc:2447
const std::set< ReferenceCell< dim > > & all_reference_cells() const
Definition tria.cc:2387
std::vector< types::geometric_orientation > & entity_orientations(const unsigned int structdim)
Definition tria.cc:2393
const std::vector< types::geometric_orientation > & entity_orientations(const unsigned int structdim) const
Definition tria.cc:2404
std::vector< types::geometric_orientation > quad_orientation
Definition tria.cc:2496
std::vector< ReferenceCell< dim > > cell_types
Definition tria.cc:2485
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:12737
static void prevent_distorted_boundary_cells(Triangulation< dim, spacedim > &)
Definition tria.cc:12827
static Triangulation< dim, spacedim >::DistortedCellList execute_refinement(Triangulation< dim, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:12818
static bool coarsening_allowed(const typename Triangulation< dim, spacedim >::cell_iterator &)
Definition tria.cc:12843
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12741
static void prepare_refinement_dim_dependent(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:12835
static void delete_children(Triangulation< dim, spacedim > &, typename Triangulation< dim, spacedim >::cell_iterator &, std::vector< unsigned int > &, std::vector< unsigned int > &)
Definition tria.cc:12807
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:3332
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:3979
static void update_neighbors(Triangulation< dim, spacedim > &triangulation)
Definition tria.cc:3560
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:4349
static void update_neighbors(Triangulation< 1, spacedim > &)
Definition tria.cc:3554
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:3532
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:4978
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:5350
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:3439
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:5361
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:4107
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:4211
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:3244
static Triangulation< 1, spacedim >::DistortedCellList execute_refinement(Triangulation< 1, spacedim > &triangulation, const bool)
Definition tria.cc:5841
static Triangulation< 3, spacedim >::DistortedCellList execute_refinement_isotropic(Triangulation< 3, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:6388
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:3703
static Triangulation< 2, spacedim >::DistortedCellList execute_refinement(Triangulation< 2, spacedim > &triangulation, const bool check_for_distorted_cells)
Definition tria.cc:6076
std::shared_ptr< const Utilities::MPI::Partitioner > active_cell_index_partitioner
Definition tria.h:188
std::vector< unsigned int > n_active_lines_level
Definition tria.h:182
std::vector< std::shared_ptr< const Utilities::MPI::Partitioner > > level_cell_index_partitioners
Definition tria.h:194
std::vector< unsigned int > n_active_quads_level
Definition tria.h:252
std::vector< unsigned int > n_active_hexes_level
Definition tria.h:311
Strides of various arrays in a Triangulation.
Definition tria.h:356
std::list< typename Triangulation< dim, spacedim >::cell_iterator > distorted_cells
Definition tria.h:1805
boost::signals2::signal< void(const typename Triangulation< dim, spacedim >::cell_iterator &cell)> post_refinement_on_cell
Definition tria.h:2438